Commit 2afe6f85 authored by Yasuyuki Kozakai's avatar Yasuyuki Kozakai Committed by Patrick McHardy

[NETFILTER]: Enable ip6t_rt.c to work without skb_linearize()

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarYasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
parent a5082f0c
...@@ -50,7 +50,7 @@ match(const struct sk_buff *skb, ...@@ -50,7 +50,7 @@ match(const struct sk_buff *skb,
unsigned int protoff, unsigned int protoff,
int *hotdrop) int *hotdrop)
{ {
struct ipv6_rt_hdr *route = NULL; struct ipv6_rt_hdr _route, *rh = NULL;
const struct ip6t_rt *rtinfo = matchinfo; const struct ip6t_rt *rtinfo = matchinfo;
unsigned int temp; unsigned int temp;
unsigned int len; unsigned int len;
...@@ -58,6 +58,7 @@ match(const struct sk_buff *skb, ...@@ -58,6 +58,7 @@ match(const struct sk_buff *skb,
unsigned int ptr; unsigned int ptr;
unsigned int hdrlen = 0; unsigned int hdrlen = 0;
unsigned int ret = 0; unsigned int ret = 0;
struct in6_addr *ap, _addr;
/* type of the 1st exthdr */ /* type of the 1st exthdr */
nexthdr = skb->nh.ipv6h->nexthdr; nexthdr = skb->nh.ipv6h->nexthdr;
...@@ -68,7 +69,7 @@ match(const struct sk_buff *skb, ...@@ -68,7 +69,7 @@ match(const struct sk_buff *skb,
temp = 0; temp = 0;
while (ip6t_ext_hdr(nexthdr)) { while (ip6t_ext_hdr(nexthdr)) {
struct ipv6_opt_hdr *hdr; struct ipv6_opt_hdr _hdr, *hp;
DEBUGP("ipv6_rt header iteration \n"); DEBUGP("ipv6_rt header iteration \n");
...@@ -84,15 +85,16 @@ match(const struct sk_buff *skb, ...@@ -84,15 +85,16 @@ match(const struct sk_buff *skb,
break; 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 */ /* Calculate the header length */
if (nexthdr == NEXTHDR_FRAGMENT) { if (nexthdr == NEXTHDR_FRAGMENT) {
hdrlen = 8; hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH) } else if (nexthdr == NEXTHDR_AUTH)
hdrlen = (hdr->hdrlen+2)<<2; hdrlen = (hp->hdrlen+2)<<2;
else else
hdrlen = ipv6_optlen(hdr); hdrlen = ipv6_optlen(hp);
/* ROUTING -> evaluate */ /* ROUTING -> evaluate */
if (nexthdr == NEXTHDR_ROUTING) { if (nexthdr == NEXTHDR_ROUTING) {
...@@ -115,7 +117,7 @@ match(const struct sk_buff *skb, ...@@ -115,7 +117,7 @@ match(const struct sk_buff *skb,
break; break;
} }
nexthdr = hdr->nexthdr; nexthdr = hp->nexthdr;
len -= hdrlen; len -= hdrlen;
ptr += hdrlen; ptr += hdrlen;
if ( ptr > skb->len ) { if ( ptr > skb->len ) {
...@@ -137,20 +139,21 @@ match(const struct sk_buff *skb, ...@@ -137,20 +139,21 @@ match(const struct sk_buff *skb,
return 0; 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("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
DEBUGP("TYPE %04X ", route->type); DEBUGP("TYPE %04X ", rh->type);
DEBUGP("SGS_LEFT %u %02X\n", route->segments_left, route->segments_left); DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
DEBUGP("IPv6 RT segsleft %02X ", DEBUGP("IPv6 RT segsleft %02X ",
(segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
route->segments_left, rh->segments_left,
!!(rtinfo->invflags & IP6T_RT_INV_SGS)))); !!(rtinfo->invflags & IP6T_RT_INV_SGS))));
DEBUGP("type %02X %02X %02X ", DEBUGP("type %02X %02X %02X ",
rtinfo->rt_type, route->type, rtinfo->rt_type, rh->type,
(!(rtinfo->flags & IP6T_RT_TYP) || (!(rtinfo->flags & IP6T_RT_TYP) ||
((rtinfo->rt_type == route->type) ^ ((rtinfo->rt_type == rh->type) ^
!!(rtinfo->invflags & IP6T_RT_INV_TYP)))); !!(rtinfo->invflags & IP6T_RT_INV_TYP))));
DEBUGP("len %02X %04X %02X ", DEBUGP("len %02X %04X %02X ",
rtinfo->hdrlen, hdrlen, rtinfo->hdrlen, hdrlen,
...@@ -158,13 +161,13 @@ match(const struct sk_buff *skb, ...@@ -158,13 +161,13 @@ match(const struct sk_buff *skb,
((rtinfo->hdrlen == hdrlen) ^ ((rtinfo->hdrlen == hdrlen) ^
!!(rtinfo->invflags & IP6T_RT_INV_LEN)))); !!(rtinfo->invflags & IP6T_RT_INV_LEN))));
DEBUGP("res %02X %02X %02X ", DEBUGP("res %02X %02X %02X ",
(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 *)route)->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], (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
route->segments_left, rh->segments_left,
!!(rtinfo->invflags & IP6T_RT_INV_SGS))) !!(rtinfo->invflags & IP6T_RT_INV_SGS)))
&& &&
(!(rtinfo->flags & IP6T_RT_LEN) || (!(rtinfo->flags & IP6T_RT_LEN) ||
...@@ -172,13 +175,19 @@ match(const struct sk_buff *skb, ...@@ -172,13 +175,19 @@ match(const struct sk_buff *skb,
!!(rtinfo->invflags & IP6T_RT_INV_LEN))) !!(rtinfo->invflags & IP6T_RT_INV_LEN)))
&& &&
(!(rtinfo->flags & IP6T_RT_TYP) || (!(rtinfo->flags & IP6T_RT_TYP) ||
((rtinfo->rt_type == route->type) ^ ((rtinfo->rt_type == rh->type) ^
!!(rtinfo->invflags & IP6T_RT_INV_TYP))) !!(rtinfo->invflags & IP6T_RT_INV_TYP)));
&&
!((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)route)->bitmap)); 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); DEBUGP("#%d ",rtinfo->addrnr);
temp = len = ptr = 0;
if ( !(rtinfo->flags & IP6T_RT_FST) ){ if ( !(rtinfo->flags & IP6T_RT_FST) ){
return ret; return ret;
} else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) { } else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) {
...@@ -187,32 +196,27 @@ match(const struct sk_buff *skb, ...@@ -187,32 +196,27 @@ match(const struct sk_buff *skb,
DEBUGP("There isn't enough space\n"); DEBUGP("There isn't enough space\n");
return 0; return 0;
} else { } else {
unsigned int i = 0;
DEBUGP("#%d ",rtinfo->addrnr); DEBUGP("#%d ",rtinfo->addrnr);
ptr = 0;
for(temp=0; temp<(unsigned int)((hdrlen-8)/16); temp++){ for(temp=0; temp<(unsigned int)((hdrlen-8)/16); temp++){
len = 0; ap = skb_header_pointer(skb,
while ((u8)(((struct rt0_hdr *)route)-> ptr
addr[temp].s6_addr[len]) == + sizeof(struct rt0_hdr)
(u8)(rtinfo->addrs[ptr].s6_addr[len])){ + temp * sizeof(_addr),
DEBUGP("%02X?%02X ", sizeof(_addr),
(u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]), &_addr);
(u8)(rtinfo->addrs[ptr].s6_addr[len]));
len++; BUG_ON(ap == NULL);
if ( len == 16 ) break;
} if (!ipv6_addr_cmp(ap, &rtinfo->addrs[i])) {
if (len==16) { DEBUGP("i=%d temp=%d;\n",i,temp);
DEBUGP("ptr=%d temp=%d;\n",ptr,temp); i++;
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);
} }
if (ptr==rtinfo->addrnr) break; if (i==rtinfo->addrnr) break;
} }
DEBUGP("ptr=%d len=%d #%d\n",ptr,len, rtinfo->addrnr); DEBUGP("i=%d #%d\n", i, rtinfo->addrnr);
if ( (len == 16) && (ptr == rtinfo->addrnr)) if (i == rtinfo->addrnr)
return ret; return ret;
else return 0; else return 0;
} }
...@@ -224,26 +228,19 @@ match(const struct sk_buff *skb, ...@@ -224,26 +228,19 @@ match(const struct sk_buff *skb,
} else { } else {
DEBUGP("#%d ",rtinfo->addrnr); DEBUGP("#%d ",rtinfo->addrnr);
for(temp=0; temp<rtinfo->addrnr; temp++){ for(temp=0; temp<rtinfo->addrnr; temp++){
len = 0; ap = skb_header_pointer(skb,
while ((u8)(((struct rt0_hdr *)route)-> ptr
addr[temp].s6_addr[len]) == + sizeof(struct rt0_hdr)
(u8)(rtinfo->addrs[temp].s6_addr[len])){ + temp * sizeof(_addr),
DEBUGP("%02X?%02X ", sizeof(_addr),
(u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]), &_addr);
(u8)(rtinfo->addrs[temp].s6_addr[len])); BUG_ON(ap == NULL);
len++;
if ( len == 16 ) break; if (ipv6_addr_cmp(ap, &rtinfo->addrs[temp]))
}
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);
break; break;
}
} }
DEBUGP("temp=%d len=%d #%d\n",temp,len,rtinfo->addrnr); DEBUGP("temp=%d #%d\n", temp, rtinfo->addrnr);
if ( (len == 16) && (temp == rtinfo->addrnr) && (temp == (unsigned int)((hdrlen-8)/16))) if ((temp == rtinfo->addrnr) && (temp == (unsigned int)((hdrlen-8)/16)))
return ret; return ret;
else return 0; else return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment