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; +}