X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Fnetfilter%2Fip6t_dst.c;h=9422413d0571c3e7698c3546c483778608b72b4b;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=540925e4a7a80161f87757e82d640938f7e90e9d;hpb=cee37fe97739d85991964371c1f3a745c00dd236;p=linux-2.6.git diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c index 540925e4a..9422413d0 100644 --- a/net/ipv6/netfilter/ip6t_dst.c +++ b/net/ipv6/netfilter/ip6t_dst.c @@ -36,157 +36,83 @@ MODULE_AUTHOR("Andras Kis-Szabo "); #endif /* - * (Type & 0xC0) >> 6 - * 0 -> ignorable - * 1 -> must drop the packet - * 2 -> send ICMP PARM PROB regardless and drop packet - * 3 -> Send ICMP if not a multicast address and drop packet + * (Type & 0xC0) >> 6 + * 0 -> ignorable + * 1 -> must drop the packet + * 2 -> send ICMP PARM PROB regardless and drop packet + * 3 -> Send ICMP if not a multicast address and drop packet * (Type & 0x20) >> 5 - * 0 -> invariant - * 1 -> can change the routing + * 0 -> invariant + * 1 -> can change the routing * (Type & 0x1F) Type - * 0 -> Pad1 (only 1 byte!) - * 1 -> PadN LENGTH info (total length = length + 2) - * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k ) - * 5 -> RTALERT 2 x x + * 0 -> Pad1 (only 1 byte!) + * 1 -> PadN LENGTH info (total length = length + 2) + * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k ) + * 5 -> RTALERT 2 x x */ static int match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, + const struct xt_match *match, const void *matchinfo, int offset, unsigned int protoff, int *hotdrop) { - struct ipv6_opt_hdr _optsh, *oh; - const struct ip6t_opts *optinfo = matchinfo; - unsigned int temp; - unsigned int len; - u8 nexthdr; - unsigned int ptr; - unsigned int hdrlen = 0; - unsigned int ret = 0; - u8 _opttype, *tp = NULL; - u8 _optlen, *lp = NULL; - unsigned int optlen; - - /* type of the 1st exthdr */ - nexthdr = skb->nh.ipv6h->nexthdr; - /* pointer to the 1st exthdr */ - ptr = sizeof(struct ipv6hdr); - /* available length */ - len = skb->len - ptr; - temp = 0; + struct ipv6_opt_hdr _optsh, *oh; + const struct ip6t_opts *optinfo = matchinfo; + unsigned int temp; + unsigned int ptr; + unsigned int hdrlen = 0; + unsigned int ret = 0; + u8 _opttype, *tp = NULL; + u8 _optlen, *lp = NULL; + unsigned int optlen; - while (ip6t_ext_hdr(nexthdr)) { - struct ipv6_opt_hdr _hdr, *hp; - - DEBUGP("ipv6_opts header iteration \n"); - - /* Is there enough space for the next ext header? */ - if (len < (int)sizeof(struct ipv6_opt_hdr)) - return 0; - /* No more exthdr -> evaluate */ - if (nexthdr == NEXTHDR_NONE) { - break; - } - /* ESP -> evaluate */ - if (nexthdr == NEXTHDR_ESP) { - break; - } - - hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); - BUG_ON(hp == NULL); - - /* Calculate the header length */ - if (nexthdr == NEXTHDR_FRAGMENT) { - hdrlen = 8; - } else if (nexthdr == NEXTHDR_AUTH) - hdrlen = (hp->hdrlen+2)<<2; - else - hdrlen = ipv6_optlen(hp); - - /* OPTS -> evaluate */ -#if HOPBYHOP - if (nexthdr == NEXTHDR_HOP) { - temp |= MASK_HOPOPTS; -#else - if (nexthdr == NEXTHDR_DEST) { - temp |= MASK_DSTOPTS; -#endif - break; - } - - - /* set the flag */ - switch (nexthdr){ - case NEXTHDR_HOP: - case NEXTHDR_ROUTING: - case NEXTHDR_FRAGMENT: - case NEXTHDR_AUTH: - case NEXTHDR_DEST: - break; - default: - DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr); - return 0; - break; - } - - nexthdr = hp->nexthdr; - len -= hdrlen; - ptr += hdrlen; - if ( ptr > skb->len ) { - DEBUGP("ipv6_opts: new pointer is too large! \n"); - break; - } - } - - /* OPTIONS header not found */ #if HOPBYHOP - if ( temp != MASK_HOPOPTS ) return 0; + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0) #else - if ( temp != MASK_DSTOPTS ) return 0; + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST, NULL) < 0) #endif + return 0; - if (len < (int)sizeof(struct ipv6_opt_hdr)){ - *hotdrop = 1; - return 0; - } - - if (len < hdrlen){ - /* Packet smaller than it's length field */ - return 0; - } + oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); + if (oh == NULL) { + *hotdrop = 1; + return 0; + } - oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); - BUG_ON(oh == NULL); + hdrlen = ipv6_optlen(oh); + if (skb->len - ptr < hdrlen) { + /* Packet smaller than it's length field */ + return 0; + } - DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); + DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); - DEBUGP("len %02X %04X %02X ", - optinfo->hdrlen, hdrlen, - (!(optinfo->flags & IP6T_OPTS_LEN) || - ((optinfo->hdrlen == hdrlen) ^ - !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); + DEBUGP("len %02X %04X %02X ", + optinfo->hdrlen, hdrlen, + (!(optinfo->flags & IP6T_OPTS_LEN) || + ((optinfo->hdrlen == hdrlen) ^ + !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); - ret = (oh != NULL) - && - (!(optinfo->flags & IP6T_OPTS_LEN) || - ((optinfo->hdrlen == hdrlen) ^ - !!(optinfo->invflags & IP6T_OPTS_INV_LEN))); + ret = (oh != NULL) && + (!(optinfo->flags & IP6T_OPTS_LEN) || + ((optinfo->hdrlen == hdrlen) ^ + !!(optinfo->invflags & IP6T_OPTS_INV_LEN))); - ptr += 2; - hdrlen -= 2; - if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){ - return ret; + ptr += 2; + hdrlen -= 2; + if (!(optinfo->flags & IP6T_OPTS_OPTS)) { + return ret; } else if (optinfo->flags & IP6T_OPTS_NSTRICT) { DEBUGP("Not strict - not implemented"); } else { DEBUGP("Strict "); - DEBUGP("#%d ",optinfo->optsnr); - for(temp=0; tempoptsnr; temp++){ + DEBUGP("#%d ", optinfo->optsnr); + for (temp = 0; temp < optinfo->optsnr; temp++) { /* type field exists ? */ if (hdrlen < 1) break; @@ -196,10 +122,10 @@ match(const struct sk_buff *skb, break; /* Type check */ - if (*tp != (optinfo->opts[temp] & 0xFF00)>>8){ + if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) { DEBUGP("Tbad %02X %02X\n", *tp, - (optinfo->opts[temp] & 0xFF00)>>8); + (optinfo->opts[temp] & 0xFF00) >> 8); return 0; } else { DEBUGP("Tok "); @@ -243,7 +169,8 @@ match(const struct sk_buff *skb, } if (temp == optinfo->optsnr) return ret; - else return 0; + else + return 0; } return 0; @@ -252,25 +179,19 @@ match(const struct sk_buff *skb, /* Called when user tries to insert an entry of this type. */ static int checkentry(const char *tablename, - const struct ip6t_ip6 *ip, - void *matchinfo, - unsigned int matchinfosize, - unsigned int hook_mask) + const void *info, + const struct xt_match *match, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask) { - const struct ip6t_opts *optsinfo = matchinfo; + const struct ip6t_opts *optsinfo = matchinfo; - if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) { - DEBUGP("ip6t_opts: matchsize %u != %u\n", - matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts))); - return 0; - } - if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { - DEBUGP("ip6t_opts: unknown flags %X\n", - optsinfo->invflags); - return 0; - } - - return 1; + if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { + DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags); + return 0; + } + return 1; } static struct ip6t_match opts_match = { @@ -279,20 +200,21 @@ static struct ip6t_match opts_match = { #else .name = "dst", #endif - .match = &match, - .checkentry = &checkentry, + .match = match, + .matchsize = sizeof(struct ip6t_opts), + .checkentry = checkentry, .me = THIS_MODULE, }; -static int __init init(void) +static int __init ip6t_dst_init(void) { - return ip6t_register_match(&opts_match); + return ip6t_register_match(&opts_match); } -static void __exit cleanup(void) +static void __exit ip6t_dst_fini(void) { - ip6t_unregister_match(&opts_match); + ip6t_unregister_match(&opts_match); } -module_init(init); -module_exit(cleanup); +module_init(ip6t_dst_init); +module_exit(ip6t_dst_fini);