* [PATCH]: prearation of removing skb_linearize()
@ 2004-09-16 3:18 Yasuyuki Kozakai
2004-09-21 11:37 ` Patrick McHardy
0 siblings, 1 reply; 3+ messages in thread
From: Yasuyuki Kozakai @ 2004-09-16 3:18 UTC (permalink / raw)
To: netfilter-devel; +Cc: usagi-core
[-- Attachment #1: Type: Text/Plain, Size: 1378 bytes --]
Hi,
I updated the patch which prepares to remove skb_linearize() from ip6_tables.c
This patch uses skb_header_pointer() so that packets can be parsed even though
skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
yet. We can remove it after changing all match/target modules.
Moreover ...
- I deleted the optimization not to parse IPv6 extension header
many time from previous patch. I'll send the patch to do this
separately.
- fixed the bug that "offset" argument of match functions are always 0.
- deleted "hdr" and "datalen" argument and added "protoff" argument
to match functions. "protoff" means the offset to Layer 4 protocol
header.
- the argument order of target function is changed likely IPv4 modules.
This prevents user from meeting kernel panic when they use old
match modules.
- changed {tcp,udp,icmp6}_match(). These functions became very similar
to codes in ip_tables.c again.
I tested this patch with some configurations(attached file: "tests.txt")
In these tests, I also used quick hack to fragment skb at the end of IPv6
header before filtering to confirm that I didn't forget to use
skb_header_pointer() somewhere.
Double checks and more tests are welcome.
Regards,
-----------------------------------------------------------------
Yasuyuki KOZAKAI @ USAGI Project <yasuyuki.kozakai@toshiba.co.jp>
[-- Attachment #2: nolinearize-fixed.patch --]
[-- Type: Text/Plain, Size: 24400 bytes --]
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.9-rc2-nolinearize/include/linux/netfilter_ipv6/ip6_tables.h
--- linux-2.6.9-rc2/include/linux/netfilter_ipv6/ip6_tables.h 2004-09-15 23:38:34.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/include/linux/netfilter_ipv6/ip6_tables.h 2004-09-15 14:05:35.000000000 +0900
@@ -355,13 +355,15 @@
/* Return true or false: return FALSE and set *hotdrop = 1 to
force immediate packet drop. */
+ /* Arguments changed since 2.6.9, as this must now handle
+ non-linear skb, using skb_header_pointer and
+ skb_ip_make_writable. */
int (*match)(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop);
/* Called when user tries to insert an entry of this type. */
@@ -386,11 +388,13 @@
const char name[IP6T_FUNCTION_MAXNAMELEN];
- /* Returns verdict. */
+ /* Returns verdict. Argument order changed since 2.6.9, as this
+ must now handle non-linear skbs, using skb_copy_bits and
+ skb_ip_make_writable. */
unsigned int (*target)(struct sk_buff **pskb,
- unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
+ unsigned int hooknum,
const void *targinfo,
void *userdata);
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6_tables.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6_tables.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6_tables.c 2004-09-15 23:38:36.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6_tables.c 2004-09-16 02:14:30.084440504 +0900
@@ -158,14 +158,15 @@
/* Returns whether matches rule or not. */
static inline int
ip6_packet_match(const struct sk_buff *skb,
- const struct ipv6hdr *ipv6,
const char *indev,
const char *outdev,
const struct ip6t_ip6 *ip6info,
- int isfrag)
+ unsigned int *protoff,
+ int *fragoff)
{
size_t i;
unsigned long ret;
+ const struct ipv6hdr *ipv6 = skb->nh.ipv6h;
#define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg))
@@ -216,9 +217,10 @@
/* look for the desired protocol header */
if((ip6info->flags & IP6T_F_PROTO)) {
u_int8_t currenthdr = ipv6->nexthdr;
- struct ipv6_opt_hdr *hdrptr;
+ struct ipv6_opt_hdr _hdr, *hp;
u_int16_t ptr; /* Header offset in skb */
u_int16_t hdrlen; /* Header */
+ u_int16_t _fragoff = 0, *fp = NULL;
ptr = IPV6_HDR_LEN;
@@ -234,23 +236,41 @@
(currenthdr == IPPROTO_ESP))
return 0;
- hdrptr = (struct ipv6_opt_hdr *)(skb->data + ptr);
+ hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+ BUG_ON(hp == NULL);
/* Size calculation */
if (currenthdr == IPPROTO_FRAGMENT) {
+ fp = skb_header_pointer(skb,
+ ptr+offsetof(struct frag_hdr,
+ frag_off),
+ sizeof(_fragoff),
+ &_fragoff);
+ if (fp == NULL)
+ return 0;
+
+ _fragoff = ntohs(*fp) & ~0x7;
hdrlen = 8;
} else if (currenthdr == IPPROTO_AH)
- hdrlen = (hdrptr->hdrlen+2)<<2;
+ hdrlen = (hp->hdrlen+2)<<2;
else
- hdrlen = ipv6_optlen(hdrptr);
+ hdrlen = ipv6_optlen(hp);
- currenthdr = hdrptr->nexthdr;
+ currenthdr = hp->nexthdr;
ptr += hdrlen;
/* ptr is too large */
if ( ptr > skb->len )
return 0;
+ if (_fragoff) {
+ if (ip6t_ext_hdr(currenthdr))
+ return 0;
+ break;
+ }
}
+ *protoff = ptr;
+ *fragoff = _fragoff;
+
/* currenthdr contains the protocol header */
dprintf("Packet protocol %hi ?= %s%hi.\n",
@@ -292,9 +312,9 @@
static unsigned int
ip6t_error(struct sk_buff **pskb,
- unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
+ unsigned int hooknum,
const void *targinfo,
void *userinfo)
{
@@ -310,13 +330,12 @@
const struct net_device *in,
const struct net_device *out,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
/* Stop iteration if it doesn't match */
if (!m->u.kernel.match->match(skb, in, out, m->data,
- offset, hdr, datalen, hotdrop))
+ offset, protoff, hotdrop))
return 1;
else
return 0;
@@ -338,10 +357,8 @@
void *userdata)
{
static const char nulldevname[IFNAMSIZ];
- u_int16_t offset = 0;
- struct ipv6hdr *ipv6;
- void *protohdr;
- u_int16_t datalen;
+ int offset = 0;
+ unsigned int protoff = 0;
int hotdrop = 0;
/* Initializing verdict to NF_DROP keeps gcc happy. */
unsigned int verdict = NF_DROP;
@@ -354,9 +371,6 @@
return NF_DROP;
/* Initialization */
- ipv6 = (*pskb)->nh.ipv6h;
- protohdr = (u_int32_t *)((char *)ipv6 + IPV6_HDR_LEN);
- datalen = (*pskb)->len - IPV6_HDR_LEN;
indev = in ? in->name : nulldevname;
outdev = out ? out->name : nulldevname;
@@ -393,17 +407,19 @@
IP_NF_ASSERT(e);
IP_NF_ASSERT(back);
(*pskb)->nfcache |= e->nfcache;
- if (ip6_packet_match(*pskb, ipv6, indev, outdev,
- &e->ipv6, offset)) {
+ if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
+ &protoff, &offset)) {
struct ip6t_entry_target *t;
if (IP6T_MATCH_ITERATE(e, do_match,
*pskb, in, out,
- offset, protohdr,
- datalen, &hotdrop) != 0)
+ offset, protoff, &hotdrop) != 0)
goto no_match;
- ADD_COUNTER(e->counters, ntohs(ipv6->payload_len) + IPV6_HDR_LEN, 1);
+ ADD_COUNTER(e->counters,
+ ntohs((*pskb)->nh.ipv6h->payload_len)
+ + IPV6_HDR_LEN,
+ 1);
t = ip6t_get_target(e);
IP_NF_ASSERT(t->u.kernel.target);
@@ -443,8 +459,8 @@
= 0xeeeeeeec;
#endif
verdict = t->u.kernel.target->target(pskb,
- hook,
in, out,
+ hook,
t->data,
userdata);
@@ -459,11 +475,6 @@
((struct ip6t_entry *)table_base)->comefrom
= 0x57acc001;
#endif
- /* Target might have changed stuff. */
- ipv6 = (*pskb)->nh.ipv6h;
- protohdr = (u_int32_t *)((void *)ipv6 + IPV6_HDR_LEN);
- datalen = (*pskb)->len - IPV6_HDR_LEN;
-
if (verdict == IP6T_CONTINUE)
e = (void *)e + e->next_offset;
else
@@ -1535,26 +1546,31 @@
static int
tcp_find_option(u_int8_t option,
- const struct tcphdr *tcp,
- u_int16_t datalen,
+ const struct sk_buff *skb,
+ unsigned int tcpoff,
+ unsigned int optlen,
int invert,
int *hotdrop)
{
- unsigned int i = sizeof(struct tcphdr);
- const u_int8_t *opt = (u_int8_t *)tcp;
+ /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
+ char _opt[60 - sizeof(struct tcphdr)], *op;
+ unsigned int i;
duprintf("tcp_match: finding option\n");
+ if (!optlen)
+ return invert;
/* If we don't have the whole header, drop packet. */
- if (tcp->doff * 4 < sizeof(struct tcphdr) ||
- tcp->doff * 4 > datalen) {
+ op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen,
+ _opt);
+ if (op == NULL) {
*hotdrop = 1;
return 0;
}
- while (i < tcp->doff * 4) {
- if (opt[i] == option) return !invert;
- if (opt[i] < 2) i++;
- else i += opt[i+1]?:1;
+ for (i = 0; i < optlen; ) {
+ if (op[i] == option) return !invert;
+ if (op[i] < 2) i++;
+ else i += op[i+1]?:1;
}
return invert;
@@ -1566,27 +1582,31 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- const struct tcphdr *tcp;
+ struct tcphdr _tcph, *th;
const struct ip6t_tcp *tcpinfo = matchinfo;
- int tcpoff;
- u8 nexthdr = skb->nh.ipv6h->nexthdr;
- /* To quote Alan:
+ if (offset) {
+ /* To quote Alan:
- Don't allow a fragment of TCP 8 bytes in. Nobody normal
- causes this. Its a cracker trying to break in by doing a
- flag overwrite to pass the direction checks.
- */
-
- if (offset == 1) {
- duprintf("Dropping evil TCP offset=1 frag.\n");
- *hotdrop = 1;
+ Don't allow a fragment of TCP 8 bytes in. Nobody normal
+ causes this. Its a cracker trying to break in by doing a
+ flag overwrite to pass the direction checks.
+ */
+ if (offset == 1) {
+ duprintf("Dropping evil TCP offset=1 frag.\n");
+ *hotdrop = 1;
+ }
+ /* Must not be a fragment. */
return 0;
- } else if (offset == 0 && datalen < sizeof(struct tcphdr)) {
+ }
+
+#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
+
+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
+ if (th == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil TCP offset=0 tinygram.\n");
@@ -1594,45 +1614,30 @@
return 0;
}
- tcpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
- tcpoff = ipv6_skip_exthdr(skb, tcpoff, &nexthdr, skb->len - tcpoff);
- if (tcpoff < 0 || tcpoff > skb->len) {
- duprintf("tcp_match: cannot skip exthdr. Dropping.\n");
- *hotdrop = 1;
- return 0;
- } else if (nexthdr == IPPROTO_FRAGMENT)
- return 0;
- else if (nexthdr != IPPROTO_TCP ||
- skb->len - tcpoff < sizeof(struct tcphdr)) {
- /* cannot be occured */
- duprintf("tcp_match: cannot get TCP header. Dropping.\n");
- *hotdrop = 1;
- return 0;
+ if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
+ ntohs(th->source),
+ !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT)))
+ return 0;
+ if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
+ ntohs(th->dest),
+ !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT)))
+ return 0;
+ if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
+ == tcpinfo->flg_cmp,
+ IP6T_TCP_INV_FLAGS))
+ return 0;
+ if (tcpinfo->option) {
+ if (th->doff * 4 < sizeof(_tcph)) {
+ *hotdrop = 1;
+ return 0;
+ }
+ if (!tcp_find_option(tcpinfo->option, skb, protoff,
+ th->doff*4 - sizeof(*th),
+ tcpinfo->invflags & IP6T_TCP_INV_OPTION,
+ hotdrop))
+ return 0;
}
-
- tcp = (struct tcphdr *)(skb->data + tcpoff);
-
- /* FIXME: Try tcp doff >> packet len against various stacks --RR */
-
-#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
-
- /* Must not be a fragment. */
- return !offset
- && port_match(tcpinfo->spts[0], tcpinfo->spts[1],
- ntohs(tcp->source),
- !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT))
- && port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
- ntohs(tcp->dest),
- !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT))
- && FWINVTCP((((unsigned char *)tcp)[13]
- & tcpinfo->flg_mask)
- == tcpinfo->flg_cmp,
- IP6T_TCP_INV_FLAGS)
- && (!tcpinfo->option
- || tcp_find_option(tcpinfo->option, tcp, datalen,
- tcpinfo->invflags
- & IP6T_TCP_INV_OPTION,
- hotdrop));
+ return 1;
}
/* Called when user tries to insert an entry of this type. */
@@ -1658,16 +1663,18 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- const struct udphdr *udp;
+ struct udphdr _udph, *uh;
const struct ip6t_udp *udpinfo = matchinfo;
- int udpoff;
- u8 nexthdr = skb->nh.ipv6h->nexthdr;
- if (offset == 0 && datalen < sizeof(struct udphdr)) {
+ /* Must not be a fragment. */
+ if (offset)
+ return 0;
+
+ uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
+ if (uh == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil UDP tinygram.\n");
@@ -1675,30 +1682,11 @@
return 0;
}
- udpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
- udpoff = ipv6_skip_exthdr(skb, udpoff, &nexthdr, skb->len - udpoff);
- if (udpoff < 0 || udpoff > skb->len) {
- duprintf("udp_match: cannot skip exthdr. Dropping.\n");
- *hotdrop = 1;
- return 0;
- } else if (nexthdr == IPPROTO_FRAGMENT)
- return 0;
- else if (nexthdr != IPPROTO_UDP ||
- skb->len - udpoff < sizeof(struct udphdr)) {
- duprintf("udp_match: cannot get UDP header. Dropping.\n");
- *hotdrop = 1;
- return 0;
- }
-
- udp = (struct udphdr *)(skb->data + udpoff);
-
- /* Must not be a fragment. */
- return !offset
- && port_match(udpinfo->spts[0], udpinfo->spts[1],
- ntohs(udp->source),
- !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
+ return port_match(udpinfo->spts[0], udpinfo->spts[1],
+ ntohs(uh->source),
+ !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
&& port_match(udpinfo->dpts[0], udpinfo->dpts[1],
- ntohs(udp->dest),
+ ntohs(uh->dest),
!!(udpinfo->invflags & IP6T_UDP_INV_DSTPT));
}
@@ -1748,14 +1736,18 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- const struct icmp6hdr *icmp = hdr;
+ struct icmp6hdr _icmp, *ic;
const struct ip6t_icmp *icmpinfo = matchinfo;
- if (offset == 0 && datalen < 2) {
+ /* Must not be a fragment. */
+ if (offset)
+ return 0;
+
+ ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp);
+ if (ic == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil ICMP tinygram.\n");
@@ -1763,13 +1755,11 @@
return 0;
}
- /* Must not be a fragment. */
- return !offset
- && icmp6_type_code_match(icmpinfo->type,
- icmpinfo->code[0],
- icmpinfo->code[1],
- icmp->icmp6_type, icmp->icmp6_code,
- !!(icmpinfo->invflags&IP6T_ICMP_INV));
+ return icmp6_type_code_match(icmpinfo->type,
+ icmpinfo->code[0],
+ icmpinfo->code[1],
+ ic->icmp6_type, ic->icmp6_code,
+ !!(icmpinfo->invflags&IP6T_ICMP_INV));
}
/* Called when user tries to insert an entry of this type. */
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_LOG.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_LOG.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_LOG.c 2004-09-15 23:38:36.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_LOG.c 2004-09-16 02:17:04.097027032 +0900
@@ -335,9 +335,9 @@
static unsigned int
ip6t_log_target(struct sk_buff **pskb,
- unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
+ unsigned int hooknum,
const void *targinfo,
void *userinfo)
{
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_MARK.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_MARK.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_MARK.c 2004-08-14 14:37:41.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_MARK.c 2004-09-15 14:05:35.000000000 +0900
@@ -20,9 +20,9 @@
static unsigned int
target(struct sk_buff **pskb,
- unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
+ unsigned int hooknum,
const void *targinfo,
void *userinfo)
{
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_ah.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_ah.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_ah.c 2004-08-14 14:36:17.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_ah.c 2004-09-15 14:05:35.000000000 +0900
@@ -45,8 +45,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
struct ip_auth_hdr *ah = NULL;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_dst.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_dst.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_dst.c 2004-08-14 14:36:13.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_dst.c 2004-09-15 14:05:35.000000000 +0900
@@ -60,8 +60,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
struct ipv6_opt_hdr *optsh = NULL;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_esp.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_esp.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_esp.c 2004-08-14 14:37:15.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_esp.c 2004-09-15 14:05:35.000000000 +0900
@@ -45,8 +45,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
struct ip_esp_hdr *esp = NULL;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_eui64.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_eui64.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_eui64.c 2004-08-14 14:36:11.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_eui64.c 2004-09-15 14:05:35.000000000 +0900
@@ -24,8 +24,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_frag.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_frag.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_frag.c 2004-08-14 14:36:32.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_frag.c 2004-09-15 14:05:35.000000000 +0900
@@ -70,8 +70,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
struct fraghdr *frag = NULL;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_hbh.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_hbh.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_hbh.c 2004-08-14 14:37:38.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_hbh.c 2004-09-15 14:05:35.000000000 +0900
@@ -59,8 +59,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
struct ipv6_opt_hdr *optsh = NULL;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_hl.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_hl.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_hl.c 2004-08-14 14:37:26.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_hl.c 2004-09-15 14:05:35.000000000 +0900
@@ -20,7 +20,7 @@
static int match(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const void *matchinfo,
- int offset, const void *hdr, u_int16_t datalen,
+ int offset, unsigned int protoff,
int *hotdrop)
{
const struct ip6t_hl_info *info = matchinfo;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_ipv6header.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_ipv6header.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_ipv6header.c 2004-08-14 14:38:10.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_ipv6header.c 2004-09-15 14:05:35.000000000 +0900
@@ -31,8 +31,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
const struct ip6t_ipv6header_info *info = matchinfo;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_length.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_length.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_length.c 2004-08-14 14:38:08.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_length.c 2004-09-15 14:05:35.000000000 +0900
@@ -23,8 +23,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
const struct ip6t_length_info *info = matchinfo;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_limit.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_limit.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_limit.c 2004-08-14 14:36:32.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_limit.c 2004-09-15 14:05:35.000000000 +0900
@@ -57,8 +57,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
struct ip6t_rateinfo *r = ((struct ip6t_rateinfo *)matchinfo)->master;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_mac.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_mac.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_mac.c 2004-08-14 14:37:41.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_mac.c 2004-09-15 14:05:35.000000000 +0900
@@ -25,8 +25,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
const struct ip6t_mac_info *info = matchinfo;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_mark.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_mark.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_mark.c 2004-08-14 14:38:11.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_mark.c 2004-09-15 14:05:35.000000000 +0900
@@ -24,8 +24,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
const struct ip6t_mark_info *info = matchinfo;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_multiport.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_multiport.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_multiport.c 2004-08-14 14:38:09.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_multiport.c 2004-09-15 14:05:35.000000000 +0900
@@ -53,15 +53,14 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- const struct udphdr *udp = hdr;
+ const struct udphdr *udp = (const struct udphdr *)(skb->data + protoff);
const struct ip6t_multiport *multiinfo = matchinfo;
/* Must be big enough to read ports. */
- if (offset == 0 && datalen < sizeof(struct udphdr)) {
+ if (offset == 0 && skb->len - protoff < sizeof(struct udphdr)) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("ip6t_multiport:"
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_owner.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_owner.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_owner.c 2004-08-14 14:37:38.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_owner.c 2004-09-15 14:05:35.000000000 +0900
@@ -92,8 +92,7 @@
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
const struct ip6t_owner_info *info = matchinfo;
diff -X /home/kozakai/dontdiff -Nur linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_rt.c linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_rt.c
--- linux-2.6.9-rc2/net/ipv6/netfilter/ip6t_rt.c 2004-08-14 14:36:33.000000000 +0900
+++ linux-2.6.9-rc2-nolinearize/net/ipv6/netfilter/ip6t_rt.c 2004-09-15 14:05:35.000000000 +0900
@@ -47,8 +47,7 @@
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;
[-- Attachment #3: tests.txt --]
[-- Type: Text/Plain, Size: 4655 bytes --]
rule: sent packet result
===============================================================================
1. built-in match
1.1 ICMPv6 tests:
type/code = echo req: type/code 128/0 match
type/code = echo req: type/code 128/1 match
type/code = echo req: type/code 129/0 not match
type/code = echo req: type/code 129/1 not match
type/code = 128/0: type/code 128/0 match
type/code = 128/0: type/code 129/0 not match
type/code = 128/0: type/code 128/1 not match
type/code = 128/0: type/code 129/1 not match
type/code != 129/1: type/code 128/0 match
type/code != 129/1: type/code 129/0 match
type/code != 129/1: type/code 128/1 match
type/code != 129/1: type/code 129/1 not match
1.2 UDP tests:
sport = 10000, dport = 20000: sport 10000, dport 20000 match
sport = 10000, dport = 20000: sport 30000, dport 20000 not match
sport = 10000, dport = 20000: sport 10000, dport 30000 not match
sport = 10000, dport = 20000: sport 30000, dport 30000 not match
sport != 10000, dport = 20000: sport 10000, dport 20000 not match
sport != 10000, dport = 20000: sport 30000, dport 20000 match
sport != 10000, dport = 20000: sport 10000, dport 30000 not match
sport != 10000, dport = 20000: sport 30000, dport 30000 not match
sport != 10000, dport != 30000: sport 10000, dport 30000 not match
sport != 10000, dport != 30000: sport 30000, dport 30000 not match
sport != 10000, dport != 30000: sport 10000, dport 20000 not match
sport != 10000, dport != 30000: sport 30000, dport 20000 match
sport = 50000, dport != 30000: sport 50000, dport 30000 not match
sport = 50000, dport != 30000: sport 60000, dport 30000 not match
sport = 50000, dport != 30000: sport 50000, dport 60000 match
sport = 50000, dport != 30000: sport 60000, dport 60000 not match
1.3 TCP tests:
sport = 2000, dport = 5000: sport 2000, dport 5000 match
sport = 2000, dport = 5000: sport 3000, dport 5000 not match
sport = 2000, dport = 5000: sport 2000, dport 6000 not match
sport = 2000, dport = 5000: sport 3000, dport 6000 not match
sport != 2000, dport = 5000: sport 2000, dport 5000 not match
sport != 2000, dport = 5000: sport 3000, dport 5000 match
sport != 2000, dport = 5000: sport 2000, dport 6000 not match
sport != 2000, dport = 5000: sport 3000, dport 6000 not match
sport = 2000, dport != 5000: sport 2000, dport 5000 not match
sport = 2000, dport != 5000: sport 3000, dport 5000 not match
sport = 2000, dport != 5000: sport 2000, dport 6000 match
sport = 2000, dport != 5000: sport 3000, dport 6000 not match
sport != 2000, dport != 5000: sport 2000, dport 5000 not match
sport != 2000, dport != 5000: sport 3000, dport 5000 not match
sport != 2000, dport != 5000: sport 2000, dport 6000 not match
sport != 2000, dport != 5000: sport 3000, dport 6000 match
flags = SYN SYN: SYN match
flags = SYN SYN: ACK not match
flags = SYN SYN: SYN,RST match
flags != SYN SYN: SYN match
flags != SYN SYN: ACK not match
flags != SYN SYN: SYN,ACK match
flags = SYN,ACK,RST SYN: SYN match
flags = SYN,ACK,RST SYN: RST not match
flags = SYN,ACK,RST SYN: SYN,RST not match
flags = SYN,ACK,RST SYN: NONE not match
flags = ALL ACK,RST: NONE not match
flags = ALL ACK,RST: SYN not match
flags = ALL ACK,RST: RST not match
flags = ALL ACK,RST: ACK not match
flags = ALL ACK,RST: ACK,RST match
flags = ALL ACK,RST: SYN,ACK not match
flags = ALL ACK,RST: SYN,RST not match
flags = ALL ACK,RST: SYN,ACK,RST not match
option = 2(MSS): NONE not match
option = 2(MSS): MSS match
option = 2(MSS): SACK-OK,2NOP not match
option != 2(MSS): NONE match
option != 2(MSS): MSS not match
option != 2(MSS): SACK-OK,2NOP match
===============================================================================
2. Skipping extention headers to find layer 4 protocol header:
protocol=TCP, dport = 5001: AH, TCP, dport = 5001 match
protocol=UDP: Routing Header, UDP header, match
dport = 5001
protocol=UDP: ESP, UDP header(encrypted), not match
dport = 5001
protocol=ESP: ESP, UDP header(encrypted), not match
dport = 5001
protocol=UDP: Fragment Header(offset=0), match
UDP header, dport = 5001
protocol=UDP: Fragment Header(offset=1448), match
UDP data(dport = 5001)
protocol=UDP, dport = 5001: Fragment Header(offset=1448), not match
UDP data(dport = 5001)
protocol=UDP: Fragment Header(offset=0), match
AH, UDP header,
dport = 5001
protocol=UDP: Fragment Header(offset=1448, not match
"Next Header" is AH, but it
doesn't exist because it's
not 1st fragment), UDP data,
dport = 5001
===============================================================================
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH]: prearation of removing skb_linearize()
2004-09-16 3:18 [PATCH]: prearation of removing skb_linearize() Yasuyuki Kozakai
@ 2004-09-21 11:37 ` Patrick McHardy
2004-09-21 12:40 ` Yasuyuki Kozakai
0 siblings, 1 reply; 3+ messages in thread
From: Patrick McHardy @ 2004-09-21 11:37 UTC (permalink / raw)
To: Yasuyuki Kozakai; +Cc: netfilter-devel, usagi-core
Hi Yasuyuki,
Yasuyuki Kozakai wrote:
>Hi,
>
>I updated the patch which prepares to remove skb_linearize() from ip6_tables.c
>
>This patch uses skb_header_pointer() so that packets can be parsed even though
>skb_linearize() doesn't exist. But this patch doesn't remove skb_linearize()
>yet. We can remove it after changing all match/target modules.
>
>Moreover ...
> - I deleted the optimization not to parse IPv6 extension header
> many time from previous patch. I'll send the patch to do this
> separately.
> - fixed the bug that "offset" argument of match functions are always 0.
> - deleted "hdr" and "datalen" argument and added "protoff" argument
> to match functions. "protoff" means the offset to Layer 4 protocol
> header.
> - the argument order of target function is changed likely IPv4 modules.
> This prevents user from meeting kernel panic when they use old
> match modules.
> - changed {tcp,udp,icmp6}_match(). These functions became very similar
> to codes in ip_tables.c again.
>
>I tested this patch with some configurations(attached file: "tests.txt")
>In these tests, I also used quick hack to fragment skb at the end of IPv6
>header before filtering to confirm that I didn't forget to use
>skb_header_pointer() somewhere.
>
>Double checks and more tests are welcome.
>
>
Looks good, I'm going to review your patch more in-depth tonight.
One thing I noticed while looking over it:
>@@ -1535,26 +1546,31 @@
>
> static int
> tcp_find_option(u_int8_t option,
>- const struct tcphdr *tcp,
>- u_int16_t datalen,
>+ const struct sk_buff *skb,
>+ unsigned int tcpoff,
>+ unsigned int optlen,
> int invert,
> int *hotdrop)
> {
>- unsigned int i = sizeof(struct tcphdr);
>- const u_int8_t *opt = (u_int8_t *)tcp;
>+ /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
>+ char _opt[60 - sizeof(struct tcphdr)], *op;
>
>
This should stay a u_int8_t, look at
http://netfilter.org/security/2004-06-30-2.6-tcpoption.html
Regards
Patrick
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH]: prearation of removing skb_linearize()
2004-09-21 11:37 ` Patrick McHardy
@ 2004-09-21 12:40 ` Yasuyuki Kozakai
0 siblings, 0 replies; 3+ messages in thread
From: Yasuyuki Kozakai @ 2004-09-21 12:40 UTC (permalink / raw)
To: kaber; +Cc: netfilter-devel, usagi-core, yasuyuki.kozakai
Hi,
From: Patrick McHardy <kaber@trash.net>
Date: Tue, 21 Sep 2004 13:37:51 +0200
> Looks good, I'm going to review your patch more in-depth tonight.
> One thing I noticed while looking over it:
Thanks! And I've started to change match/target modules to use
skb_header_pointer().
>
> >@@ -1535,26 +1546,31 @@
> >
> > static int
> > tcp_find_option(u_int8_t option,
> >- const struct tcphdr *tcp,
> >- u_int16_t datalen,
> >+ const struct sk_buff *skb,
> >+ unsigned int tcpoff,
> >+ unsigned int optlen,
> > int invert,
> > int *hotdrop)
> > {
> >- unsigned int i = sizeof(struct tcphdr);
> >- const u_int8_t *opt = (u_int8_t *)tcp;
> >+ /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
> >+ char _opt[60 - sizeof(struct tcphdr)], *op;
> >
> >
>
> This should stay a u_int8_t, look at
> http://netfilter.org/security/2004-06-30-2.6-tcpoption.html
Oh, thank you for notice.
-----------------------------------------------------------------
Yasuyuki KOZAKAI @ USAGI Project <yasuyuki.kozakai@toshiba.co.jp>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2004-09-21 12:40 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-09-16 3:18 [PATCH]: prearation of removing skb_linearize() Yasuyuki Kozakai
2004-09-21 11:37 ` Patrick McHardy
2004-09-21 12:40 ` Yasuyuki Kozakai
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.