Commit c1684d9a authored by Yasuyuki Kozakai's avatar Yasuyuki Kozakai Committed by Patrick McHardy

[NETFILTER]: Introduce skb_header_pointer() to dst match

Signed-off-by: default avatarYasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent f2e9de25
...@@ -60,7 +60,7 @@ match(const struct sk_buff *skb, ...@@ -60,7 +60,7 @@ match(const struct sk_buff *skb,
unsigned int protoff, unsigned int protoff,
int *hotdrop) int *hotdrop)
{ {
struct ipv6_opt_hdr *optsh = NULL; struct ipv6_opt_hdr _optsh, *oh;
const struct ip6t_opts *optinfo = matchinfo; const struct ip6t_opts *optinfo = matchinfo;
unsigned int temp; unsigned int temp;
unsigned int len; unsigned int len;
...@@ -68,7 +68,8 @@ match(const struct sk_buff *skb, ...@@ -68,7 +68,8 @@ 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;
u8 *opttype = NULL; u8 _opttype, *tp = NULL;
u8 _optlen, *lp = NULL;
unsigned int optlen; unsigned int optlen;
/* type of the 1st exthdr */ /* type of the 1st exthdr */
...@@ -80,7 +81,7 @@ match(const struct sk_buff *skb, ...@@ -80,7 +81,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_opts header iteration \n"); DEBUGP("ipv6_opts header iteration \n");
...@@ -96,15 +97,16 @@ match(const struct sk_buff *skb, ...@@ -96,15 +97,16 @@ match(const struct sk_buff *skb,
break; break;
} }
hdr = (void *)(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);
/* OPTS -> evaluate */ /* OPTS -> evaluate */
#if HOPBYHOP #if HOPBYHOP
...@@ -132,7 +134,7 @@ match(const struct sk_buff *skb, ...@@ -132,7 +134,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 ) {
...@@ -158,9 +160,10 @@ match(const struct sk_buff *skb, ...@@ -158,9 +160,10 @@ match(const struct sk_buff *skb,
return 0; return 0;
} }
optsh = (void *)(skb->data + ptr); oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
BUG_ON(oh == NULL);
DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen); DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
DEBUGP("len %02X %04X %02X ", DEBUGP("len %02X %04X %02X ",
optinfo->hdrlen, hdrlen, optinfo->hdrlen, hdrlen,
...@@ -168,7 +171,7 @@ match(const struct sk_buff *skb, ...@@ -168,7 +171,7 @@ match(const struct sk_buff *skb,
((optinfo->hdrlen == hdrlen) ^ ((optinfo->hdrlen == hdrlen) ^
!!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
ret = (optsh != NULL) ret = (oh != NULL)
&& &&
(!(optinfo->flags & IP6T_OPTS_LEN) || (!(optinfo->flags & IP6T_OPTS_LEN) ||
((optinfo->hdrlen == hdrlen) ^ ((optinfo->hdrlen == hdrlen) ^
...@@ -185,36 +188,43 @@ match(const struct sk_buff *skb, ...@@ -185,36 +188,43 @@ match(const struct sk_buff *skb,
DEBUGP("#%d ",optinfo->optsnr); DEBUGP("#%d ",optinfo->optsnr);
for(temp=0; temp<optinfo->optsnr; temp++){ for(temp=0; temp<optinfo->optsnr; temp++){
/* type field exists ? */ /* type field exists ? */
if (ptr > skb->len - 1 || hdrlen < 1) if (hdrlen < 1)
break;
tp = skb_header_pointer(skb, ptr, sizeof(_opttype),
&_opttype);
if (tp == NULL)
break; break;
opttype = (void *)(skb->data + ptr);
/* Type check */ /* Type check */
if (*opttype != (optinfo->opts[temp] & 0xFF00)>>8){ if (*tp != (optinfo->opts[temp] & 0xFF00)>>8){
DEBUGP("Tbad %02X %02X\n", DEBUGP("Tbad %02X %02X\n",
*opttype, *tp,
(optinfo->opts[temp] & 0xFF00)>>8); (optinfo->opts[temp] & 0xFF00)>>8);
return 0; return 0;
} else { } else {
DEBUGP("Tok "); DEBUGP("Tok ");
} }
/* Length check */ /* Length check */
if (*opttype) { if (*tp) {
u16 spec_len; u16 spec_len;
/* length field exists ? */ /* length field exists ? */
if (ptr > skb->len - 2 || hdrlen < 2) if (hdrlen < 2)
break;
lp = skb_header_pointer(skb, ptr + 1,
sizeof(_optlen),
&_optlen);
if (lp == NULL)
break; break;
optlen = *((u8 *)(skb->data + ptr + 1));
spec_len = optinfo->opts[temp] & 0x00FF; spec_len = optinfo->opts[temp] & 0x00FF;
if (spec_len != 0x00FF && spec_len != optlen) { if (spec_len != 0x00FF && spec_len != *lp) {
DEBUGP("Lbad %02X %04X\n", optlen, DEBUGP("Lbad %02X %04X\n", *lp,
spec_len); spec_len);
return 0; return 0;
} }
DEBUGP("Lok "); DEBUGP("Lok ");
optlen += 2; optlen = *lp + 2;
} else { } else {
DEBUGP("Pad1\n"); DEBUGP("Pad1\n");
optlen = 1; optlen = 1;
......
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