All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.