X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Fnetfilter%2Fip6t_rt.c;h=a9526b773d284d1e9fca90aa719ddd26d2c22866;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=f444ed920668c3bb9d29225216c05f5f079360e0;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index f444ed920..a9526b773 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c @@ -47,11 +47,10 @@ match(const struct sk_buff *skb, const struct net_device *out, const void *matchinfo, int offset, - const void *protohdr, - u_int16_t datalen, + unsigned int protoff, int *hotdrop) { - struct ipv6_rt_hdr *route = NULL; + struct ipv6_rt_hdr _route, *rh = NULL; const struct ip6t_rt *rtinfo = matchinfo; unsigned int temp; unsigned int len; @@ -59,6 +58,7 @@ match(const struct sk_buff *skb, unsigned int ptr; unsigned int hdrlen = 0; unsigned int ret = 0; + struct in6_addr *ap, _addr; /* type of the 1st exthdr */ nexthdr = skb->nh.ipv6h->nexthdr; @@ -69,7 +69,7 @@ match(const struct sk_buff *skb, temp = 0; while (ip6t_ext_hdr(nexthdr)) { - struct ipv6_opt_hdr *hdr; + struct ipv6_opt_hdr _hdr, *hp; DEBUGP("ipv6_rt header iteration \n"); @@ -85,15 +85,16 @@ match(const struct sk_buff *skb, break; } - hdr=(struct ipv6_opt_hdr *)skb->data+ptr; + 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 = (hdr->hdrlen+2)<<2; + hdrlen = (hp->hdrlen+2)<<2; else - hdrlen = ipv6_optlen(hdr); + hdrlen = ipv6_optlen(hp); /* ROUTING -> evaluate */ if (nexthdr == NEXTHDR_ROUTING) { @@ -116,7 +117,7 @@ match(const struct sk_buff *skb, break; } - nexthdr = hdr->nexthdr; + nexthdr = hp->nexthdr; len -= hdrlen; ptr += hdrlen; if ( ptr > skb->len ) { @@ -138,20 +139,21 @@ match(const struct sk_buff *skb, return 0; } - route = (struct ipv6_rt_hdr *) (skb->data + ptr); + rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); + BUG_ON(rh == NULL); - DEBUGP("IPv6 RT LEN %u %u ", hdrlen, route->hdrlen); - DEBUGP("TYPE %04X ", route->type); - DEBUGP("SGS_LEFT %u %08X\n", ntohl(route->segments_left), ntohl(route->segments_left)); + DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); + DEBUGP("TYPE %04X ", rh->type); + DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); DEBUGP("IPv6 RT segsleft %02X ", (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], - ntohl(route->segments_left), + rh->segments_left, !!(rtinfo->invflags & IP6T_RT_INV_SGS)))); DEBUGP("type %02X %02X %02X ", - rtinfo->rt_type, route->type, + rtinfo->rt_type, rh->type, (!(rtinfo->flags & IP6T_RT_TYP) || - ((rtinfo->rt_type == route->type) ^ + ((rtinfo->rt_type == rh->type) ^ !!(rtinfo->invflags & IP6T_RT_INV_TYP)))); DEBUGP("len %02X %04X %02X ", rtinfo->hdrlen, hdrlen, @@ -159,13 +161,13 @@ match(const struct sk_buff *skb, ((rtinfo->hdrlen == hdrlen) ^ !!(rtinfo->invflags & IP6T_RT_INV_LEN)))); DEBUGP("res %02X %02X %02X ", - (rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)route)->bitmap, - !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)route)->bitmap))); + (rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)rh)->bitmap, + !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)rh)->bitmap))); - ret = (route != NULL) + ret = (rh != NULL) && (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], - ntohl(route->segments_left), + rh->segments_left, !!(rtinfo->invflags & IP6T_RT_INV_SGS))) && (!(rtinfo->flags & IP6T_RT_LEN) || @@ -173,13 +175,19 @@ match(const struct sk_buff *skb, !!(rtinfo->invflags & IP6T_RT_INV_LEN))) && (!(rtinfo->flags & IP6T_RT_TYP) || - ((rtinfo->rt_type == route->type) ^ - !!(rtinfo->invflags & IP6T_RT_INV_TYP))) - && - !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)route)->bitmap)); + ((rtinfo->rt_type == rh->type) ^ + !!(rtinfo->invflags & IP6T_RT_INV_TYP))); + + if (ret && (rtinfo->flags & IP6T_RT_RES)) { + u_int32_t *bp, _bitmap; + bp = skb_header_pointer(skb, + ptr + offsetof(struct rt0_hdr, bitmap), + sizeof(_bitmap), &_bitmap); + + ret = (*bp == 0); + } DEBUGP("#%d ",rtinfo->addrnr); - temp = len = ptr = 0; if ( !(rtinfo->flags & IP6T_RT_FST) ){ return ret; } else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) { @@ -188,32 +196,27 @@ match(const struct sk_buff *skb, DEBUGP("There isn't enough space\n"); return 0; } else { + unsigned int i = 0; + DEBUGP("#%d ",rtinfo->addrnr); - ptr = 0; for(temp=0; temp<(unsigned int)((hdrlen-8)/16); temp++){ - len = 0; - while ((u8)(((struct rt0_hdr *)route)-> - addr[temp].s6_addr[len]) == - (u8)(rtinfo->addrs[ptr].s6_addr[len])){ - DEBUGP("%02X?%02X ", - (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]), - (u8)(rtinfo->addrs[ptr].s6_addr[len])); - len++; - if ( len == 16 ) break; - } - if (len==16) { - DEBUGP("ptr=%d temp=%d;\n",ptr,temp); - ptr++; - } else { - DEBUGP("%02X?%02X ", - (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]), - (u8)(rtinfo->addrs[ptr].s6_addr[len])); - DEBUGP("!ptr=%d temp=%d;\n",ptr,temp); + ap = skb_header_pointer(skb, + ptr + + sizeof(struct rt0_hdr) + + temp * sizeof(_addr), + sizeof(_addr), + &_addr); + + BUG_ON(ap == NULL); + + if (ipv6_addr_equal(ap, &rtinfo->addrs[i])) { + DEBUGP("i=%d temp=%d;\n",i,temp); + i++; } - if (ptr==rtinfo->addrnr) break; + if (i==rtinfo->addrnr) break; } - DEBUGP("ptr=%d len=%d #%d\n",ptr,len, rtinfo->addrnr); - if ( (len == 16) && (ptr == rtinfo->addrnr)) + DEBUGP("i=%d #%d\n", i, rtinfo->addrnr); + if (i == rtinfo->addrnr) return ret; else return 0; } @@ -225,26 +228,19 @@ match(const struct sk_buff *skb, } else { DEBUGP("#%d ",rtinfo->addrnr); for(temp=0; tempaddrnr; temp++){ - len = 0; - while ((u8)(((struct rt0_hdr *)route)-> - addr[temp].s6_addr[len]) == - (u8)(rtinfo->addrs[temp].s6_addr[len])){ - DEBUGP("%02X?%02X ", - (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]), - (u8)(rtinfo->addrs[temp].s6_addr[len])); - len++; - if ( len == 16 ) break; - } - if (len!=16) { - DEBUGP("%02X?%02X ", - (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]), - (u8)(rtinfo->addrs[temp].s6_addr[len])); - DEBUGP("!len=%d temp=%d;\n",len,temp); + ap = skb_header_pointer(skb, + ptr + + sizeof(struct rt0_hdr) + + temp * sizeof(_addr), + sizeof(_addr), + &_addr); + BUG_ON(ap == NULL); + + if (!ipv6_addr_equal(ap, &rtinfo->addrs[temp])) break; - } } - DEBUGP("temp=%d len=%d #%d\n",temp,len,rtinfo->addrnr); - if ( (len == 16) && (temp == rtinfo->addrnr) && (temp == (unsigned int)((hdrlen-8)/16))) + DEBUGP("temp=%d #%d\n", temp, rtinfo->addrnr); + if ((temp == rtinfo->addrnr) && (temp == (unsigned int)((hdrlen-8)/16))) return ret; else return 0; }