Module Name:    src
Committed By:   rmind
Date:           Wed May 30 21:38:04 UTC 2012

Modified Files:
        src/sys/net/npf: npf_ctl.c npf_handler.c npf_impl.h npf_state.c
            npf_state_tcp.c
        src/sys/rump/dev/lib/libnpf: Makefile
        src/usr.sbin/npf/npftest: Makefile npftest.c npftest.h
        src/usr.sbin/npf/npftest/libnpftest: Makefile npf_mbuf_subr.c
            npf_test.h
Added Files:
        src/usr.sbin/npf/npftest: npfstream.c
        src/usr.sbin/npf/npftest/libnpftest: npf_test_subr.c

Log Message:
npftest: add a stream processor, which prints out the TCP state information.
A tool for debugging connection tracking from tcpdump -w captured data.


To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/net/npf/npf_ctl.c \
    src/sys/net/npf/npf_impl.h
cvs rdiff -u -r1.16 -r1.17 src/sys/net/npf/npf_handler.c
cvs rdiff -u -r1.6 -r1.7 src/sys/net/npf/npf_state.c
cvs rdiff -u -r1.4 -r1.5 src/sys/net/npf/npf_state_tcp.c
cvs rdiff -u -r1.2 -r1.3 src/sys/rump/dev/lib/libnpf/Makefile
cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/npf/npftest/Makefile \
    src/usr.sbin/npf/npftest/npftest.c src/usr.sbin/npf/npftest/npftest.h
cvs rdiff -u -r0 -r1.1 src/usr.sbin/npf/npftest/npfstream.c
cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/npf/npftest/libnpftest/Makefile \
    src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c \
    src/usr.sbin/npf/npftest/libnpftest/npf_test.h
cvs rdiff -u -r0 -r1.1 src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/npf/npf_ctl.c
diff -u src/sys/net/npf/npf_ctl.c:1.14 src/sys/net/npf/npf_ctl.c:1.15
--- src/sys/net/npf/npf_ctl.c:1.14	Sun Mar 11 18:27:59 2012
+++ src/sys/net/npf/npf_ctl.c	Wed May 30 21:38:03 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_ctl.c,v 1.14 2012/03/11 18:27:59 rmind Exp $	*/
+/*	$NetBSD: npf_ctl.c,v 1.15 2012/05/30 21:38:03 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.14 2012/03/11 18:27:59 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.15 2012/05/30 21:38:03 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -434,15 +434,14 @@ npfctl_reload(u_long cmd, void *data)
 	int error;
 
 	/* Retrieve the dictionary. */
-#ifdef _KERNEL
+#ifndef _NPF_TESTING
 	error = prop_dictionary_copyin_ioctl(pref, cmd, &npf_dict);
 	if (error)
 		return error;
 #else
-	npf_dict = prop_dictionary_internalize_from_file(data);
-	if (npf_dict == NULL)
-		return EINVAL;
+	npf_dict = (prop_dictionary_t)pref;
 #endif
+
 	/* Dictionary for error reporting. */
 	errdict = prop_dictionary_create();
 
@@ -507,7 +506,7 @@ fail:
 
 	/* Error report. */
 	prop_dictionary_set_int32(errdict, "errno", error);
-#ifdef _KERNEL
+#ifndef _NPF_TESTING
 	prop_dictionary_copyout_ioctl(pref, cmd, errdict);
 #endif
 	prop_object_release(errdict);
@@ -544,17 +543,11 @@ npfctl_update_rule(u_long cmd, void *dat
 	const char *name;
 	int error;
 
-#ifdef _KERNEL
 	/* Retrieve and construct the rule. */
 	error = prop_dictionary_copyin_ioctl(pref, cmd, &dict);
 	if (error) {
 		return error;
 	}
-#else
-	dict = prop_dictionary_internalize_from_file(data);
-	if (dict == NULL)
-		return EINVAL;
-#endif
 
 	/* Dictionary for error reporting. */
 	errdict = prop_dictionary_create();
@@ -580,9 +573,7 @@ out:		/* Error path. */
 
 	/* Error report. */
 	prop_dictionary_set_int32(errdict, "errno", error);
-#ifdef _KERNEL
 	prop_dictionary_copyout_ioctl(pref, cmd, errdict);
-#endif
 	prop_object_release(errdict);
 	return error;
 }
@@ -612,11 +603,7 @@ npfctl_sessions_save(u_long cmd, void *d
 	/* Set the session list, NAT policy list and export the dictionary. */
 	prop_dictionary_set(sesdict, "session-list", selist);
 	prop_dictionary_set(sesdict, "nat-policy-list", nplist);
-#ifdef _KERNEL
 	error = prop_dictionary_copyout_ioctl(pref, cmd, sesdict);
-#else
-	error = prop_dictionary_externalize_to_file(sesdict, data) ? 0 : errno;
-#endif
 fail:
 	prop_object_release(sesdict);
 	return error;
@@ -636,15 +623,10 @@ npfctl_sessions_load(u_long cmd, void *d
 	int error;
 
 	/* Retrieve the dictionary containing session and NAT policy lists. */
-#ifdef _KERNEL
 	error = prop_dictionary_copyin_ioctl(pref, cmd, &sesdict);
 	if (error)
 		return error;
-#else
-	sesdict = prop_dictionary_internalize_from_file(data);
-	if (sesdict == NULL)
-		return EINVAL;
-#endif
+
 	/*
 	 * Note: session objects contain the references to the NAT policy
 	 * entries.  Therefore, no need to directly access it.
Index: src/sys/net/npf/npf_impl.h
diff -u src/sys/net/npf/npf_impl.h:1.14 src/sys/net/npf/npf_impl.h:1.15
--- src/sys/net/npf/npf_impl.h:1.14	Sun May  6 02:45:25 2012
+++ src/sys/net/npf/npf_impl.h	Wed May 30 21:38:03 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_impl.h,v 1.14 2012/05/06 02:45:25 rmind Exp $	*/
+/*	$NetBSD: npf_impl.h,v 1.15 2012/05/30 21:38:03 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -115,6 +115,13 @@ typedef struct {
 	npf_tcpstate_t	nst_tcpst[2];
 } npf_state_t;
 
+#if defined(_NPF_TESTING)
+void		npf_state_sample(npf_state_t *, bool);
+#define	NPF_TCP_STATE_SAMPLE(n, r)	npf_state_sample(n, r)
+#else
+#define	NPF_TCP_STATE_SAMPLE(n, r)
+#endif
+
 /*
  * INTERFACES.
  */
@@ -149,6 +156,7 @@ void		npf_stats_dec(npf_stats_t);
 int		npf_pfil_register(void);
 void		npf_pfil_unregister(void);
 bool		npf_pfil_registered_p(void);
+int		npf_packet_handler(void *, struct mbuf **, ifnet_t *, int);
 void		npf_log_packet(npf_cache_t *, nbuf_t *, int);
 
 /* Protocol helpers. */

Index: src/sys/net/npf/npf_handler.c
diff -u src/sys/net/npf/npf_handler.c:1.16 src/sys/net/npf/npf_handler.c:1.17
--- src/sys/net/npf/npf_handler.c:1.16	Sun May  6 02:45:25 2012
+++ src/sys/net/npf/npf_handler.c	Wed May 30 21:38:03 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_handler.c,v 1.16 2012/05/06 02:45:25 rmind Exp $	*/
+/*	$NetBSD: npf_handler.c,v 1.17 2012/05/30 21:38:03 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.16 2012/05/06 02:45:25 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.17 2012/05/30 21:38:03 rmind Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -61,8 +61,6 @@ static struct pfil_head *	npf_ph_if = NU
 static struct pfil_head *	npf_ph_inet = NULL;
 static struct pfil_head *	npf_ph_inet6 = NULL;
 
-int	npf_packet_handler(void *, struct mbuf **, ifnet_t *, int);
-
 /*
  * npf_ifhook: hook handling interface changes.
  */

Index: src/sys/net/npf/npf_state.c
diff -u src/sys/net/npf/npf_state.c:1.6 src/sys/net/npf/npf_state.c:1.7
--- src/sys/net/npf/npf_state.c:1.6	Tue Nov 29 20:05:30 2011
+++ src/sys/net/npf/npf_state.c	Wed May 30 21:38:03 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_state.c,v 1.6 2011/11/29 20:05:30 rmind Exp $	*/
+/*	$NetBSD: npf_state.c,v 1.7 2012/05/30 21:38:03 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_state.c,v 1.6 2011/11/29 20:05:30 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_state.c,v 1.7 2012/05/30 21:38:03 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -134,6 +134,7 @@ npf_state_inspect(const npf_cache_t *npc
 	default:
 		ret = false;
 	}
+	NPF_TCP_STATE_SAMPLE(nst, ret);
 	mutex_exit(&nst->nst_lock);
 
 	if (__predict_false(!ret)) {

Index: src/sys/net/npf/npf_state_tcp.c
diff -u src/sys/net/npf/npf_state_tcp.c:1.4 src/sys/net/npf/npf_state_tcp.c:1.5
--- src/sys/net/npf/npf_state_tcp.c:1.4	Tue Apr  3 22:14:12 2012
+++ src/sys/net/npf/npf_state_tcp.c	Wed May 30 21:38:03 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_state_tcp.c,v 1.4 2012/04/03 22:14:12 rmind Exp $	*/
+/*	$NetBSD: npf_state_tcp.c,v 1.5 2012/05/30 21:38:03 rmind Exp $	*/
 
 /*-
  * Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.4 2012/04/03 22:14:12 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.5 2012/05/30 21:38:03 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -50,13 +50,6 @@ __KERNEL_RCSID(0, "$NetBSD: npf_state_tc
 
 #include "npf_impl.h"
 
-#if defined(_NPF_TESTING)
-void	npf_state_sample(npf_state_t *);
-#define	NPF_TCP_STATE_SAMPLE(nst)	npf_state_sample(nst)
-#else
-#define	NPF_TCP_STATE_SAMPLE(nst)
-#endif
-
 /*
  * NPF TCP states.  Note: these states are different from the TCP FSM
  * states of RFC 793.  The packet filter is a man-in-the-middle.
@@ -389,8 +382,6 @@ npf_tcp_inwindow(const npf_cache_t *npc,
 		end = fstate->nst_end;
 		seq = end;
 	}
-
-	NPF_TCP_STATE_SAMPLE(nst);
 #if 0
 	/* Strict in-order sequence for RST packets. */
 	if (((tcpfl & TH_RST) != 0) && (fstate->nst_end - seq) > 1) {
@@ -463,6 +454,7 @@ npf_state_tcp(const npf_cache_t *npc, nb
 	} else {
 		nstate = NPF_TCPS_CLOSED;
 	}
+
 	/* Determine whether TCP packet really belongs to this connection. */
 	if (!npf_tcp_inwindow(npc, nbuf, nst, di)) {
 		return false;
@@ -470,6 +462,7 @@ npf_state_tcp(const npf_cache_t *npc, nb
 	if (__predict_true(nstate == NPF_TCPS_OK)) {
 		return true;
 	}
+
 	nst->nst_state = nstate;
 	return true;
 }

Index: src/sys/rump/dev/lib/libnpf/Makefile
diff -u src/sys/rump/dev/lib/libnpf/Makefile:1.2 src/sys/rump/dev/lib/libnpf/Makefile:1.3
--- src/sys/rump/dev/lib/libnpf/Makefile:1.2	Sat Apr 14 19:01:22 2012
+++ src/sys/rump/dev/lib/libnpf/Makefile	Wed May 30 21:38:03 2012
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.2 2012/04/14 19:01:22 rmind Exp $
+#	$NetBSD: Makefile,v 1.3 2012/05/30 21:38:03 rmind Exp $
 #
 # Public Domain.
 #
@@ -16,6 +16,7 @@ SRCS+=	component.c
 
 WARNS=	4
 
+CPPFLAGS+=	-D_NPF_TESTING
 CPPFLAGS+=	-I${.CURDIR}/../../../librump/rumpvfs
 
 .include <bsd.lib.mk>

Index: src/usr.sbin/npf/npftest/Makefile
diff -u src/usr.sbin/npf/npftest/Makefile:1.1 src/usr.sbin/npf/npftest/Makefile:1.2
--- src/usr.sbin/npf/npftest/Makefile:1.1	Sat Apr 14 21:57:29 2012
+++ src/usr.sbin/npf/npftest/Makefile	Wed May 30 21:38:04 2012
@@ -1,19 +1,20 @@
-# $NetBSD: Makefile,v 1.1 2012/04/14 21:57:29 rmind Exp $
+# $NetBSD: Makefile,v 1.2 2012/05/30 21:38:04 rmind Exp $
 #
 # Public Domain
 #
 
 PROG=		npftest
 
-SRCS=		npftest.c
+SRCS=		npftest.c npfstream.c
 CPPFLAGS+=	-I${.CURDIR}
 
 LIBNPFTEST!=	cd ${.CURDIR}/libnpftest && ${MAKE} -V .OBJDIR
 DPADD+=		${LIBNPFTEST}/libnpftest.a
 LDADD+=		-L${LIBNPFTEST} -lnpftest
 
-LDADD+=		-lrump -lrumpvfs -lrumpnet -lrump -lrumpnet_net
-LDADD+=		-lrumpnet_virtif -lrumpdev_npf -lpthread
+LDADD+=		-lrump -lrumpvfs -lrumpnet -lrumpnet_net -lrumpdev_npf
+
+LDADD+=		-lpcap -lprop -lpthread
 
 WARNS=		4
 NOMAN=		# no man page
Index: src/usr.sbin/npf/npftest/npftest.c
diff -u src/usr.sbin/npf/npftest/npftest.c:1.1 src/usr.sbin/npf/npftest/npftest.c:1.2
--- src/usr.sbin/npf/npftest/npftest.c:1.1	Sat Apr 14 21:57:29 2012
+++ src/usr.sbin/npf/npftest/npftest.c	Wed May 30 21:38:04 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npftest.c,v 1.1 2012/04/14 21:57:29 rmind Exp $	*/
+/*	$NetBSD: npftest.c,v 1.2 2012/05/30 21:38:04 rmind Exp $	*/
 
 /*
  * NPF testing framework.
@@ -9,27 +9,44 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
+#include <string.h>
 #include <unistd.h>
 #include <assert.h>
+#include <fcntl.h>
+#include <err.h>
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <arpa/inet.h>
 
 #include <rump/rump.h>
+#include <rump/rump_syscalls.h>
 
 #include "npftest.h"
 
-static bool benchmark, verbose, quiet;
+static bool verbose, quiet;
 
 static void
 usage(void)
 {
-	printf("%s: [ -b ] [ -v ]\n", getprogname());
-	exit(EXIT_SUCCESS);
+	printf("usage: %s: [ -q | -v ] [ -c <config> ] "
+	    "[ -i 'interfaces' ] < -b | -t | -s file >\n"
+	    "\t-b: benchmark\n"
+	    "\t-t: regression test\n"
+	    "\t-c <config>: NPF configuration file\n"
+	    "\t-i 'interfaces': interfaces to create\n"
+	    "\t-q: quiet mode\n"
+	    "\t-s <file>: pcap stream\n"
+	    "\t-v: verbose mode\n",
+	    getprogname());
+	exit(EXIT_FAILURE);
 }
 
 static void
-result(const char *test, bool ok)
+result(const char *testcase, bool ok)
 {
 	if (!quiet) {
-		printf("NPF %-10s\t%s\n", test, ok ? "OK" : "fail");
+		printf("NPF %-10s\t%s\n", testcase, ok ? "OK" : "fail");
 	}
 	if (verbose) {
 		puts("-----");
@@ -39,17 +56,77 @@ result(const char *test, bool ok)
 	}
 }
 
+#if 0
+static void
+construct_interfaces(char *ifs)
+{
+	char *ifname, *addr, *mask, *sptr;
+
+	/*
+	 * Format: ifname0[,ip0,mask1];ifname1,...
+	 */
+	ifname = strtok_r(ifs, ";", &sptr);
+	while (ifname) {
+		/* Address and netmask. */
+		addr = strchr(ifname, ',');
+		if (addr) {
+			*addr++ = '\0';
+		}
+		mask = strchr(addr, ',');
+		if (mask) {
+			*mask++ = '\0';
+		}
+
+		/* Construct; next.. */
+		setup_rump_if(ifname, addr, mask);
+		ifname = strtok_r(NULL, ";", &sptr);
+	}
+}
+#endif
+
+static void
+load_npf_config(const char *config)
+{
+	prop_dictionary_t npf_dict;
+	void *xml;
+	int error;
+
+	npf_dict = prop_dictionary_internalize_from_file(config);
+	if (!npf_dict) {
+		err(EXIT_FAILURE, "prop_dictionary_internalize_from_file");
+	}
+	xml = prop_dictionary_externalize(npf_dict);
+	prop_object_release(npf_dict);
+
+	error = rumpns_npf_test_load(xml);
+	if (error) {
+		errx(EXIT_FAILURE, "npf_test_load: %s\n", strerror(error));
+	}
+	free(xml);
+
+	if (verbose) {
+		printf("Loaded NPF config at '%s'\n", config);
+	}
+}
+
 int
 main(int argc, char **argv)
 {
-	bool ok;
+	bool benchmark, test, ok;
+	char *config, *interfaces, *stream;
 	int ch;
 
 	benchmark = false;
+	test = false;
+
+	config = NULL;
+	interfaces = NULL;
+	stream = NULL;
+
 	verbose = false;
 	quiet = false;
 
-	while ((ch = getopt(argc, argv, "bqv")) != -1) {
+	while ((ch = getopt(argc, argv, "bqvc:i:s:t")) != -1) {
 		switch (ch) {
 		case 'b':
 			benchmark = true;
@@ -60,11 +137,28 @@ main(int argc, char **argv)
 		case 'v':
 			verbose = true;
 			break;
+		case 'c':
+			config = optarg;
+			break;
+		case 'i':
+			interfaces = optarg;
+			break;
+		case 's':
+			stream = optarg;
+			break;
+		case 't':
+			test = true;
+			break;
 		default:
 			usage();
 		}
 	}
 
+	/* Either benchmark or test. */
+	if (benchmark == test && (!stream || !interfaces)) {
+		usage();
+	}
+
 	/* XXX rn_init */
 	extern int rumpns_max_keylen;
 	rumpns_max_keylen = 1;
@@ -72,14 +166,30 @@ main(int argc, char **argv)
 	rump_init();
 	rump_schedule();
 
-	ok = rumpns_npf_nbuf_test(verbose);
-	result("nbuf", ok);
+	if (config) {
+		load_npf_config(config);
+	}
+
+	if (test) {
+		ok = rumpns_npf_nbuf_test(verbose);
+		result("nbuf", ok);
 
-	ok = rumpns_npf_processor_test(verbose);
-	result("processor", ok);
+		ok = rumpns_npf_processor_test(verbose);
+		result("processor", ok);
 
-	ok = rumpns_npf_table_test(verbose);
-	result("table", ok);
+		ok = rumpns_npf_table_test(verbose);
+		result("table", ok);
+	}
+
+	if (stream) {
+		unsigned idx = if_nametoindex(interfaces);
+		if (idx == 0) {
+			err(EXIT_FAILURE, "if_nametoindex");
+		} else if (verbose) {
+			printf("Interface %s index %u\n", interfaces, idx);
+		}
+		process_stream(stream, NULL, idx);
+	}
 
 	rump_unschedule();
 
Index: src/usr.sbin/npf/npftest/npftest.h
diff -u src/usr.sbin/npf/npftest/npftest.h:1.1 src/usr.sbin/npf/npftest/npftest.h:1.2
--- src/usr.sbin/npf/npftest/npftest.h:1.1	Sat Apr 14 21:57:29 2012
+++ src/usr.sbin/npf/npftest/npftest.h	Wed May 30 21:38:04 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npftest.h,v 1.1 2012/04/14 21:57:29 rmind Exp $	*/
+/*	$NetBSD: npftest.h,v 1.2 2012/05/30 21:38:04 rmind Exp $	*/
 
 /*
  * Public Domain.
@@ -7,10 +7,17 @@
 #ifndef _NPF_TEST_H_
 #define _NPF_TEST_H_
 
+#include <stdint.h>
 #include <stdbool.h>
 
+int		rumpns_npf_test_load(const void *);
+int		rumpns_npf_test_handlepkt(const void *, size_t,
+		    unsigned, bool, int64_t *);
+
 bool		rumpns_npf_nbuf_test(bool);
 bool		rumpns_npf_processor_test(bool);
 bool		rumpns_npf_table_test(bool);
 
+int		process_stream(const char *, const char *, unsigned);
+
 #endif

Index: src/usr.sbin/npf/npftest/libnpftest/Makefile
diff -u src/usr.sbin/npf/npftest/libnpftest/Makefile:1.1 src/usr.sbin/npf/npftest/libnpftest/Makefile:1.2
--- src/usr.sbin/npf/npftest/libnpftest/Makefile:1.1	Sat Apr 14 21:57:29 2012
+++ src/usr.sbin/npf/npftest/libnpftest/Makefile	Wed May 30 21:38:04 2012
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.1 2012/04/14 21:57:29 rmind Exp $
+# $NetBSD: Makefile,v 1.2 2012/05/30 21:38:04 rmind Exp $
 #
 # Public Domain
 #
@@ -8,12 +8,14 @@ RUMPTOP=	${.CURDIR}/../../../../sys/rump
 LIB=		npftest
 LIBISPRIVATE=	yes
 
+SRCS+=		npf_test_subr.c
 SRCS+=		npf_mbuf_subr.c
 
 SRCS+=		npf_nbuf_test.c
 SRCS+=		npf_processor_test.c
 SRCS+=		npf_table_test.c
 
+CPPFLAGS+=	-D_NPF_TESTING
 CPPFLAGS+=	-I${.CURDIR}/../../../../sys/net/npf
 CPPFLAGS+=	-I${RUMPTOP}/librump/rumpkern
 
Index: src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c
diff -u src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c:1.1 src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c:1.2
--- src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c:1.1	Sat Apr 14 21:57:29 2012
+++ src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c	Wed May 30 21:38:04 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_mbuf_subr.c,v 1.1 2012/04/14 21:57:29 rmind Exp $	*/
+/*	$NetBSD: npf_mbuf_subr.c,v 1.2 2012/05/30 21:38:04 rmind Exp $	*/
 
 /*
  * NPF testing - helper routines.
@@ -13,13 +13,15 @@
 #include "npf_test.h"
 
 struct mbuf *
-mbuf_getwithdata(void *data, size_t len)
+mbuf_getwithdata(const void *data, size_t len)
 {
 	struct mbuf *m;
+	void *dst;
 
-	m = kmem_zalloc(sizeof(struct mbuf), KM_SLEEP);
+	m = m_gethdr(M_WAITOK, MT_HEADER);
 	assert(m != NULL);
-	m->m_data = data;
+	dst = mtod(m, void *);
+	memcpy(dst, data, len);
 	m->m_len = len;
 	return m;
 }
Index: src/usr.sbin/npf/npftest/libnpftest/npf_test.h
diff -u src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.1 src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.2
--- src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.1	Sat Apr 14 21:57:29 2012
+++ src/usr.sbin/npf/npftest/libnpftest/npf_test.h	Wed May 30 21:38:04 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_test.h,v 1.1 2012/04/14 21:57:29 rmind Exp $	*/
+/*	$NetBSD: npf_test.h,v 1.2 2012/05/30 21:38:04 rmind Exp $	*/
 
 /*
  * Public Domain.
@@ -24,7 +24,11 @@
 #include <net/if_ether.h>
 #include <net/ethertypes.h>
 
-struct mbuf *	mbuf_getwithdata(void *, size_t);
+int		npf_test_load(const void *);
+int		npf_test_handlepkt(const void *, size_t, unsigned,
+		    bool, int64_t *);
+
+struct mbuf *	mbuf_getwithdata(const void *, size_t);
 struct mbuf *	mbuf_construct_ether(int);
 struct mbuf *	mbuf_construct(int);
 void *		mbuf_return_hdrs(struct mbuf *, bool, struct ip **);

Added files:

Index: src/usr.sbin/npf/npftest/npfstream.c
diff -u /dev/null src/usr.sbin/npf/npftest/npfstream.c:1.1
--- /dev/null	Wed May 30 21:38:04 2012
+++ src/usr.sbin/npf/npftest/npfstream.c	Wed May 30 21:38:04 2012
@@ -0,0 +1,117 @@
+/*	$NetBSD: npfstream.c,v 1.1 2012/05/30 21:38:04 rmind Exp $	*/
+
+/*
+ * NPF stream processor.
+ *
+ * Public Domain.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <inttypes.h>
+#include <err.h>
+#include <pcap.h>
+
+#include <arpa/inet.h>
+
+#include <net/if.h>
+#include <net/ethertypes.h>
+#include <net/if_ether.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include <rump/rump.h>
+
+#include "npftest.h"
+
+static struct in_addr	initial_ip;
+static int		snd_packet_no = 0;
+static int		rcv_packet_no = 0;
+
+static void
+process_tcpip(const void *data, size_t len, FILE *fp, unsigned idx)
+{
+	const struct ether_header *eth = data;
+	const struct ip *ip;
+	const struct tcphdr *th;
+	unsigned hlen, tcpdlen;
+	int error, packetno;
+	tcp_seq seq;
+	bool forw;
+
+	if (ntohs(eth->ether_type) != ETHERTYPE_IP) {
+		errx(EXIT_FAILURE, "process_tcpip: not IP protocol (%d)",
+		    eth->ether_type);
+	}
+	ip = (const struct ip *)(eth + 1);
+	hlen = ip->ip_hl << 2;
+	th = (const struct tcphdr *)((const uint8_t *)ip + hlen);
+
+	tcpdlen = ntohs(ip->ip_len) - hlen - (th->th_off << 2);
+	if (th->th_flags & TH_SYN) {
+		tcpdlen++;
+	}
+	if (th->th_flags & TH_FIN) {
+		tcpdlen++;
+	}
+	seq = ntohl(th->th_seq);
+
+	if (snd_packet_no == 0) {
+		memcpy(&initial_ip, &ip->ip_src, sizeof(struct in_addr));
+	}
+
+	forw = (initial_ip.s_addr == ip->ip_src.s_addr);
+	packetno = forw ? ++snd_packet_no : ++rcv_packet_no;
+
+	int64_t result[9];
+	memset(result, 0, sizeof(result));
+
+	len = ntohs(ip->ip_len);
+	error = rumpns_npf_test_handlepkt(ip, len, idx, forw, result);
+
+	fprintf(fp, "%s%2x %5d %3d %11u %11u %11u %11u %12lx",
+	    forw ? ">" : "<", (th->th_flags & (TH_SYN | TH_ACK | TH_FIN)),
+	    packetno, error, (u_int)seq, (u_int)ntohl(th->th_ack),
+	    (u_int)(seq + tcpdlen), ntohs(th->th_win), (uintptr_t)result[0]);
+
+	for (unsigned i = 1; i < __arraycount(result); i++) {
+		fprintf(fp, "%11" PRIu64 " ", result[i]);
+	}
+	fputs("\n", fp);
+}
+
+int
+process_stream(const char *input, const char *output, unsigned idx)
+{
+	pcap_t *pcap;
+	char pcap_errbuf[PCAP_ERRBUF_SIZE];
+	struct pcap_pkthdr *phdr;
+	const uint8_t *data;
+	FILE *fp;
+
+	pcap = pcap_open_offline(input, pcap_errbuf);
+	if (pcap == NULL) {
+		errx(EXIT_FAILURE, "pcap_open_offline failed: %s", pcap_errbuf);
+	}
+	fp = output ? fopen(output, "w") : stdout;
+	if (fp == NULL) {
+		err(EXIT_FAILURE, "fopen");
+	}
+	fprintf(fp, "#   %5s %3s %11s %11s %11s %11s %11s %11s %11s\n",
+	    "No", "Err", "Seq", "Ack", "TCP Len", "Win",
+	    "Stream", "RetVal", "State");
+	while (pcap_next_ex(pcap, &phdr, &data) > 0) {
+		if (phdr->len != phdr->caplen) {
+			warnx("process_stream: truncated packet");
+		}
+		process_tcpip(data, phdr->caplen, fp, idx);
+	}
+	pcap_close(pcap);
+	fclose(fp);
+
+	return 0;
+}

Index: src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c
diff -u /dev/null src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c:1.1
--- /dev/null	Wed May 30 21:38:04 2012
+++ src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c	Wed May 30 21:38:04 2012
@@ -0,0 +1,74 @@
+/*	$NetBSD: npf_test_subr.c,v 1.1 2012/05/30 21:38:04 rmind Exp $	*/
+
+/*
+ * NPF initialisation and handler routines.
+ *
+ * Public Domain.
+ */
+
+#include <sys/types.h>
+#include <net/if.h>
+#include <net/if_types.h>
+
+#include "npf_impl.h"
+#include "npf_test.h"
+
+/* State of the current stream. */
+static npf_state_t	cstream_state;
+static void *		cstream_ptr;
+static bool		cstream_retval;
+
+int
+npf_test_load(const void *xml)
+{
+	prop_dictionary_t npf_dict = prop_dictionary_internalize(xml);
+	return npfctl_reload(0, npf_dict);
+}
+
+/*
+ * State sampler - this routine is called from inside of NPF state engine.
+ */
+void
+npf_state_sample(npf_state_t *nst, bool retval)
+{
+	/* Pointer will serve as an ID. */
+	cstream_ptr = nst;
+	memcpy(&cstream_state, nst, sizeof(npf_state_t));
+	cstream_retval = retval;
+}
+
+int
+npf_test_handlepkt(const void *data, size_t len, unsigned idx,
+    bool forw, int64_t *result)
+{
+	ifnet_t ifp = { .if_index = idx };
+	struct mbuf *m;
+	int i = 0, error;
+
+	m = mbuf_getwithdata(data, len);
+	error = npf_packet_handler(NULL, &m, &ifp, forw ? PFIL_OUT : PFIL_IN);
+	if (error) {
+		assert(m == NULL);
+		return error;
+	}
+	assert(m != NULL);
+	m_freem(m);
+
+	const int di = forw ? NPF_FLOW_FORW : NPF_FLOW_BACK;
+	npf_tcpstate_t *fstate = &cstream_state.nst_tcpst[di];
+	npf_tcpstate_t *tstate = &cstream_state.nst_tcpst[!di];
+
+	result[i++] = (intptr_t)cstream_ptr;
+	result[i++] = cstream_retval;
+	result[i++] = cstream_state.nst_state;
+
+	result[i++] = fstate->nst_end;
+	result[i++] = fstate->nst_maxend;
+	result[i++] = fstate->nst_maxwin;
+
+	result[i++] = tstate->nst_end;
+	result[i++] = tstate->nst_maxend;
+	result[i++] = tstate->nst_maxwin;
+
+	return 0;
+}

Reply via email to