diff options
Diffstat (limited to 'src/extra/ipv6.c')
-rw-r--r-- | src/extra/ipv6.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/src/extra/ipv6.c b/src/extra/ipv6.c index 6e8820c..fd8ebc4 100644 --- a/src/extra/ipv6.c +++ b/src/extra/ipv6.c @@ -15,6 +15,7 @@ #include <arpa/inet.h> #include <netinet/ip6.h> +#include <linux/netfilter/nfnetlink_queue.h> #include <libnetfilter_queue/libnetfilter_queue.h> #include <libnetfilter_queue/libnetfilter_queue_ipv6.h> #include <libnetfilter_queue/pktbuff.h> @@ -23,6 +24,17 @@ /** * \defgroup ipv6 IPv6 helper functions + * + * \manonly +.SH SYNOPSIS +.nf +\fB +#include <arpa/inet.h> +#include <linux/netfilter/nfnetlink_queue.h> +#include <libnetfilter_queue/libnetfilter_queue.h> +#include <libnetfilter_queue/libnetfilter_queue_ipv6.h> +\endmanonly + * * @{ */ @@ -36,7 +48,7 @@ EXPORT_SYMBOL struct ip6_hdr *nfq_ip6_get_hdr(struct pkt_buff *pktb) { struct ip6_hdr *ip6h; - unsigned int pktlen = pktb->tail - pktb->network_header; + unsigned int pktlen = pktb_tail(pktb) - pktb->network_header; /* Not enough room for IPv6 header. */ if (pktlen < sizeof(struct ip6_hdr)) @@ -67,17 +79,26 @@ int nfq_ip6_set_transport_header(struct pkt_buff *pktb, struct ip6_hdr *ip6h, uint8_t nexthdr = ip6h->ip6_nxt; uint8_t *cur = (uint8_t *)ip6h + sizeof(struct ip6_hdr); - while (nexthdr != target) { + while (nexthdr == IPPROTO_HOPOPTS || + nexthdr == IPPROTO_ROUTING || + nexthdr == IPPROTO_FRAGMENT || + nexthdr == IPPROTO_AH || + nexthdr == IPPROTO_NONE || + nexthdr == IPPROTO_DSTOPTS) { struct ip6_ext *ip6_ext; uint32_t hdrlen; + /* Extension header was requested, we're done. */ + if (nexthdr == target) + break; + /* No more extensions, we're done. */ if (nexthdr == IPPROTO_NONE) { cur = NULL; break; } /* No room for extension, bad packet. */ - if (pktb->tail - cur < sizeof(struct ip6_ext)) { + if (pktb_tail(pktb) - cur < sizeof(struct ip6_ext)) { cur = NULL; break; } @@ -87,16 +108,16 @@ int nfq_ip6_set_transport_header(struct pkt_buff *pktb, struct ip6_hdr *ip6h, uint16_t *frag_off; /* No room for full fragment header, bad packet. */ - if (pktb->tail - cur < sizeof(struct ip6_frag)) { + if (pktb_tail(pktb) - cur < sizeof(struct ip6_frag)) { cur = NULL; break; } - frag_off = (uint16_t *)cur + - offsetof(struct ip6_frag, ip6f_offlg); + frag_off = (uint16_t *)(cur + + offsetof(struct ip6_frag, ip6f_offlg)); /* Fragment offset is only 13 bits long. */ - if (htons(*frag_off & ~0x7)) { + if (htons(*frag_off) & ~0x7) { /* Not the first fragment, it does not contain * any headers. */ @@ -107,11 +128,13 @@ int nfq_ip6_set_transport_header(struct pkt_buff *pktb, struct ip6_hdr *ip6h, } else if (nexthdr == IPPROTO_AH) hdrlen = (ip6_ext->ip6e_len + 2) << 2; else - hdrlen = ip6_ext->ip6e_len; + hdrlen = (ip6_ext->ip6e_len + 1) << 3; nexthdr = ip6_ext->ip6e_nxt; cur += hdrlen; } + if (nexthdr != target) + cur = NULL; pktb->transport_header = cur; return cur ? 1 : 0; } @@ -140,7 +163,7 @@ int nfq_ip6_mangle(struct pkt_buff *pktb, unsigned int dataoff, /* Fix IPv6 hdr length information */ ip6h->ip6_plen = - htons(pktb->tail - pktb->network_header - sizeof *ip6h); + htons(pktb_tail(pktb) - pktb->network_header - sizeof *ip6h); return 1; } |