[netfilter-cvslog] r3382 - in trunk/nfsim: core core/ipv4 kernelenv kernelenv/include tools

rusty at netfilter.org rusty at netfilter.org
Wed Dec 15 04:44:56 CET 2004


Author: rusty at netfilter.org
Date: 2004-12-15 04:44:55 +0100 (Wed, 15 Dec 2004)
New Revision: 3382

Added:
   trunk/nfsim/core/failtest.c
Modified:
   trunk/nfsim/core/Makefile
   trunk/nfsim/core/core.c
   trunk/nfsim/core/core.h
   trunk/nfsim/core/ipv4/ipv4.c
   trunk/nfsim/core/message.c
   trunk/nfsim/core/proc.c
   trunk/nfsim/core/talloc.h
   trunk/nfsim/core/tui.c
   trunk/nfsim/core/utils.c
   trunk/nfsim/kernelenv/include/kernelenv.h
   trunk/nfsim/kernelenv/kernelenv.c
   trunk/nfsim/tools/gen_ip.c
   trunk/nfsim/tools/iptables.c
Log:
Differentiate exit states:
	EXIT_SUCCESS: normal
	EXIT_SCRIPTFAIL: a test or command in the script failed
	EXIT_FAILURE: other failure (memory leak, etc)
	EXIT_SILENT: pass error code up, silently.
Log script failures using LOG_UI, so they don't appear with -q.
ipv4.c: fix skb leak when routing fails.
failtest.c, --failtest, should_i_fail(): fork on possible resource failure points to test all error paths.
--failpattern: pattern of failures to reproduce for debugging.
alloc_skb_internal: gen_ip can't handle spurious failures.
call_elem_hook: move out of line to avoid gcov confusion, add failure point.
__ip_route_output_key: add failure point
proc_create: add failure point
vmalloc, kmalloc: backend onto new __malloc.
KERN_EMERG: make strings readable rather than kernel-style <N>
alloc_skb: add __alloc_skb(), pass location.
__get_free_pages, free_pages, get_order: move out of line.
__alloc_skb: add failure point
__malloc: add failure point
kmem_cache_create: add failure point
kmem_cache_alloc: add failure point
iptables.c: suppress failure points while talking to external binary (it doesn't fork with us, yet).




Modified: trunk/nfsim/core/Makefile
===================================================================
--- trunk/nfsim/core/Makefile	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/core/Makefile	2004-12-15 03:44:55 UTC (rev 3382)
@@ -1,2 +1,2 @@
-OBJS += core/utils.o core/core.o core/message.o core/$(TYPE)/$(TYPE).o core/seq_file.o core/talloc.o
+OBJS += core/utils.o core/core.o core/message.o core/$(TYPE)/$(TYPE).o core/seq_file.o core/talloc.o core/failtest.o
 HELP_OBJS += core/tui.o core/expect.o core/log.o core/proc.o

Modified: trunk/nfsim/core/core.c
===================================================================
--- trunk/nfsim/core/core.c	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/core/core.c	2004-12-15 03:44:55 UTC (rev 3382)
@@ -129,6 +129,27 @@
 	running = 0;
 }
 
+/* We want logging for every hook */
+unsigned int call_elem_hook(struct nf_hook_ops *ops,
+			    unsigned int hooknum,
+			    struct sk_buff **skb,
+			    const struct net_device *in,
+			    const struct net_device *out,
+			    int (*okfn)(struct sk_buff *))
+{
+	unsigned int ret;
+
+	if (should_i_fail(__func__))
+		return NF_DROP;
+
+	ret = ops->hook(hooknum, skb, in, out, okfn);
+	nfsim_log(LOG_HOOK, "hook:%s %s %s%s",
+		   nf_hooknames[PF_INET][hooknum], ops->owner->name,
+		   nf_retval(ret), describe_packet(*skb));
+	return ret;
+}
+
+
 static void run_inits(void)
 {
 	/* Linker magic creates these to delineate section. */
@@ -154,14 +175,17 @@
 	{"exit",  0, 0, 'e'},
 	{"no-modules",  0, 0, 'N'},
 	{"version",  0, 0, 'V'},
+	{"failtest",  0, 0, 1},
+	{"failpattern",  1, 0, 2},
 	{0,        0, 0, 0 }
 };
 
 int main(int argc, char **argv)
 {
-	int termfd, load_modules = 1;
+	int termfd, failtest = 0, load_modules = 1;
 	char c;
 	char *p;
+	char *failpattern = NULL;
 
 	while ((c = getopt_long(argc, argv, "xqeNV", options, NULL)) != EOF) {
 		switch (c) {
@@ -181,8 +205,15 @@
 			printf("nfsim version %s\nkernel version %s\n",
 			       VERSION, UTS_RELEASE);
 			print_license();
-			exit(0);
+			exit(EXIT_SUCCESS);
 			break;
+		case 1:
+			failtest = 1;
+			break;
+		case 2:
+			failpattern = optarg;
+			failtest = 1;
+			break;
 		default:
 			fprintf(stderr, "Unknown argument %c\n", c);
 			return EXIT_FAILURE;
@@ -228,6 +259,9 @@
 	
 	nfsim_log(LOG_UI, "initialisation done");
 
+	if (failtest)
+		set_failtest(failpattern);
+
 	running = 1;
 
 	message_init();

Modified: trunk/nfsim/core/core.h
===================================================================
--- trunk/nfsim/core/core.h	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/core/core.h	2004-12-15 03:44:55 UTC (rev 3382)
@@ -26,6 +26,7 @@
 #define __HAVE_CORE_H 1
 
 #include <stdarg.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <kernelenv.h>
 
@@ -202,6 +203,9 @@
 			struct nf_info *info,
 			unsigned int verdict);
 
+/* Like alloc_skb, but never fails even when failtest on. */
+struct sk_buff *alloc_skb_internal(unsigned int size, int gfp_mask, const char *loc);
+
 #include <ipv4/ipv4.h>
 
 void stop(void);
@@ -229,19 +233,12 @@
 const char *describe_packet(struct sk_buff *skb);
 
 /* We want logging for every hook */
-static inline unsigned int call_elem_hook(struct nf_hook_ops *ops,
-					  unsigned int hooknum,
-					  struct sk_buff **skb,
-					  const struct net_device *in,
-					  const struct net_device *out,
-					  int (*okfn)(struct sk_buff *))
-{
-	unsigned int ret = ops->hook(hooknum, skb, in, out, okfn);
-	nfsim_log(LOG_HOOK, "hook:%s %s %s%s",
-		   nf_hooknames[PF_INET][hooknum], ops->owner->name,
-		   nf_retval(ret), describe_packet(*skb));
-	return ret;
-}
+unsigned int call_elem_hook(struct nf_hook_ops *ops,
+			    unsigned int hooknum,
+			    struct sk_buff **skb,
+			    const struct net_device *in,
+			    const struct net_device *out,
+			    int (*okfn)(struct sk_buff *));
 
 /* netlink sockets */
 
@@ -265,6 +262,17 @@
 /* tools/ifconfig.c: used to create initial devices. */
 struct net_device *create_device(const char *name, int argc, char **);
 
+/* For failtest to test malloc etc failures. */
+bool should_i_fail(const char *func);
+void set_failtest(const char *pattern);
+
+enum exitcodes
+{
+	/* EXIT_SUCCESS, EXIT_FAILURE is in stdlib.h */
+	EXIT_SCRIPTFAIL = EXIT_FAILURE + 1,
+	EXIT_SILENT,
+};
+
 /* init code */
 typedef void (*initcall_t)(void);
 #define init_call(fn) \

Added: trunk/nfsim/core/failtest.c
===================================================================
--- trunk/nfsim/core/failtest.c	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/core/failtest.c	2004-12-15 03:44:55 UTC (rev 3382)
@@ -0,0 +1,135 @@
+/*
+
+Copyright (c) 2004 Jeremy Kerr & Rusty Russell
+
+This file is part of nfsim.
+
+nfsim is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+nfsim is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with nfsim; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <log.h>
+#include <kernelenv.h>
+#include <utils.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+static bool failtest_on = false;
+bool suppress_failtest;
+
+/* Failures pattern so far. */
+static char *faillist;
+/* Failure pattern to follow (initialized by --failpattern). */
+static const char *failpattern = NULL;
+
+/* static void failtest_help(int argc, char **argv) */
+/* { */
+/* #include "failtest-help:failtest" */
+/* /\*** XML Help: */
+/*     <section id="a:failtest"> */
+/*      <title><command>failtest</command></title> */
+/*      <para>Recursively test allocation etc. failures.</para> */
+/*      <cmdsynopsis> */
+/*       <command>failtest</command> */
+/*      </cmdsynopsis> */
+
+/*      <para>The <command>failtest</command> command runs the rest of the */
+/*      script, but deliberately inserts failures (currently allocation */
+/*      failures and user-copying failures).  At each potential failure, */
+/*      both failure and success will be simulated: where we fail, the */
+/*      script will no doubt fail later which is OK, but we ensure that */
+/*      the entire system doesn't fall over or leak memory.</para> */
+
+/*      <para>This testing can be slow, but allows for testing of failure */
+/*      paths which would otherwise be very difficult to test */
+/*      automatically.</para> */
+/*     </section> */
+/* *\/ */
+/* } */
+
+static bool do_failpattern(const char *func)
+{
+	if (*failpattern == '[') {
+		failpattern++;
+		if (strncmp(failpattern, func, strlen(func)) != 0
+		    || failpattern[strlen(func)] != ']')
+			barf("Failpattern expected %.*s not %s\n",
+			     strcspn(failpattern, "]"), failpattern, func);
+		failpattern += strlen(func) + 1;
+	}
+
+	switch ((failpattern++)[0]) {
+	case 'F':
+	case 'f':
+		return true;
+	case 'S':
+	case 's':
+		return false;
+	case 0:
+		failpattern = NULL;
+		failtest_on = 0;
+		return false;
+	default:
+		barf("Failpattern '%c' failed to pattern",
+		     failpattern[-1]);
+	}
+}
+
+/* Should I fail at this point? */
+bool should_i_fail(const char *func)
+{
+	pid_t child;
+	int status;
+
+	if (!failtest_on || suppress_failtest)
+		return false;
+
+	if (failpattern)
+		return do_failpattern(func);
+
+	child = fork();
+	if (child == -1)
+		barf_perror("fork failed for failtest!");
+
+	/* The child actually fails.  The script will screw up at this
+	 * point, but keep going to get as much code coverage as possible. */
+	if (child == 0) {
+		faillist = talloc_asprintf_append(faillist, "[%s]F", func);
+		return true;
+	}
+
+	faillist = talloc_asprintf_append(faillist, "[%s]S", func);
+	if (waitpid(child, &status, 0) != child)
+		barf_perror("failtest waitpid failed for child %i",(int)child);
+
+	/* If child succeeded, or mere script failure, continue. */
+	if (WIFEXITED(status) && (WEXITSTATUS(status) == EXIT_SUCCESS
+				  || WEXITSTATUS(status) == EXIT_SCRIPTFAIL))
+		return true;
+
+	/* Report unless child already reported it. */
+	if (!WIFEXITED(status) || WEXITSTATUS(status) == EXIT_SILENT) {
+		nfsim_log(LOG_ALWAYS, "Child %s %i on failure path: %s[%s]F",
+			  WIFEXITED(status) ? "exited" : "signalled",
+			  WIFEXITED(status) ? WEXITSTATUS(status)
+			  : WTERMSIG(status), faillist, func);
+	}
+	exit(EXIT_SILENT);
+}
+
+void set_failtest(const char *initial_failpattern)
+{
+	failtest_on = true;
+	failpattern = initial_failpattern;
+}

Modified: trunk/nfsim/core/ipv4/ipv4.c
===================================================================
--- trunk/nfsim/core/ipv4/ipv4.c	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/core/ipv4/ipv4.c	2004-12-15 03:44:55 UTC (rev 3382)
@@ -152,6 +152,7 @@
 
 	if (__ip_route_output_key(&rt, &fl)) {
 		log_route(skb, "no route");
+		kfree_skb(skb);
 		return 1;
 	}
 	
@@ -201,6 +202,9 @@
 	struct net_device *dev;
 	struct ipv4_route *route;
 
+	if (should_i_fail(__func__))
+		return -ENOMEM;
+
 	/* check for a cached route */
 	for (rth = rcache; rth; rth = rth->u.rt_next) {
 		if (rth->fl.fl4_dst == flp->fl4_dst &&

Modified: trunk/nfsim/core/message.c
===================================================================
--- trunk/nfsim/core/message.c	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/core/message.c	2004-12-15 03:44:55 UTC (rev 3382)
@@ -126,7 +126,6 @@
 	write(sock[0], msg, sizeof(struct nf_userspace_message) + msg->len);
 	/* expect a reply */
 	return handle_userspace_message(sock[0]);
-
 }
 
 int copy_to_user(void *to, const void *from, unsigned long n)

Modified: trunk/nfsim/core/proc.c
===================================================================
--- trunk/nfsim/core/proc.c	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/core/proc.c	2004-12-15 03:44:55 UTC (rev 3382)
@@ -76,6 +76,9 @@
 		goto out;
 	len = strlen(fn);
 
+	if (should_i_fail(__func__))
+		goto out;
+
 	ent = talloc_size(NULL, sizeof(struct proc_dir_entry) + len + 1);
 	if (!ent) goto out;
 

Modified: trunk/nfsim/core/talloc.h
===================================================================
--- trunk/nfsim/core/talloc.h	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/core/talloc.h	2004-12-15 03:44:55 UTC (rev 3382)
@@ -20,6 +20,7 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
+#include <stdarg.h>
 
 /*
   this uses a little trick to allow __LINE__ to be stringified

Modified: trunk/nfsim/core/tui.c
===================================================================
--- trunk/nfsim/core/tui.c	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/core/tui.c	2004-12-15 03:44:55 UTC (rev 3382)
@@ -189,19 +189,19 @@
 	char *str;
 	va_list arglist;
 
-	fprintf(stderr, "Script failed at line %i: ", linenum);
+	nfsim_log(LOG_UI, "Script failed at line %i: ", linenum);
 
 	va_start(arglist, fmt);
 	str = talloc_vasprintf(NULL, fmt, arglist);
 	va_end(arglist);
 
-	nfsim_log(LOG_ALWAYS, "%s", str);
+	nfsim_log(LOG_UI, "%s", str);
 	talloc_free(str);
 
 	unload_all_modules();
 	check_allocations();
-	
-	exit(1);
+
+	exit(EXIT_SCRIPTFAIL);
 }
 
 void process_line(char *line)

Modified: trunk/nfsim/core/utils.c
===================================================================
--- trunk/nfsim/core/utils.c	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/core/utils.c	2004-12-15 03:44:55 UTC (rev 3382)
@@ -42,7 +42,7 @@
 
 	nfsim_log(LOG_ALWAYS, "%s", str);
 	free(str);
-	exit(1);
+	exit(EXIT_FAILURE);
 }
 
 void barf_perror(const char *fmt, ...)
@@ -59,5 +59,5 @@
 
 	nfsim_log(LOG_ALWAYS, "%s: %s", str, strerror(err));
 	free(str);
-	exit(1);
+	exit(EXIT_FAILURE);
 }

Modified: trunk/nfsim/kernelenv/include/kernelenv.h
===================================================================
--- trunk/nfsim/kernelenv/include/kernelenv.h	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/kernelenv/include/kernelenv.h	2004-12-15 03:44:55 UTC (rev 3382)
@@ -94,26 +94,15 @@
 #define __inline
 #define ____cacheline_aligned
 
-#include <stdarg.h>
 #include <talloc.h>
 extern void *__vmalloc_ctx;
 extern void *__kmalloc_atomic_ctx;
 extern void *__kmalloc_ctx;
+void *__malloc(unsigned int, void *ctx, const char *location);
 
-#define MALLOC_INIT 1
+#define vmalloc(s) __malloc((s), __vmalloc_ctx, __location__)
+#define kmalloc(s,f) __malloc((s), (f) & GFP_ATOMIC ? __kmalloc_atomic_ctx : __kmalloc_ctx, __location__)
 
-#ifdef MALLOC_INIT
-#define vmalloc(s) talloc_zero_named_const(__vmalloc_ctx, (s), __location__)
-#define kmalloc(s,f) ((f) & GFP_ATOMIC				\
-		      ? talloc_zero_named_const(__kmalloc_atomic_ctx, (s), __location__)	\
-		      : talloc_zero_named_const(__kmalloc_ctx, (s), __location__))
-#else
-#define vmalloc(s) talloc_size(__vmalloc_ctx, (s))
-#define kmalloc(s,f) ((f) & GFP_ATOMIC				\
-		      ? talloc_size(__kmalloc_atomic_ctx, (s))	\
-		      : talloc_size(__kmalloc_ctx, (s)))
-#endif
-
 #define vfree(p)   talloc_unlink(__vmalloc_ctx, (p))
 #define kfree(p)   talloc_free(p)
 
@@ -174,14 +163,14 @@
 
 #define HZ 100
 
-#define	KERN_EMERG	"<0>"	/* system is unusable			*/
-#define	KERN_ALERT	"<1>"	/* action must be taken immediately	*/
-#define	KERN_CRIT	"<2>"	/* critical conditions			*/
-#define	KERN_ERR	"<3>"	/* error conditions			*/
-#define	KERN_WARNING	"<4>"	/* warning conditions			*/
-#define	KERN_NOTICE	"<5>"	/* normal but significant condition	*/
-#define	KERN_INFO	"<6>"	/* informational			*/
-#define	KERN_DEBUG	"<7>"	/* debug-level messages			*/
+#define	KERN_EMERG	"EMERG:"/* system is unusable			*/
+#define	KERN_ALERT	"ALERT:"/* action must be taken immediately	*/
+#define	KERN_CRIT	"CRIT:"	/* critical conditions			*/
+#define	KERN_ERR	"ERR;"	/* error conditions			*/
+#define	KERN_WARNING	"WARN:"	/* warning conditions			*/
+#define	KERN_NOTICE	"NOTICE:"/* normal but significant condition	*/
+#define	KERN_INFO	"INFO:"	/* informational			*/
+#define	KERN_DEBUG	"DEBUG:"/* debug-level messages			*/
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
@@ -518,7 +507,8 @@
 
 extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
 
-struct sk_buff *alloc_skb(unsigned int size, int gfp_mask);
+#define alloc_skb(size, gfp) __alloc_skb((size), (gfp), __location__)
+struct sk_buff *__alloc_skb(unsigned int size, int gfp_mask, const char *loc);
 void kfree_skb(struct sk_buff *skb);
 
 #define dev_alloc_skb(s) alloc_skb(s,0)
@@ -1108,30 +1098,10 @@
 void *kmem_cache_alloc(kmem_cache_t *, int);
 void kmem_cache_free(kmem_cache_t *, void *);
 
-static inline unsigned long
-__get_free_pages(unsigned int gfp_mask, unsigned int order)
-{
-	return (unsigned long)(kmalloc(PAGE_SIZE << order, gfp_mask));
-}
-static inline void free_pages(unsigned long addr, unsigned int order)
-{
-	memset((void *)addr, 0, PAGE_SIZE << order);
-	kfree((void *)addr);
-}
+unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order);
+void free_pages(unsigned long addr, unsigned int order);
+int get_order(unsigned long size);
 
-static inline int get_order(unsigned long size)
-{
-	int order;
-
-	size = (size-1) >> (PAGE_SHIFT-1);
-	order = -1;
-	do {
-		size >>= 1;
-		order++;
-	} while (size);
-	return order;
-}
-
 /* wait.h */
 struct __wait_queue_head {
 	spinlock_t lock;

Modified: trunk/nfsim/kernelenv/kernelenv.c
===================================================================
--- trunk/nfsim/kernelenv/kernelenv.c	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/kernelenv/kernelenv.c	2004-12-15 03:44:55 UTC (rev 3382)
@@ -30,16 +30,16 @@
 unsigned long jiffies = INITIAL_JIFFIES;
 
 /* skbuff */
-struct sk_buff *alloc_skb(unsigned int size, int gfp_mask)
+struct sk_buff *alloc_skb_internal(unsigned int size, int gfp_mask, const char *loc)
 {
 	struct sk_buff *skb;
 	static int seq;
 
 	/* skb, followed by data, followed by skb_shinfo */
-	skb = talloc_size(__skb_ctx, sizeof(struct sk_buff) +
-			  sizeof(struct skb_shared_info) + size);
-	
-	memset(skb, 0, sizeof(struct sk_buff) + size);
+	skb = talloc_zero_named_const(__skb_ctx, sizeof(struct sk_buff) +
+				      sizeof(struct skb_shared_info) + size,
+				      loc);
+
 	atomic_set(&skb->users, 1);
 
 	skb->head = skb->data = skb->tail = (char *)skb + sizeof(struct sk_buff);
@@ -53,6 +53,14 @@
 	return skb;	
 }
 
+struct sk_buff *__alloc_skb(unsigned int size, int gfp_mask, const char *loc)
+{
+	if (should_i_fail(loc))
+		return NULL;
+
+	return alloc_skb_internal(size, gfp_mask, loc);
+}
+
 void kfree_skb(struct sk_buff *skb)
 {
 #ifdef CONFIG_NETFILTER
@@ -470,7 +478,13 @@
 }
 
 /* cache */
+void *__malloc(unsigned int size, void *ctx, const char *location)
+{
+	if (should_i_fail(__func__))
+		return NULL;
 
+	return talloc_zero_named_const(ctx, size, location);
+}
 
 kmem_cache_t *kmem_cache_create(const char *name, size_t objsize,
         size_t offset, unsigned long flags,
@@ -479,6 +493,9 @@
 {
 	kmem_cache_t *cache;
 
+	if (should_i_fail(__func__))
+		return NULL;
+
 	cache = talloc(__kmem_cache_ctx, kmem_cache_t);
 	cache->name = name;
 	cache->objsize = objsize;
@@ -500,6 +517,9 @@
 {
 	struct kmem_cache_obj *obj;
 
+	if (should_i_fail(__func__))
+		return NULL;
+
 	obj = talloc(cache, struct kmem_cache_obj);
 	obj->ptr = talloc_size(obj, cache->objsize);
 
@@ -523,6 +543,31 @@
 	panic("[cache] attempting to free non-cache memory\n");
 }
 
+unsigned long
+__get_free_pages(unsigned int gfp_mask, unsigned int order)
+{
+	return (unsigned long)(kmalloc(PAGE_SIZE << order, gfp_mask));
+}
+
+void free_pages(unsigned long addr, unsigned int order)
+{
+	memset((void *)addr, 0, PAGE_SIZE << order);
+	kfree((void *)addr);
+}
+
+int get_order(unsigned long size)
+{
+	int order;
+
+	size = (size-1) >> (PAGE_SHIFT-1);
+	order = -1;
+	do {
+		size >>= 1;
+		order++;
+	} while (size);
+	return order;
+}
+
 void kernelenv_init(void)
 {
 	__vmalloc_ctx = talloc_named_const(NULL, 1, "vmallocs");

Modified: trunk/nfsim/tools/gen_ip.c
===================================================================
--- trunk/nfsim/tools/gen_ip.c	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/tools/gen_ip.c	2004-12-15 03:44:55 UTC (rev 3382)
@@ -486,7 +486,7 @@
 
 	len = 16 + ntohs(packet->iph.tot_len);
 
-	skb = alloc_skb(len + 4096, 0);
+	skb = alloc_skb_internal(len + 4096, 0, "send_packet");
 	
 	skb_reserve(skb, 2048);
 	skb_put(skb, len);

Modified: trunk/nfsim/tools/iptables.c
===================================================================
--- trunk/nfsim/tools/iptables.c	2004-12-14 08:29:08 UTC (rev 3381)
+++ trunk/nfsim/tools/iptables.c	2004-12-15 03:44:55 UTC (rev 3382)
@@ -31,6 +31,13 @@
 #include "utils.h"
 #include "message.h"
 
+/* FIXME: We can't fork while we're talking to the external program.
+ * The correct thing to do is to record the messages up to the point
+ * of fork in failtest.c, do a new run_command() and replay the
+ * messages, which effectively "forks" the external program.
+ */
+extern bool suppress_failtest;
+
 static bool run_command(int argc, char **argv)
 {
 	pid_t child;
@@ -39,6 +46,8 @@
 	char *prefix;
 	char buf[4096] = { 0 };
 
+	suppress_failtest = true;
+
 	if (pipe(childfd) != 0)
 		barf_perror("%s pipe", argv[0]);
 
@@ -62,7 +71,7 @@
 			execvp(argv[0], argv);
 			fprintf(stderr, "Could not exec %s!\n", argv[0]);
 		}
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 
 	close(childfd[1]);
@@ -77,6 +86,7 @@
 		input[ret] = '\0';
 		nfsim_log_partial(LOG_USERSPACE, buf, sizeof(buf), "%s",input);
 	}
+	suppress_failtest = false;
 
 	if (waitpid(child, &status, 0) <= 0)
 		barf_perror("Waiting for %s child", argv[0]);




More information about the netfilter-cvslog mailing list