diff -Nru nfsim-20040907-plain/core/fakesockopt.c nfsim-20040907-laf/core/fakesockopt.c
--- nfsim-20040907-plain/core/fakesockopt.c	2004-03-01 07:26:37.000000000 +0100
+++ nfsim-20040907-laf/core/fakesockopt.c	2004-09-20 00:27:58.000000000 +0200
@@ -1,6 +1,6 @@
 /*
 
-Copyright (c) 2003,2004 Jeremy Kerr & Rusty Russell
+Copyright (c) 2003,2004 Jeremy Kerr, Rusty Russell & Harald Welte
 
 This file is part of nfsim.
 
@@ -33,21 +33,28 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+
 #include <dlfcn.h>
 
 #include <assert.h>
 #include <string.h>
 
+#include <netinet/in.h>
+
 /* pointers to the real functions */
 static int (*__socket)(int, int, int);
 static int (*__getsockopt)(int, int , int , void *, socklen_t *);
 static int (*__setsockopt)(int, int , int , void *, socklen_t *);
+static int (*__open)(const char *pathname, int flags, ...);
+FILE * (*__fopen)(const char *path, const char *mode);
 static int (*__close)(int);
 
 static int sd;
 static void *handle;
+static char *proc_prefix = "/tmp/nfsim/proc";
 
 #undef DEBUG
+#define DEBUG
 
 /* utils expects a log function.  Give it to them. */
 void nfsim_log(enum log_type type, const char *fmt, ...)
@@ -81,6 +88,7 @@
 {
 	struct sockaddr_un unix_addr;
 	int addrlen;
+	char *prefix;
 
 	if (!(handle = dlopen("libc.so.6", RTLD_LAZY))) {
 		fprintf(stderr, "%s\n", dlerror());
@@ -90,6 +98,8 @@
 	sym(handle, getsockopt);
 	sym(handle, setsockopt);
 	sym(handle, socket);
+	sym(handle, open);
+	sym(handle, fopen);
 	sym(handle, close);
 
 	dlclose(handle);
@@ -112,6 +122,10 @@
 		exit(EXIT_FAILURE);
 	}
 
+	prefix = getenv("NFSIM_PROC_PREFIX");
+	if (prefix)
+		proc_prefix = prefix;
+
 	return;
 
 }
@@ -254,9 +268,100 @@
 	printf("socket(%d, %d, %d)\n", domain, type, protocol);
 #endif /* DEBUG */
 
-	return sd;
+	/* only catch AF_INET/SOCK_RAW/IPPROTO_RAW sockets */
+	if (domain == AF_INET && type == SOCK_RAW && protocol == IPPROTO_RAW)
+		return sd;
+	//else if (domain == AF_NETLINK)
+	//	return fake_netlink_socket(domain, type, protocol);
+	else
+		return __socket(domain, type, protocol);
+}
+
+
+static int file_is_proc(const char *pathname)
+{
+	if (pathname && strlen(pathname) >= 6 
+	    && !strncmp(pathname, "/proc/", 6))
+		return 1;
+	else
+		return 0;
+}
+
+static char *mangle_alloc_proc_path(const char *pathname)
+{
+	char *fakepath = (char *) malloc(strlen(pathname) 
+			 + strlen(proc_prefix));
+	if (!fakepath)
+		return NULL;
+
+	strcpy(fakepath, proc_prefix);
+	strcat(fakepath, pathname+5); /* 5 because '/' */
+
+	return fakepath;
 }
 
+
+/* open intercepts any accesses to /proc and directs them to somewhere else */
+int open(const char *pathname, int flags, ...)
+{
+	int ret;
+	va_list arglist;
+	mode_t mode = 0;
+
+#ifdef DEBUG
+	printf("open(%s, %d)\n", pathname, flags);
+#endif
+
+	va_start(arglist, flags);
+
+	/* mode is only valid if O_CREAT was specified */
+	if (flags & O_CREAT)
+		mode = va_arg(arglist, mode_t);
+
+	/* if this is not a /proc open, pass it through */
+	if (!file_is_proc(pathname))
+		ret = __open(pathname, flags, mode);
+	else {
+		char *fakepath = mangle_alloc_proc_path(pathname);
+		if (!fakepath) {
+			ret = -ENOMEM;
+			/* need this ugly goto for va_end */
+			goto out;
+		}
+
+		/* mode will be ignored in case of no O_CRAT */
+		ret = __open(fakepath, flags, mode);
+
+		free(fakepath);
+	}
+out:
+	va_end(arglist);
+	return ret;
+}
+
+FILE *fopen(const char *path, const char *mode)
+{
+	FILE *ret;
+
+#ifdef DEBUG
+	printf("%s(%s, %s)\n", __FUNCTION__, path, mode);
+#endif
+
+	if (!file_is_proc(path))
+		ret = __fopen(path, mode);
+	else {
+		char *fakepath = mangle_alloc_proc_path(path);
+		if (!fakepath) {
+			errno = -ENOMEM;
+			return NULL;
+		}
+
+		ret = __fopen(fakepath, mode);
+	}
+	return ret;
+}
+
+
 int close(int fd)
 {
 	return (fd == sd) ? 0 : (*__close)(fd);
diff -Nru nfsim-20040907-plain/core/message.c nfsim-20040907-laf/core/message.c
--- nfsim-20040907-plain/core/message.c	2004-03-01 07:26:37.000000000 +0100
+++ nfsim-20040907-laf/core/message.c	2004-09-19 22:11:00.000000000 +0200
@@ -22,6 +22,7 @@
 #include "message.h"
 #include "utils.h"
 
+#include <signal.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -35,6 +36,7 @@
 void message_init(void)
 {
 	struct sockaddr_un unix_addr;
+	sigset_t ss;
 
 	unlink(FAKE_SOCKET);
 
@@ -51,11 +53,21 @@
 
 	if (listen(sockfd, 0))
 		barf_perror("listen");
+
+	sigemptyset(&ss);
+	sigaddset(&ss, SIGPIPE);
+	sigprocmask(SIG_BLOCK, &ss, NULL);
 }
 
 void message_cleanup(void)
 {
+	sigset_t ss;
+
 	close(sockfd);
+
+	sigemptyset(&ss);
+	sigaddset(&ss, SIGPIPE);
+	sigprocmask(SIG_UNBLOCK, &ss, NULL);
 }
 
 int message_client_connection(int fd)
@@ -80,10 +92,12 @@
 	struct nf_userspace_message *msg;
 
 	msg = new(struct nf_userspace_message);
-	if ((len = read(fd, msg, sizeof(*msg)) != sizeof(*msg))) {
+	len = read(fd, msg, sizeof(*msg));
+	if (len != sizeof(*msg)) {
 		free(msg);
 		return -1;
 	}
+	fprintf(stderr, "%s: received %u bytes\n", __FUNCTION__, len);
 
 	if (msg->type == UM_SYSCALL) {
 		switch (msg->opcode) {
@@ -122,7 +136,7 @@
 				msg->opcode);
 		}
 	} else {
-		fprintf(stderr, "Unknown message type\n");
+		fprintf(stderr, "Unknown message type %d\n", msg->type);
 	}
 
 	free(msg);
diff -Nru nfsim-20040907-plain/tools/iptables.c nfsim-20040907-laf/tools/iptables.c
--- nfsim-20040907-plain/tools/iptables.c	2004-03-01 07:26:29.000000000 +0100
+++ nfsim-20040907-laf/tools/iptables.c	2004-09-19 22:11:27.000000000 +0200
@@ -1,6 +1,6 @@
 /*
 
-Copyright (c) 2003,2004 Jeremy Kerr & Rusty Russell
+Copyright (c) 2003,2004 Jeremy Kerr, Rusty Russell and Harald Welte
 
 This file is part of nfsim.
 
@@ -24,6 +24,7 @@
 #include <ipv4/ipv4.h>
 
 #include <unistd.h>
+#include <stdlib.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <signal.h>
@@ -31,36 +32,46 @@
 #include "message.h"
 
 static int sigfd[2];
+static char *iptables_prefix = "/sbin";
 
 static void wake_parent(int signum)
 {
 	write(sigfd[1], "", 1);
 }
 
-static bool iptables(int argc, char **argv)
+static bool xtables_x(int argc, char **argv)
 {
 	pid_t child;
 	int status;
+	int cmdlen = strlen(argv[0]) + strlen(iptables_prefix) + 2;
+	char *cmd = malloc(cmdlen);
+
+	if (!cmd)
+		barf_perror("%s: ENOMEM", argv[0]);
+
+	strcpy(cmd, iptables_prefix);
+	strcat(cmd, "/");
+	strcat(cmd, argv[0]);
 
 	if (pipe(sigfd) != 0)
-		barf_perror("iptables pipe");
+		barf_perror("%s pipe", argv[0]);
 
 	signal(SIGCHLD, wake_parent);
-	
+
 	child = fork();
 	switch (child) {
 	case -1:
-		barf_perror("iptables fork");
+		barf_perror("%s fork", argv[0]);
 	case 0:
 		if (setenv("LD_PRELOAD", "core/fakesockopt.so.1.0", 1))
 			barf("putenv failed");
-		execv("/sbin/iptables", argv);
+		execv(cmd, argv);
 		exit(1);
 	}
 
 	wait_for_message(sigfd[0]);
 	if (waitpid(child, &status, WNOHANG) <= 0)
-		barf_perror("Waiting for iptables child");
+		barf_perror("Waiting for %s child", argv[0]);
 
 	close(sigfd[0]);
 	close(sigfd[1]);
@@ -70,16 +81,29 @@
 	return false;
 }
 
-static void iptables_help(int argc, char **argv)
+static void xtables_x_help(int argc, char **argv)
 {
-	nfsim_log(LOG_ALWAYS, "iptables <arguments>\n"
-		"\trun iptables (on the simulated netfilter code), with the\n"
-		"\tspecified arguments");
+	nfsim_log(LOG_ALWAYS, "%s <arguments>\n"
+		"\trun %s (on the simulated netfilter code), with the\n"
+		"\tspecified arguments", argv[0]);
 }
 
 static int init(void)
 {
-	tui_register_command("iptables", iptables, iptables_help);
+	char *prefix = getenv("NFSIM_IPTABLES_PREFIX");
+	if (prefix)
+		iptables_prefix = prefix;
+
+	tui_register_command("iptables", xtables_x, xtables_x_help);
+	tui_register_command("iptables-save", xtables_x, xtables_x_help);
+	tui_register_command("iptables-restore", xtables_x, xtables_x_help);
+
+#ifdef HAVE_IPV6
+	tui_register_command("ip6tables", xtables_x, xtables_x_help);
+	tui_register_command("ip6tables-save", xtables_x, xtables_x_help);
+	tui_register_command("ip6tables-restore", xtables_x, xtables_x_help);
+#endif
+
 	return 0;
 }
 

