[netfilter-cvslog] r3566 - in trunk: nfsim nfsim/core nfsim/core/ipv4 nfsim/kernelenv nfsim/kernelenv/include nfsim/tools nfsim-testsuite nfsim-testsuite/01iptables nfsim-testsuite/02conntrack

rusty at netfilter.org rusty at netfilter.org
Tue Jan 4 10:11:30 CET 2005


Author: rusty at netfilter.org
Date: 2005-01-04 10:11:29 +0100 (Tue, 04 Jan 2005)
New Revision: 3566

Modified:
   trunk/nfsim-testsuite/01iptables/01reject.sim
   trunk/nfsim-testsuite/02conntrack/07fragments.sim
   trunk/nfsim-testsuite/README
   trunk/nfsim-testsuite/test.sh
   trunk/nfsim/core/core.c
   trunk/nfsim/core/core.h
   trunk/nfsim/core/ipv4/ipv4.c
   trunk/nfsim/core/ipv4/ipv4.h
   trunk/nfsim/core/tui.c
   trunk/nfsim/kernelenv/include/kernelenv.h
   trunk/nfsim/kernelenv/kernelenv.c
   trunk/nfsim/netfilter.c.sed
   trunk/nfsim/tools/gen_err.c
   trunk/nfsim/tools/gen_ip.c
   trunk/nfsim/tools/time.c
Log:
Major nfsim rework for nonlinear skbs, and to make valgrind clean:
	override skb_ip_make_writable to record which parts are writable
		and make worst-cast split packet, and always realloc.
	fix fragment size, and skb len
	Real ip_select_ident so field is initialized
	Fix truncated packet descriptions
	Remove broken "command not found" expect handling (current_cmd is NULL)
	Implement nfsim_check_packet, call in various places.
	Remove skb->malloc_data.
	Move skb_shinfo to hidden field, not end of data, so valgrind can see overruns.
	nfsim_nonlinear_skb() and nfsim_skb() allocators.
	panic() turned to barf() (don't rely on kernel routines)
	Fix timer use-after-free bug.
	Initialize all fields in packet, esp. padding and mac addresses.

Valgrind is now only run with --valgrind, not just because it's installed.
"time +infinity" fixed everywhere, and "time garbage" caught.
Found many kernel bugs with this!


Modified: trunk/nfsim/core/core.c
===================================================================
--- trunk/nfsim/core/core.c	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim/core/core.c	2005-01-04 09:11:29 UTC (rev 3566)
@@ -138,6 +138,8 @@
 	unsigned int ret;
 	char *hookname = talloc_asprintf(NULL, "%s:%i", __func__, hooknum);
 
+	nfsim_check_packet(*skb);
+
 	if (should_i_fail(hookname)) {
 		talloc_free(hookname);
 		return NF_DROP;

Modified: trunk/nfsim/core/core.h
===================================================================
--- trunk/nfsim/core/core.h	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim/core/core.h	2005-01-04 09:11:29 UTC (rev 3566)
@@ -51,6 +51,14 @@
 int nf_rcv(struct sk_buff *skb);
 int nf_rcv_local(struct sk_buff *skb);
 
+/* Create an skb: first amount that is linear, then the rest. */
+struct sk_buff *nfsim_nonlinear_skb(const void *data1, unsigned int size1,
+				    const void *data2, unsigned int size2);
+
+/* Check packet is OK. */
+void nfsim_check_packet(const struct sk_buff *skb);
+/* Internal routine to say we updated packet. */
+void nfsim_update_skb(struct sk_buff *skb, void *p, unsigned int size);
 /*
  * simulator queueing
  */
@@ -238,8 +246,6 @@
 	return len;
 }
 
-int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len);
-
 unsigned int skb_checksum(const struct sk_buff *skb, int offset,
 			  int len, unsigned int csum);
 

Modified: trunk/nfsim/core/ipv4/ipv4.c
===================================================================
--- trunk/nfsim/core/ipv4/ipv4.c	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim/core/ipv4/ipv4.c	2005-01-04 09:11:29 UTC (rev 3566)
@@ -349,11 +349,14 @@
 		kfree_skb(skb);
 		return 1;
 	}
+	nfsim_update_skb(skb, &skb->nh.iph->ttl, sizeof(skb->nh.iph->ttl));
 
 	check = skb->nh.iph->check;
 	check += htons(0x0100);
 	skb->nh.iph->check = check + (check>=0xFFFF);
 
+	/* Tell nfsim it's me changing data here. */
+	nfsim_update_skb(skb, &skb->nh.iph->check, sizeof(skb->nh.iph->check));
 
 	/* FIXME: strict source routing... */
 
@@ -497,9 +500,8 @@
 			max = len + off;
 
 		memset(filled + off, 1, len);
-		memcpy(data + off, (void *)f->frags[i]->nh.iph
-		       + f->frags[i]->nh.iph->ihl * 4,
-		       len);
+		skb_copy_bits(f->frags[i], f->frags[i]->nh.iph->ihl * 4,
+			      data + off, len);
 		if (!(ntohs(f->frags[i]->nh.iph->frag_off) & IP_MF))
 			ended = true;
 	}
@@ -517,11 +519,11 @@
 
 	skb->nh.iph = (void *)skb->data;
 	memcpy(skb->nh.iph, f->frags[0]->nh.iph, f->frags[0]->nh.iph->ihl*4);
-	memcpy((void *)skb->nh.iph + f->frags[0]->nh.iph->ihl*4, data, len);
+	memcpy(skb_put(skb, max), data, max);
 
 	/* Except we're not a fragment, and we're longer. */
 	skb->nh.iph->frag_off = 0;
-	skb->nh.iph->tot_len = max + skb->nh.iph->ihl*4;
+	skb->nh.iph->tot_len = htons(max + skb->nh.iph->ihl*4);
 
 	list_del(&f->list);
 	talloc_free(f);
@@ -731,6 +733,11 @@
 	return addr;
 }
 
+void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, struct sock *sk)
+{
+	iph->id = 0;
+}
+
 static char *print_data(char *ptr, const char *data, int len)
 {
 	int i;
@@ -807,6 +814,7 @@
 		goto out;
 	
 	iplen = htons(iph->tot_len) - sizeof(struct iphdr);
+	len -= sizeof(struct iphdr);
 	
 	switch (iph->protocol) {
 	case IPPROTO_ICMP:
@@ -814,7 +822,7 @@
 		ptr += sprintf(ptr, "%u %u ",
 		       iplen - sizeof(struct icmphdr), iph->protocol);
 
-		if (len - sizeof(struct iphdr) < sizeof(struct icmphdr)) {
+		if (len < sizeof(struct icmphdr)) {
 			ptr += sprintf(ptr, "-TRUNCATED-");
 			goto out;
 		}
@@ -850,8 +858,7 @@
 		ptr += sprintf(ptr, "%u %u ",
 		       iplen - sizeof(struct udphdr), iph->protocol);
 
-		if (len - sizeof(struct iphdr) <
-		               sizeof(struct udphdr)) {
+		if (len < sizeof(struct udphdr)) {
 			ptr += sprintf(ptr, "-TRUNCATED-");
 			goto out;
 		}
@@ -882,13 +889,16 @@
 
 	case IPPROTO_TCP:
 		tcph = (struct tcphdr *)(iph + 1);
-		ptr += sprintf(ptr, "%u %u ",
-		       iplen - tcph->doff*4, iph->protocol);
+		if (len < sizeof(struct tcphdr)) {
+			/* Assume no tcp options... */
+			ptr += sprintf(ptr, "%u %u ",
+				       iplen - sizeof(*tcph), iph->protocol);
 
-		if (len - sizeof(struct iphdr) < sizeof(struct tcphdr)) {
 			ptr += sprintf(ptr, "-TRUNCATED-");
 			goto out;
 		}
+		ptr += sprintf(ptr, "%u %u ",
+		       iplen - tcph->doff*4, iph->protocol);
 
 		ptr += sprintf(ptr, "%u %u ",
 			       ntohs(tcph->source), ntohs(tcph->dest));
@@ -957,6 +967,10 @@
 			
 	default:
 		ptr += sprintf(ptr, "%u %u", iplen, iph->protocol);
+		if (len < iplen) {
+			ptr += sprintf(ptr, "-TRUNCATED-");
+			goto out;
+		}
 	}
 
 out:
@@ -970,8 +984,11 @@
 char *ipv4_describe_packet(struct sk_buff *skb)
 {
 	static char ipv4_pbuf[1024];
+	char packet[skb->len];
 
-	describe(ipv4_pbuf, skb->len, skb->nh.iph,
+	if (skb_copy_bits(skb, 0, packet, skb->len) != 0)
+		barf("skb_copy_bits failed");
+	describe(ipv4_pbuf, skb->len, (struct iphdr *)packet,
 		 field_value(skb, "dump_flags"));
 	return ipv4_pbuf;
 }

Modified: trunk/nfsim/core/ipv4/ipv4.h
===================================================================
--- trunk/nfsim/core/ipv4/ipv4.h	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim/core/ipv4/ipv4.h	2005-01-04 09:11:29 UTC (rev 3566)
@@ -448,7 +448,7 @@
 };
 
 
-#define ip_select_ident(iph,dst,sk)
+void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, struct sock *sk);
 
 /* fib */
 enum

Modified: trunk/nfsim/core/tui.c
===================================================================
--- trunk/nfsim/core/tui.c	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim/core/tui.c	2005-01-04 09:11:29 UTC (rev 3566)
@@ -212,10 +212,10 @@
 		return ret;
 	}
 
-	/* Someone might expect this command not to be found? */
-	if (!nfsim_log(LOG_UI, "%s: command not found", argv[0])
-	    && abort)
+	if (abort)
 		script_fail("%s not found", argv[0]);
+
+	nfsim_log(LOG_UI, "%s: command not found", argv[0]);
 	return false;
 }
 

Modified: trunk/nfsim/kernelenv/include/kernelenv.h
===================================================================
--- trunk/nfsim/kernelenv/include/kernelenv.h	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim/kernelenv/include/kernelenv.h	2005-01-04 09:11:29 UTC (rev 3566)
@@ -479,8 +479,7 @@
 #endif
 
 
-	unsigned char		*malloc_data,
-				*head,
+	unsigned char		*head,
 				*data,
 				*tail,
 				*end;
@@ -517,12 +516,9 @@
 
 extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
 
-#define alloc_skb(size, gfp) __alloc_skb((size), (gfp), __location__)
-struct sk_buff *__alloc_skb(unsigned int size, int gfp_mask, const char *loc);
+struct sk_buff *alloc_skb(unsigned int size, int priority);
 void kfree_skb(struct sk_buff *skb);
 
-#define dev_alloc_skb(s) alloc_skb(s,0)
-
 unsigned int skb_headroom(const struct sk_buff *skb);
 unsigned int skb_tailroom(const struct sk_buff *skb);
 
@@ -551,9 +547,9 @@
 
 void skb_orphan(struct sk_buff *skb);
 
-int skb_is_nonlinear(struct sk_buff *skb);
+int skb_is_nonlinear(const struct sk_buff *skb);
 
-#define skb_linearize(skb, len) 0
+extern int skb_linearize(struct sk_buff *skb, int gfp);
 #define skb_copy(skb, gfp) \
 	skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb), gfp)
 
@@ -565,7 +561,7 @@
 extern int skb_checksum_help(struct sk_buff *skb, int inward);
 #endif
 
-#define skb_shinfo(SKB)		((struct skb_shared_info *)((SKB)->end))
+extern struct skb_shared_info *skb_shinfo(struct sk_buff *skb);
 
 void *skb_header_pointer(const struct sk_buff *skb, int offset,
 			 int len, void *buffer);
@@ -618,6 +614,12 @@
 void skb_set_owner_w(struct sk_buff *skb, struct sock *sk);
 
 struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom);
+
+int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len);
+
+/* netfilter.c's version: unused. */
+int __unused_skb_ip_make_writable(struct sk_buff **, unsigned int);
+
 /* net.h */
 #define net_ratelimit() 1
 

Modified: trunk/nfsim/kernelenv/kernelenv.c
===================================================================
--- trunk/nfsim/kernelenv/kernelenv.c	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim/kernelenv/kernelenv.c	2005-01-04 09:11:29 UTC (rev 3566)
@@ -32,35 +32,127 @@
 unsigned long jiffies = INITIAL_JIFFIES;
 
 /* skbuff */
-struct sk_buff *alloc_skb_internal(unsigned int size, int gfp_mask, const char *loc)
+static int nfsim_seq;
+
+/* We hide the shared info in hidden field (kernel puts it after
+ * data).  This way valgrind can spot overruns. */
+struct skb_shared_info *skb_shinfo(struct sk_buff *skb)
 {
+	return field_value(skb, "skb_shinfo");
+}
+
+struct skb_extra_info {
+	void *data;
+	unsigned int len, writable_len;
+};
+
+/* Create an skb: first amount that is linear, then the rest. */
+struct sk_buff *nfsim_nonlinear_skb(const void *data1, unsigned int size1,
+				    const void *data2, unsigned int size2)
+{
 	struct sk_buff *skb;
-	static int seq;
+	struct skb_shared_info *sinfo;
+	struct skb_extra_info *extra;
 
-	/* skb, followed by data, followed by skb_shinfo */
-	skb = talloc_zero_named_const(__skb_ctx, sizeof(struct sk_buff) +
-				      sizeof(struct skb_shared_info) + size,
-				      loc);
+	/* Skb header. */
+	skb = talloc_zero(__skb_ctx, struct sk_buff);
 
+	/* Save copy of data, all non-writable. */
+	extra = talloc(skb, struct skb_extra_info);
+	extra->len = size1 + size2;
+	extra->writable_len = 0;
+	extra->data = talloc_size(extra, extra->len);
+	memcpy(extra->data, data1, size1);
+	memcpy(extra->data+size1, data2, size2);
+	field_attach(skb, "extra_data", extra);
+
+	/* Place linear data in skb. */
+	skb->data = talloc_memdup(skb, extra->data, size1);
+
+	sinfo = talloc(skb, struct skb_shared_info);
+	field_attach(skb, "skb_shinfo", sinfo);
+
 	atomic_set(&skb->users, 1);
 
-	skb->head = skb->data = skb->tail = (char *)skb + sizeof(struct sk_buff);
+	skb->head = skb->data;
+	skb->end = skb->tail = skb->data + size1;
+	skb->len = size1 + size2;
+
+	skb->seq = ++nfsim_seq;
+
+	/* set shinfo fields */
+	skb_shinfo(skb)->tso_size = 0;
+
+	return skb;
+}
+
+/* Normal, linear skb. */
+static struct sk_buff *nfsim_skb(unsigned int size)
+{
+	struct sk_buff *skb;
+	struct skb_shared_info *sinfo;
+
+	/* Skb header. */
+	skb = talloc_zero(__skb_ctx, struct sk_buff);
+
+	/* Place linear data in skb. */
+	skb->data = talloc_size(skb, size);
+	sinfo = talloc(skb, struct skb_shared_info);
+	field_attach(skb, "skb_shinfo", sinfo);
+
+	atomic_set(&skb->users, 1);
+	skb->head = skb->tail = skb->data;
+	skb->len = 0;
 	skb->end = skb->data + size;
 
-	skb->seq = ++seq;
+	skb->seq = ++nfsim_seq;
 
 	/* set shinfo fields */
 	skb_shinfo(skb)->tso_size = 0;
+	return skb;
+}
 
-	return skb;	
+void nfsim_check_packet(const struct sk_buff *skb)
+{
+	struct skb_extra_info *extra = field_value(skb, "extra_data");
+	unsigned int linear_len = skb->end - skb->head;
+
+	if (!extra)
+		return;
+
+	/* Packet should not have been changed where not writable. */
+	if (memcmp(skb->head + extra->writable_len,
+		   extra->data + extra->writable_len,
+		   linear_len - extra->writable_len) != 0)
+		barf("skb modified without being made writable!");
 }
 
-struct sk_buff *__alloc_skb(unsigned int size, int gfp_mask, const char *loc)
+/* Internal routine to say we updated skb. */
+void nfsim_update_skb(struct sk_buff *skb, void *p, unsigned int size)
 {
-	if (should_i_fail(loc))
+	struct skb_extra_info *extra = field_value(skb, "extra_data");
+	unsigned int off = p - (void *)skb->head;
+
+	if (!extra)
+		return;
+
+	if (off + size > extra->len)
+		barf("Bad nfsim_update_skb %i");
+
+	/* If it wasn't already writable, copy update to master. */
+	if (off + size > extra->writable_len)
+		memcpy(extra->data + off, p, size);
+
+	nfsim_check_packet(skb);
+}
+
+/* Defined to return a linear skb. */
+struct sk_buff *alloc_skb(unsigned int size, int priority)
+{
+	if (should_i_fail(__func__))
 		return NULL;
 
-	return alloc_skb_internal(size, gfp_mask, loc);
+	return nfsim_skb(size);
 }
 
 void kfree_skb(struct sk_buff *skb)
@@ -74,16 +166,13 @@
 	talloc_free(skb);
 }
 
-
 unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
 {
 	unsigned char *tmp = skb->tail;
 	skb->tail += len;
 	skb->len += len;
-	if (skb->tail > skb->end) {
-		panic("skb_put will overrun buffer");
-		/* panic ? */
-	}
+	if (skb->tail > skb->end)
+		barf("skb_put will overrun buffer");
 	return tmp;
 }
 
@@ -91,10 +180,8 @@
 {	
 	skb->data -= len;
 	skb->len  += len;
-	if (skb->data < skb->head) {
-		panic("skb_push will underrun buffer");
-		/* panic */
-	}
+	if (skb->data < skb->head)
+		barf("skb_push will underrun buffer");
 	return skb->data;
 }
 
@@ -103,42 +190,35 @@
 	skb->data += len;
 	skb->len  -= len;
 
-	if (skb->data < skb->head) {
-		panic("skb_pull will underrun buffer");
-		/* panic */
-	}
+	if (skb->data < skb->head)
+		barf("skb_pull will underrun buffer");
+
 	return skb->data;
 }
 
+/* Defined to return a writable, linear skb. */
 struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
 				int newheadroom, int newtailroom, int gfp_mask)
 {
-	struct sk_buff *n = alloc_skb(newheadroom + skb->len + newtailroom, 0);
+	struct sk_buff *n;
 
-	if (!n)
-		return 0;
-	
+	nfsim_check_packet(skb);
+
+	if (should_i_fail(__func__))
+		return NULL;
+
+	n = nfsim_skb(newheadroom + skb->len + newtailroom);
 	skb_reserve(n, newheadroom);
-
 	skb_put(n, skb->len);
 
-	if (skb_copy_bits(skb, 0, n->data, skb->len)) {
-		panic("skb_copy_bits failed");
-		/* panic */
-	}
+	if (skb_copy_bits(skb, 0, n->data, skb->len))
+		barf("skb_copy_bits failed");
 
 	copy_skb_header(n, skb);
 
 	return n;
 }
 
-/*
-unsigned int skb_headlen(const struct sk_buff *skb)
-{
-	return skb->len - skb->data_len;
-}
-*/
-
 unsigned int skb_headroom(const struct sk_buff *skb)
 {
 	return skb->data - skb->head;
@@ -146,13 +226,15 @@
 
 unsigned int skb_tailroom(const struct sk_buff *skb)
 {
-	return skb->end - skb->tail;
+	return skb_is_nonlinear(skb) ? 0 : skb->end - skb->tail;
 }
 
 void skb_reserve(struct sk_buff *skb, unsigned int len)
 {
 	skb->data += len;
 	skb->tail += len;
+	if (skb->data > skb->end || skb->tail > skb->end)
+		barf("skb_reserve: too much");
 }
 
 /* careful with this one.. */
@@ -191,14 +273,35 @@
 
 #undef __copy
 
+static inline int nfsim_linear_length(const struct sk_buff *skb)
+{
+	return skb->end - skb->data;
+}
 
-int skb_copy_bits(const struct sk_buff *skb, int offset,
-				     void *to, int len)
+int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
 {
+	struct skb_extra_info *extra = field_value(skb, "extra_data");
+
+	nfsim_check_packet(skb);
+
 	if (offset > (int)skb->len - len)
 		return -EFAULT;
 
-	memcpy(to, skb->data + offset, len);
+	/* Can we copy some from linear part of packet? */
+	if (offset < nfsim_linear_length(skb)) {
+		int len_from_data = min(len, nfsim_linear_length(skb)-offset);
+
+		memcpy(to, skb->data + offset, len_from_data);
+		offset += len_from_data;
+		len -= len_from_data;
+		to += len_from_data;
+	}
+
+	/* Copy from nonlinear part. */
+	if (extra)
+		memcpy(to, extra->data + skb_headroom(skb) + offset, len);
+	else
+		assert(len == 0);
 	return 0;
 }
 
@@ -282,11 +385,12 @@
 unsigned int skb_checksum(const struct sk_buff *skb, int offset,
 			  int len, unsigned int csum)
 {
-	assert(offset + len <= skb->len);
+	char data[len];
 
-	csum = csum_partial(skb->data + offset, len, csum);
+	if (skb_copy_bits(skb, offset, data, len) != 0)
+		barf("skb_checksum invalid length");
 
-	return csum;
+	return csum_partial(data, len, csum);
 }
 
 void __skb_trim(struct sk_buff *skb, unsigned int len)
@@ -309,20 +413,89 @@
         skb->sk         = NULL;
 }
 
-/* FIXME: nonlinear skb support would be good. */
-int skb_is_nonlinear(struct sk_buff *skb)
+int skb_is_nonlinear(const struct sk_buff *skb)
 {
+	nfsim_check_packet(skb);
+
+	return skb->data + skb->len > skb->end;
+}
+
+int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
+{
+	struct sk_buff *new;
+	struct skb_extra_info *extra;
+	char data[(*pskb)->len];
+
+	nfsim_check_packet(*pskb);
+
+	if (writable_len > (*pskb)->len)
+		return 0;
+
+	if (should_i_fail(__func__))
+		return 0;
+
+	/* Use skb_copy_bits, which handles packet whatever shape. */
+	skb_copy_bits(*pskb, 0, data, (*pskb)->len);
+
+	/* Always reallocate, to catch cached pointers. */
+	new = nfsim_nonlinear_skb(data, writable_len,
+				  data + writable_len,
+				  (*pskb)->len - writable_len);
+	copy_skb_header(new, *pskb);
+	extra = field_value(new, "extra_data");
+	extra->writable_len = writable_len;
+
+	if ((*pskb)->sk)
+		skb_set_owner_w(new, (*pskb)->sk);
+
+	kfree_skb(*pskb);
+	*pskb = new;
+	return 1;
+}
+
+int skb_linearize(struct sk_buff *skb, int len)
+{
+	unsigned char *new_head;
+	unsigned int headroom = skb_headroom(skb);
+
+	nfsim_check_packet(skb);
+
+	if (should_i_fail(__func__))
+		return -ENOMEM;
+
+	new_head = talloc_size(skb, skb->len + headroom);
+	memcpy(new_head, skb->head, headroom);
+	skb_copy_bits(skb, 0, new_head + headroom, skb->len);
+
+	skb->data = new_head + headroom;
+	skb->tail = skb->end = new_head + headroom + skb->len;
+	talloc_free(skb->head);
+	skb->head = new_head;
+
+	/* Don't need this on writable, linear packets. */
+	field_detach(skb, "extra_data");
 	return 0;
 }
 
+/* Either copy into buffer or give pointer to in-place. */
 void *skb_header_pointer(const struct sk_buff *skb, int offset,
 			 int len, void *buffer)
 {
-	/* We're always linear. */
+	nfsim_check_packet(skb);
+
 	if (offset + len > skb->len)
 		return NULL;
 
-	return skb->data + offset;
+	/* We should test copying even if not required. */
+	if (!should_i_fail_once(__func__)) {
+		if (offset + len <= nfsim_linear_length(skb))
+			return skb->data + offset;
+	}
+
+	if (skb_copy_bits(skb, offset, buffer, len) < 0)
+		barf("skb_header_pointer: logic error");
+
+	return buffer;
 }
 
 void sock_hold(struct sock *sk)
@@ -422,33 +595,6 @@
 	return (struct ethhdr *)skb->mac.raw;
 }
 
-/*
-{
-	unsigned int csum;
-	int offset = (*pskb)->h.raw - (*pskb)->data;
-
-	if (inward) {
-		(*pskb)->ip_summed = CHECKSUM_NONE;
-		return 0;
-	}
-
-	if (offset > (int)skb->len)
-		BUG();
-	csum = skb_checksum((*pskb), offset, (*pskb)->len-offset, 0);
-
-	offset = (*pskb)->tail - (*pskb)->h.raw;
-	if (offset <= 0)
-		BUG();
-	if ((*pskb)->csum + 2 > offset)
-		BUG();
-
-	*(u16*)((*pskb)->h.raw + (*pskb)->csum) = csum_fold(csum);
-	(*pskb)->ip_summed = CHECKSUM_NONE;
-
-	return 0;
-}
-*/
-
 /* spinlock: use talloc for unreleased lock detection */
 void __generic_write_lock(spinlock_t *lock, const char *location)
 {
@@ -622,8 +768,8 @@
 	struct timer_list *t, *next;
 	list_for_each_entry_safe(t, next, &__running_timers, entry) {
 		list_del(&t->entry);
+		talloc_free(t->use);
 		t->function(t->data);
-		talloc_free(t->use);
 	}
 	return true;
 }
@@ -664,9 +810,9 @@
 			t->ownerfunction, t->function);
 		i = i->next;
 		list_del(&t->entry);
-		t->function(t->data);
 		talloc_free(t->use);
 		t->use = NULL;
+		t->function(t->data);
 	}
 }
 

Modified: trunk/nfsim/netfilter.c.sed
===================================================================
--- trunk/nfsim/netfilter.c.sed	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim/netfilter.c.sed	2005-01-04 09:11:29 UTC (rev 3566)
@@ -4,5 +4,6 @@
 s/^int nf_register_hook(/int __nf_register_hook(/
 s/^void nf_unregister_sockopt(/void __nf_unregister_sockopt(/
 s/^void nf_unregister_hook(/void __nf_unregister_hook(/
+s/^int skb_ip_make_writable(/int __unused_skb_ip_make_writable(/
 
 

Modified: trunk/nfsim/tools/gen_err.c
===================================================================
--- trunk/nfsim/tools/gen_err.c	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim/tools/gen_err.c	2005-01-04 09:11:29 UTC (rev 3566)
@@ -45,6 +45,9 @@
 		return false;
 	}
 
+	packet->pad = 0;
+	memset(&packet->ehdr, 0, sizeof(packet->ehdr));
+	packet->ehdr.h_proto = htons(ETH_P_IP);	
 	packet->iph = ((struct iphdr)
 		      {
 #if __BYTE_ORDER == __LITTLE_ENDIAN

Modified: trunk/nfsim/tools/gen_ip.c
===================================================================
--- trunk/nfsim/tools/gen_ip.c	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim/tools/gen_ip.c	2005-01-04 09:11:29 UTC (rev 3566)
@@ -552,21 +552,20 @@
 	struct sk_buff *skb;
 	int len;
 
-	len = 16 + ntohs(packet->iph.tot_len);
+	/* Ethernet header and IPv4 headers are linear for netfilter hooks. */
+	len = offsetof(struct packet, iph) + packet->iph.ihl*4;
+	skb = nfsim_nonlinear_skb(packet, len, (void *)packet + len,
+				  offsetof(struct packet, iph) 
+				  + ntohs(packet->iph.tot_len) - len);
+	nfsim_check_packet(skb);
 
-	skb = alloc_skb_internal(len + 4096, 0, "send_packet");
-	
-	skb_reserve(skb, 2048);
-	skb_put(skb, len);
+	skb->mac.ethernet = (void *)skb->data + offsetof(struct packet, ehdr);
+	skb->nh.iph       = (void *)skb->data + offsetof(struct packet, iph);
+	skb->protocol = skb->mac.ethernet->h_proto;
 
-	memcpy(skb->data, packet, len);
+	/* You'll need to linearize to get this one. */
+	skb->h.raw = NULL;
 
-	skb->mac.ethernet = (void *)(skb->data + offsetof(struct packet, ehdr));
-	skb->nh.iph       = (void *)(skb->data + offsetof(struct packet, iph));
-	skb->h.raw        = skb->data + offsetof(struct packet, u);
-
-	skb->protocol = skb->mac.ethernet->h_proto;
-
 	if (dump_flags)
 		field_attach(skb, "dump_flags", dump_flags);
 
@@ -732,6 +731,9 @@
 		}
 		argc--;
 		argv++;
+	} else {
+		memset(packet->ehdr.h_dest, 0, sizeof(packet->ehdr.h_dest));
+		memset(packet->ehdr.h_source, 0,sizeof(packet->ehdr.h_source));
 	}
 
 	if (argc > 5 && strncmp(argv[1], "TOS=", 4) == 0) {
@@ -835,6 +837,7 @@
 	if (ce)
 		packet->iph.frag_off |= htons(IP_CE);
 
+	packet->pad = 0;
 	packet->iph.check = ~csum_partial(&packet->iph, sizeof(packet->iph),0);
 	packet->ehdr.h_proto = htons(ETH_P_IP);
 	return true;

Modified: trunk/nfsim/tools/time.c
===================================================================
--- trunk/nfsim/tools/time.c	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim/tools/time.c	2005-01-04 09:11:29 UTC (rev 3566)
@@ -42,15 +42,20 @@
 	}
 
 	if (argc == 2) {
-		if (*argv[1] == '+') {
+		if (streq(argv[1], "+infinity")) {
+			increment_time(find_last_timer() - jiffies);
+		} else if (*argv[1] == '+') {
 			increment_time(atoi(argv[1]+1) * HZ);
 		} else if (*argv[1] == '-') {
 			nfsim_log(LOG_ALWAYS, "Backwards time travel not "
 				"implemented");
 			return false;
-		} else if (streq(argv[1], "infinity")) {
-			increment_time(find_last_timer() - jiffies);
 		} else {
+			if (atoi(argv[1]) == 0) {
+				nfsim_log(LOG_ALWAYS,
+					  "Bad time argument %s", argv[1]);
+				return false;
+			}
 			if (atoi(argv[1]) * HZ < jiffies) {
 				nfsim_log(LOG_ALWAYS,
 					  "Flares alert: Backwards time travel not "
@@ -83,7 +88,7 @@
      </cmdsynopsis>
      <cmdsynopsis>
       <command>time</command>
-      <arg choice="req">+intinife</arg>
+      <arg choice="req">+infinity</arg>
      </cmdsynopsis>
      <para><command>time</command> with no arguments will show the current
       kernel time (in seconds).</para>

Modified: trunk/nfsim-testsuite/01iptables/01reject.sim
===================================================================
--- trunk/nfsim-testsuite/01iptables/01reject.sim	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim-testsuite/01iptables/01reject.sim	2005-01-04 09:11:29 UTC (rev 3566)
@@ -7,9 +7,9 @@
 gen_ip IF=eth0 192.168.0.2 192.168.0.1 10 17 1 2
 
 # nothing in return for an ICMP error.
-expect gen_err hook:NF_IP_LOCAL_IN * NF_DROP {IPv4 192.168.0.2 192.168.0.1 30 1 3 0 CONTAINS 192.168.0.1 192.168.0.2 10 17 1 2}
+expect gen_err hook:NF_IP_LOCAL_IN * NF_DROP {IPv4 192.168.0.2 192.168.0.1 38 1 3 0 CONTAINS 192.168.0.1 192.168.0.2 10 17 1 2}
 expect ! gen_err send:eth0*
-gen_err IF=eth0 LEN=30 192.168.0.2 3 0 192.168.0.1 192.168.0.2 10 17 1 2
+gen_err IF=eth0 LEN=38 192.168.0.2 3 0 192.168.0.1 192.168.0.2 10 17 1 2
 
 iptables -D INPUT -j REJECT
 

Modified: trunk/nfsim-testsuite/02conntrack/07fragments.sim
===================================================================
--- trunk/nfsim-testsuite/02conntrack/07fragments.sim	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim-testsuite/02conntrack/07fragments.sim	2005-01-04 09:11:29 UTC (rev 3566)
@@ -7,13 +7,13 @@
 expect ! proc *
 proc /proc/net/ip_conntrack
 
-expect gen_ip hook:NF_IP_PRE_ROUTING ip_conntrack NF_ACCEPT {IPv4 192.168.0.2 192.168.1.2 21484 3}
+expect gen_ip hook:NF_IP_PRE_ROUTING ip_conntrack NF_ACCEPT {IPv4 192.168.0.2 192.168.1.2 64 3}
 gen_ip IF=eth0 FRAG=32,32 192.168.0.2 192.168.1.2 64 3
 
 expect proc unknown  3 600 src=192.168.0.2 dst=192.168.1.2 *[UNREPLIED] src=192.168.1.2 dst=192.168.0.2 *use=1
 proc cat /proc/net/ip_conntrack
 
-time infinity
+time +infinity
 
 # Reverse order should be the same.
 expect gen_ip hook:NF_IP_PRE_ROUTING * NF_STOLEN
@@ -23,7 +23,7 @@
 expect ! proc *
 proc cat /proc/net/ip_conntrack
 
-expect gen_ip hook:NF_IP_PRE_ROUTING ip_conntrack NF_ACCEPT {IPv4 192.168.0.2 192.168.1.2 21484 3}
+expect gen_ip hook:NF_IP_PRE_ROUTING ip_conntrack NF_ACCEPT {IPv4 192.168.0.2 192.168.1.2 64 3}
 gen_ip IF=eth0 FRAG=0,32 MF 192.168.0.2 192.168.1.2 64 3
 
 expect proc unknown  3 600 src=192.168.0.2 dst=192.168.1.2 *[UNREPLIED] src=192.168.1.2 dst=192.168.0.2 *use=1

Modified: trunk/nfsim-testsuite/README
===================================================================
--- trunk/nfsim-testsuite/README	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim-testsuite/README	2005-01-04 09:11:29 UTC (rev 3566)
@@ -24,6 +24,9 @@
 		coverage.  nfsim will fork, and the child will test
 		the failure case.
 
+	--valgrind
+		Use valgrind to check for memory errors.
+
 	-v
 		Verbose mode: print out test names, and errors from
 		tests we are expecting to fail.

Modified: trunk/nfsim-testsuite/test.sh
===================================================================
--- trunk/nfsim-testsuite/test.sh	2005-01-03 09:55:14 UTC (rev 3565)
+++ trunk/nfsim-testsuite/test.sh	2005-01-04 09:11:29 UTC (rev 3566)
@@ -18,8 +18,9 @@
 	-k) KEEP_GOING=1; shift;;
 	--nfsim=*) NFSIM=`echo "$1" | cut -d= -f2-`; shift;;
 	--time) TIME=time; VERBOSE=1; shift;;
+	--valgrind) VALGRIND=1; shift;;
 	--help)
-	    echo "Usage $0 [-k|-vv|-v|--failtest|--time|--nfsim=<nfsim>]" >&2; exit 0;;
+	    echo "Usage $0 [-k|-vv|-v|--failtest|--time|--valgrind|--nfsim=<nfsim>]" >&2; exit 0;;
 	--*) NFSIM_ARGS="$NFSIM_ARGS $1"; shift;;
 	*) break;;
     esac
@@ -93,10 +94,8 @@
 }
 export -f valgrind_nfsim
 
-# Make them run the valgrind wrappers, if available.
-if type valgrind 2>/dev/null; then
-    NFSIM="valgrind_nfsim $NFSIM"
-fi
+# --valgrind?
+[ -z "$VALGRIND" ] || NFSIM="valgrind_nfsim $NFSIM"
 export NFSIM NFSIM_ARGS
 
 # Use iptables from SVN dir if we're in it.




More information about the netfilter-cvslog mailing list