[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