Module Name: src Committed By: tls Date: Sun Aug 10 07:00:01 UTC 2014
Modified Files: src/usr.sbin/npf [tls-earlyentropy]: Makefile src/usr.sbin/npf/npfctl [tls-earlyentropy]: npf.conf.5 npf_bpf_comp.c npf_build.c npf_scan.l npf_show.c npfctl.8 npfctl.c npfctl.h src/usr.sbin/npf/npftest [tls-earlyentropy]: README src/usr.sbin/npf/npftest/libnpftest [tls-earlyentropy]: npf_bpf_test.c npf_nat_test.c npf_perf_test.c npf_rule_test.c npf_state_test.c npf_test_subr.c Added Files: src/usr.sbin/npf [tls-earlyentropy]: npf.7 Log Message: Rebase. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.4.6.1 src/usr.sbin/npf/Makefile cvs rdiff -u -r0 -r1.1.2.2 src/usr.sbin/npf/npf.7 cvs rdiff -u -r1.39 -r1.39.2.1 src/usr.sbin/npf/npfctl/npf.conf.5 cvs rdiff -u -r1.4 -r1.4.2.1 src/usr.sbin/npf/npfctl/npf_bpf_comp.c cvs rdiff -u -r1.36 -r1.36.2.1 src/usr.sbin/npf/npfctl/npf_build.c \ src/usr.sbin/npf/npfctl/npfctl.h cvs rdiff -u -r1.20 -r1.20.2.1 src/usr.sbin/npf/npfctl/npf_scan.l cvs rdiff -u -r1.13 -r1.13.2.1 src/usr.sbin/npf/npfctl/npf_show.c cvs rdiff -u -r1.15 -r1.15.2.1 src/usr.sbin/npf/npfctl/npfctl.8 cvs rdiff -u -r1.40 -r1.40.2.1 src/usr.sbin/npf/npfctl/npfctl.c cvs rdiff -u -r1.4 -r1.4.6.1 src/usr.sbin/npf/npftest/README cvs rdiff -u -r1.4 -r1.4.2.1 \ src/usr.sbin/npf/npftest/libnpftest/npf_bpf_test.c cvs rdiff -u -r1.8 -r1.8.2.1 \ src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c cvs rdiff -u -r1.3 -r1.3.2.1 \ src/usr.sbin/npf/npftest/libnpftest/npf_perf_test.c cvs rdiff -u -r1.10 -r1.10.2.1 \ src/usr.sbin/npf/npftest/libnpftest/npf_rule_test.c cvs rdiff -u -r1.5 -r1.5.2.1 \ src/usr.sbin/npf/npftest/libnpftest/npf_state_test.c cvs rdiff -u -r1.9.2.1 -r1.9.2.2 \ 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/usr.sbin/npf/Makefile diff -u src/usr.sbin/npf/Makefile:1.4 src/usr.sbin/npf/Makefile:1.4.6.1 --- src/usr.sbin/npf/Makefile:1.4 Thu Sep 13 21:02:50 2012 +++ src/usr.sbin/npf/Makefile Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.4 2012/09/13 21:02:50 martin Exp $ +# $NetBSD: Makefile,v 1.4.6.1 2014/08/10 07:00:01 tls Exp $ .include <bsd.own.mk> @@ -8,4 +8,7 @@ SUBDIR= npfctl SUBDIR+= npftest .endif +MAN= npf.7 + +.include <bsd.man.mk> .include <bsd.subdir.mk> Index: src/usr.sbin/npf/npfctl/npf.conf.5 diff -u src/usr.sbin/npf/npfctl/npf.conf.5:1.39 src/usr.sbin/npf/npfctl/npf.conf.5:1.39.2.1 --- src/usr.sbin/npf/npfctl/npf.conf.5:1.39 Fri Feb 14 01:52:58 2014 +++ src/usr.sbin/npf/npfctl/npf.conf.5 Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: npf.conf.5,v 1.39 2014/02/14 01:52:58 rmind Exp $ +.\" $NetBSD: npf.conf.5,v 1.39.2.1 2014/08/10 07:00:01 tls Exp $ .\" .\" Copyright (c) 2009-2014 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd February 14, 2014 +.Dd August 2, 2014 .Dt NPF.CONF 5 .Os .Sh NAME @@ -155,6 +155,25 @@ block out final pcap-filter "tcp and dst .Pp Fragments are not selectable since NPF always reassembles packets before further processing. +.Ss Stateful +Stateful packet inspection is enabled using +.Cd stateful +or +.Cd stateful-ends +keywords. +The former creates a state which is uniquely identified by a 5-tuple (source +and destination IP addresses, port numbers and an interface identifier). +The latter excludes the interface identifier and must be used with +precaution. +In both cases, a full TCP state tracking is performed for TCP connections +and a limited tracking for message-based protocols (UDP and ICMP). +.Pp +By default, a stateful rule implies SYN-only flag check ("flags S/SAFR") +for the TCP packets. +It is not advisable to change this behavior; however, +it can be overridden with the +.Cd flags +keyword. .Ss Map Network Address Translation (NAT) is expressed in a form of segment mapping. The translation may be dynamic (stateful) or static (stateless). @@ -252,7 +271,8 @@ rule-list = [ rule new-line ] rule-list npf-filter = [ "family" family-opt ] [ "proto" protocol [ proto-opts ] ] ( "all" | filt-opts ) -static-rule = ( "block" [ block-opts ] | "pass" ) [ "stateful" ] +static-rule = ( "block" [ block-opts ] | "pass" ) + [ "stateful" | "stateful-ends" ] [ "in" | out" ] [ "final" ] [ "on" interface ] ( npf-filter | "pcap-filter" pcap-filter-expr ) [ "apply" proc-name ] @@ -332,6 +352,7 @@ group default { .\" ----- .Sh SEE ALSO .Xr bpf 4 , +.Xr npf 7 , .Xr pcap-filter 7 , .Xr npfctl 8 .Sh HISTORY Index: src/usr.sbin/npf/npfctl/npf_bpf_comp.c diff -u src/usr.sbin/npf/npfctl/npf_bpf_comp.c:1.4 src/usr.sbin/npf/npfctl/npf_bpf_comp.c:1.4.2.1 --- src/usr.sbin/npf/npfctl/npf_bpf_comp.c:1.4 Sat Mar 15 08:46:01 2014 +++ src/usr.sbin/npf/npfctl/npf_bpf_comp.c Sun Aug 10 07:00:01 2014 @@ -1,7 +1,7 @@ -/* $NetBSD: npf_bpf_comp.c,v 1.4 2014/03/15 08:46:01 rmind Exp $ */ +/* $NetBSD: npf_bpf_comp.c,v 1.4.2.1 2014/08/10 07:00:01 tls Exp $ */ /*- - * Copyright (c) 2010-2013 The NetBSD Foundation, Inc. + * Copyright (c) 2010-2014 The NetBSD Foundation, Inc. * All rights reserved. * * This material is based upon work partially supported by The @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_bpf_comp.c,v 1.4 2014/03/15 08:46:01 rmind Exp $"); +__RCSID("$NetBSD: npf_bpf_comp.c,v 1.4.2.1 2014/08/10 07:00:01 tls Exp $"); #include <stdlib.h> #include <stdbool.h> @@ -62,7 +62,8 @@ __RCSID("$NetBSD: npf_bpf_comp.c,v 1.4 2 * something other than L4 header offset. Generally, when BPF_LDX is used. */ #define FETCHED_L3 0x01 -#define X_EQ_L4OFF 0x02 +#define CHECKED_L4 0x02 +#define X_EQ_L4OFF 0x04 struct npf_bpf { /* @@ -283,8 +284,7 @@ fetch_l3(npf_bpf_t *ctx, sa_family_t af, } /* - * Fetch L3 information. The coprocessor populates the following - * words in the scratch memory store: + * The memory store is populated with: * - BPF_MW_IPVER: IP version (4 or 6). * - BPF_MW_L4OFF: L4 header offset. * - BPF_MW_L4PROTO: L4 protocol. @@ -307,21 +307,12 @@ fetch_l3(npf_bpf_t *ctx, sa_family_t af, * A <- IP version; A == expected-version? * If no particular version specified, check for non-zero. */ - if ((ctx->flags & FETCHED_L3) == 0) { - struct bpf_insn insns_l3[] = { - BPF_STMT(BPF_MISC+BPF_COP, NPF_COP_L3), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ver, jt, jf), - }; - add_insns(ctx, insns_l3, __arraycount(insns_l3)); - ctx->flags |= FETCHED_L3; - } else { - /* IP version is already fetched in BPF_MW_IPVER. */ - struct bpf_insn insns_af[] = { - BPF_STMT(BPF_LD+BPF_W+BPF_MEM, BPF_MW_IPVER), - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ver, jt, jf), - }; - add_insns(ctx, insns_af, __arraycount(insns_af)); - } + struct bpf_insn insns_af[] = { + BPF_STMT(BPF_LD+BPF_W+BPF_MEM, BPF_MW_IPVER), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ver, jt, jf), + }; + add_insns(ctx, insns_af, __arraycount(insns_af)); + ctx->flags |= FETCHED_L3; ctx->af = af; if (af) { @@ -369,6 +360,7 @@ npfctl_bpf_proto(npf_bpf_t *ctx, sa_fami uint32_t mwords[] = { BM_PROTO, 1, proto }; done_block(ctx, mwords, sizeof(mwords)); + ctx->flags |= CHECKED_L4; } /* @@ -471,6 +463,7 @@ npfctl_bpf_ports(npf_bpf_t *ctx, u_int o /* TCP and UDP port offsets are the same. */ assert(sport_off == offsetof(struct tcphdr, th_sport)); assert(dport_off == offsetof(struct tcphdr, th_dport)); + assert(ctx->flags & CHECKED_L4); assert(((opts & MATCH_SRC) != 0) ^ ((opts & MATCH_DST) != 0)); off = (opts & MATCH_SRC) ? sport_off : dport_off; @@ -513,12 +506,26 @@ npfctl_bpf_ports(npf_bpf_t *ctx, u_int o * npfctl_bpf_tcpfl: code block to match TCP flags. */ void -npfctl_bpf_tcpfl(npf_bpf_t *ctx, uint8_t tf, uint8_t tf_mask) +npfctl_bpf_tcpfl(npf_bpf_t *ctx, uint8_t tf, uint8_t tf_mask, bool checktcp) { const u_int tcpfl_off = offsetof(struct tcphdr, th_flags); + const bool usingmask = tf_mask != tf; /* X <- IP header length */ fetch_l3(ctx, AF_UNSPEC, X_EQ_L4OFF); + if (checktcp) { + const u_int jf = usingmask ? 3 : 2; + assert(ctx->ingroup == false); + + /* A <- L4 protocol; A == TCP? If not, jump out. */ + struct bpf_insn insns_tcp[] = { + BPF_STMT(BPF_LD+BPF_W+BPF_MEM, BPF_MW_L4PROTO), + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_TCP, 0, jf), + }; + add_insns(ctx, insns_tcp, __arraycount(insns_tcp)); + } else { + assert(ctx->flags & CHECKED_L4); + } struct bpf_insn insns_tf[] = { /* A <- TCP flags */ @@ -526,7 +533,7 @@ npfctl_bpf_tcpfl(npf_bpf_t *ctx, uint8_t }; add_insns(ctx, insns_tf, __arraycount(insns_tf)); - if (tf_mask != tf) { + if (usingmask) { /* A <- (A & mask) */ struct bpf_insn insns_mask[] = { BPF_STMT(BPF_ALU+BPF_AND+BPF_K, tf_mask), @@ -540,8 +547,10 @@ npfctl_bpf_tcpfl(npf_bpf_t *ctx, uint8_t }; add_insns(ctx, insns_cmp, __arraycount(insns_cmp)); - uint32_t mwords[] = { BM_TCPFL, 2, tf, tf_mask}; - done_block(ctx, mwords, sizeof(mwords)); + if (!checktcp) { + uint32_t mwords[] = { BM_TCPFL, 2, tf, tf_mask}; + done_block(ctx, mwords, sizeof(mwords)); + } } /* @@ -554,6 +563,7 @@ npfctl_bpf_icmp(npf_bpf_t *ctx, int type const u_int type_off = offsetof(struct icmp, icmp_type); const u_int code_off = offsetof(struct icmp, icmp_code); + assert(ctx->flags & CHECKED_L4); assert(offsetof(struct icmp6_hdr, icmp6_type) == type_off); assert(offsetof(struct icmp6_hdr, icmp6_code) == code_off); assert(type != -1 || code != -1); Index: src/usr.sbin/npf/npfctl/npf_build.c diff -u src/usr.sbin/npf/npfctl/npf_build.c:1.36 src/usr.sbin/npf/npfctl/npf_build.c:1.36.2.1 --- src/usr.sbin/npf/npfctl/npf_build.c:1.36 Thu Feb 13 03:34:40 2014 +++ src/usr.sbin/npf/npfctl/npf_build.c Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_build.c,v 1.36 2014/02/13 03:34:40 rmind Exp $ */ +/* $NetBSD: npf_build.c,v 1.36.2.1 2014/08/10 07:00:01 tls Exp $ */ /*- * Copyright (c) 2011-2014 The NetBSD Foundation, Inc. @@ -34,11 +34,12 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_build.c,v 1.36 2014/02/13 03:34:40 rmind Exp $"); +__RCSID("$NetBSD: npf_build.c,v 1.36.2.1 2014/08/10 07:00:01 tls Exp $"); #include <sys/types.h> #include <sys/mman.h> #include <sys/stat.h> +#include <netinet/tcp.h> #include <stdlib.h> #include <inttypes.h> @@ -267,7 +268,7 @@ npfctl_build_proto(npf_bpf_t *ctx, sa_fa assert(npfvar_get_count(popts) == 2); tf = npfvar_get_data(popts, NPFVAR_TCPFLAG, 0); tf_mask = npfvar_get_data(popts, NPFVAR_TCPFLAG, 1); - npfctl_bpf_tcpfl(ctx, *tf, *tf_mask); + npfctl_bpf_tcpfl(ctx, *tf, *tf_mask, false); } break; case IPPROTO_ICMP: @@ -292,10 +293,10 @@ static bool npfctl_build_code(nl_rule_t *rl, sa_family_t family, const opt_proto_t *op, const filt_opts_t *fopts) { + bool noproto, noaddrs, noports, need_tcpudp = false; const addr_port_t *apfrom = &fopts->fo_from; const addr_port_t *apto = &fopts->fo_to; const int proto = op->op_proto; - bool noproto, noaddrs, noports; npf_bpf_t *bc; size_t len; @@ -316,7 +317,9 @@ npfctl_build_code(nl_rule_t *rl, sa_fami switch (proto) { case IPPROTO_TCP: case IPPROTO_UDP: + break; case -1: + need_tcpudp = true; break; default: yyerror("invalid filter options for protocol %d", proto); @@ -328,11 +331,28 @@ npfctl_build_code(nl_rule_t *rl, sa_fami /* Build layer 4 protocol blocks. */ npfctl_build_proto(bc, family, op); + /* + * If this is a stateful rule and TCP flags are not specified, + * then add "flags S/SAFR" filter for TCP protocol case. + */ + if ((npf_rule_getattr(rl) & NPF_RULE_STATEFUL) != 0 && + (proto == -1 || (proto == IPPROTO_TCP && !op->op_opts))) { + npfctl_bpf_tcpfl(bc, TH_SYN, + TH_SYN | TH_ACK | TH_FIN | TH_RST, proto == -1); + } + /* Build IP address blocks. */ npfctl_build_vars(bc, family, apfrom->ap_netaddr, MATCH_SRC); npfctl_build_vars(bc, family, apto->ap_netaddr, MATCH_DST); /* Build port-range blocks. */ + if (need_tcpudp) { + /* TCP/UDP check for the ports. */ + npfctl_bpf_group(bc); + npfctl_bpf_proto(bc, AF_UNSPEC, IPPROTO_TCP); + npfctl_bpf_proto(bc, AF_UNSPEC, IPPROTO_UDP); + npfctl_bpf_endgroup(bc); + } npfctl_build_vars(bc, family, apfrom->ap_portrange, MATCH_SRC); npfctl_build_vars(bc, family, apto->ap_portrange, MATCH_DST); Index: src/usr.sbin/npf/npfctl/npfctl.h diff -u src/usr.sbin/npf/npfctl/npfctl.h:1.36 src/usr.sbin/npf/npfctl/npfctl.h:1.36.2.1 --- src/usr.sbin/npf/npfctl/npfctl.h:1.36 Thu Feb 13 03:34:40 2014 +++ src/usr.sbin/npf/npfctl/npfctl.h Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npfctl.h,v 1.36 2014/02/13 03:34:40 rmind Exp $ */ +/* $NetBSD: npfctl.h,v 1.36.2.1 2014/08/10 07:00:01 tls Exp $ */ /*- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ #define NPF_DEV_PATH "/dev/npf" #define NPF_CONF_PATH "/etc/npf.conf" -#define NPF_SESSDB_PATH "/var/db/npf_sessions.db" +#define NPF_DB_PATH "/var/db/npf.db" typedef struct fam_addr_mask { sa_family_t fam_family; @@ -166,7 +166,7 @@ void npfctl_bpf_proto(npf_bpf_t *, sa_f void npfctl_bpf_cidr(npf_bpf_t *, u_int, sa_family_t, const npf_addr_t *, const npf_netmask_t); void npfctl_bpf_ports(npf_bpf_t *, u_int, in_port_t, in_port_t); -void npfctl_bpf_tcpfl(npf_bpf_t *, uint8_t, uint8_t); +void npfctl_bpf_tcpfl(npf_bpf_t *, uint8_t, uint8_t, bool); void npfctl_bpf_icmp(npf_bpf_t *, int, int); void npfctl_bpf_table(npf_bpf_t *, u_int, u_int); Index: src/usr.sbin/npf/npfctl/npf_scan.l diff -u src/usr.sbin/npf/npfctl/npf_scan.l:1.20 src/usr.sbin/npf/npfctl/npf_scan.l:1.20.2.1 --- src/usr.sbin/npf/npfctl/npf_scan.l:1.20 Fri Mar 14 11:29:45 2014 +++ src/usr.sbin/npf/npfctl/npf_scan.l Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_scan.l,v 1.20 2014/03/14 11:29:45 rmind Exp $ */ +/* $NetBSD: npf_scan.l,v 1.20.2.1 2014/08/10 07:00:01 tls Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -84,6 +84,7 @@ npfctl_parse_string(const char *str) ID [a-zA-Z_][a-zA-Z_0-9]* DID [a-zA-Z_][a-zA-Z_0-9-]* NUMBER [0-9]+ +HEXDIG [0-9a-fA-F]+ %% alg return ALG; @@ -151,7 +152,7 @@ any return ANY; "," return COMMA; "=" return EQ; -"0x"[0-9a-fA-F]+ { +"0x"{HEXDIG} { char *endp, *buf = ecalloc(1, yyleng + 1); buf[yyleng] = 0; yylval.num = strtoul(buf+2, &endp, 16); @@ -166,7 +167,12 @@ any return ANY; return FPNUM; } -[0-9a-fA-F]+":"[0-9a-fA-F:]* { +{HEXDIG}":"[0-9a-fA-F:]* { + yylval.str = estrndup(yytext, yyleng); + return IPV6ADDR; + } + +"::"{HEXDIG}[0-9a-fA-F:]* { yylval.str = estrndup(yytext, yyleng); return IPV6ADDR; } Index: src/usr.sbin/npf/npfctl/npf_show.c diff -u src/usr.sbin/npf/npfctl/npf_show.c:1.13 src/usr.sbin/npf/npfctl/npf_show.c:1.13.2.1 --- src/usr.sbin/npf/npfctl/npf_show.c:1.13 Fri Mar 14 11:29:45 2014 +++ src/usr.sbin/npf/npfctl/npf_show.c Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_show.c,v 1.13 2014/03/14 11:29:45 rmind Exp $ */ +/* $NetBSD: npf_show.c,v 1.13.2.1 2014/08/10 07:00:01 tls Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_show.c,v 1.13 2014/03/14 11:29:45 rmind Exp $"); +__RCSID("$NetBSD: npf_show.c,v 1.13.2.1 2014/08/10 07:00:01 tls Exp $"); #include <sys/socket.h> #include <netinet/in.h> @@ -248,7 +248,7 @@ static const struct mark_keyword_mapent u_int fwords; } mark_keyword_map[] = { { BM_IPVER, "family %s", NULL, print_family, 1 }, - { BM_PROTO, "proto %s", NULL, print_proto, 1 }, + { BM_PROTO, "proto %s", ", ", print_proto, 1 }, { BM_TCPFL, "flags %s", NULL, print_tcpflags, 2 }, { BM_ICMP_TYPE, "icmp-type %s", NULL, print_number, 1 }, { BM_ICMP_CODE, "code %s", NULL, print_number, 1 }, @@ -452,7 +452,7 @@ npfctl_config_show(int fd) if (ncf == NULL) { return errno; } - fprintf(ctx->fp, "Filtering:\t%s\nConfiguration:\t%s\n", + fprintf(ctx->fp, "# filtering:\t%s\n# config:\t%s\n", active ? "active" : "inactive", loaded ? "loaded" : "empty"); print_linesep(ctx); Index: src/usr.sbin/npf/npfctl/npfctl.8 diff -u src/usr.sbin/npf/npfctl/npfctl.8:1.15 src/usr.sbin/npf/npfctl/npfctl.8:1.15.2.1 --- src/usr.sbin/npf/npfctl/npfctl.8:1.15 Fri Sep 20 21:30:49 2013 +++ src/usr.sbin/npf/npfctl/npfctl.8 Sun Aug 10 07:00:01 2014 @@ -1,6 +1,6 @@ -.\" $NetBSD: npfctl.8,v 1.15 2013/09/20 21:30:49 wiz Exp $ +.\" $NetBSD: npfctl.8,v 1.15.2.1 2014/08/10 07:00:01 tls Exp $ .\" -.\" Copyright (c) 2009-2013 The NetBSD Foundation, Inc. +.\" Copyright (c) 2009-2014 The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This material is based upon work partially supported by The @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd September 19, 2013 +.Dd August 2, 2014 .Dt NPFCTL 8 .Os .Sh NAME @@ -53,26 +53,26 @@ Valid commands are: .It Ic start Enable packet inspection using the currently loaded configuration, if any. Note that this command does not load or reload the configuration, -or affect existing sessions. +or affect existing connections. .It Ic stop Disable packet inspection. This command does not change the currently loaded configuration, -or affect existing sessions. +or affect existing connections. .It Ic reload Op Ar path Load or reload configuration from file. The configuration file at .Pa /etc/npf.conf will be used unless a file is specified by .Ar path . -All sessions will be preserved during the reload, except those which +All connections will be preserved during the reload, except those which will lose NAT policy due to removal. NAT policy is determined by the translation type and address. -Note that change of filter criteria will not expire associated sessions. +Note that change of filter criteria will not expire associated connections. The reload operation (i.e., replacing the ruleset, NAT policies and tables) is atomic. .It Ic flush Flush configuration. -That is, remove all rules, tables and expire all sessions. +That is, remove all rules, tables and expire all connections. This command does not disable packet inspection. .It Ic show Show the current state and configuration. @@ -137,20 +137,16 @@ List all entries in the currently loaded .Ar tid . This operation is expensive and should be used with caution. .\" --- -.It Ic sess-save -Save all active sessions. +.It Ic save +Save the active configuration and a spanshot of the current connections. The data will be stored in the -.Pa /var/db/npf_sessions.db +.Pa /var/db/npf.db file. -Administrator may want to stop the packet inspection before the -session saving. -.It Ic sess-load -Load saved sessions from the file. -Note that original configuration should be loaded before the session loading. -In a case of NAT policy changes, sessions which lose an associated policy -will not be loaded. -Any existing sessions during the load operation will be expired. -Administrator may want to start packet inspection after the session loading. +Administrator may want to stop the packet inspection before saving. +.It Ic load +Load the saved configuration file and the connections from the file. +Note that any existing connections will be destroyed. +Administrator may want to start packet inspection after the load. .It Ic stats Print various statistics. .It Ic debug @@ -190,7 +186,8 @@ Addition and removal of entries in the t .\" ----- .Sh SEE ALSO .Xr bpf 4 , -.Xr npf.conf 5 +.Xr npf.conf 5 , +.Xr npf 7 .Sh HISTORY NPF first appeared in .Nx 6.0 . Index: src/usr.sbin/npf/npfctl/npfctl.c diff -u src/usr.sbin/npf/npfctl/npfctl.c:1.40 src/usr.sbin/npf/npfctl/npfctl.c:1.40.2.1 --- src/usr.sbin/npf/npfctl/npfctl.c:1.40 Tue Nov 12 00:46:34 2013 +++ src/usr.sbin/npf/npfctl/npfctl.c Sun Aug 10 07:00:01 2014 @@ -1,7 +1,7 @@ -/* $NetBSD: npfctl.c,v 1.40 2013/11/12 00:46:34 rmind Exp $ */ +/* $NetBSD: npfctl.c,v 1.40.2.1 2014/08/10 07:00:01 tls Exp $ */ /*- - * Copyright (c) 2009-2013 The NetBSD Foundation, Inc. + * Copyright (c) 2009-2014 The NetBSD Foundation, Inc. * All rights reserved. * * This material is based upon work partially supported by The @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npfctl.c,v 1.40 2013/11/12 00:46:34 rmind Exp $"); +__RCSID("$NetBSD: npfctl.c,v 1.40.2.1 2014/08/10 07:00:01 tls Exp $"); #include <sys/ioctl.h> #include <sys/stat.h> @@ -60,8 +60,8 @@ enum { NPFCTL_TABLE, NPFCTL_RULE, NPFCTL_STATS, - NPFCTL_SESSIONS_SAVE, - NPFCTL_SESSIONS_LOAD, + NPFCTL_SAVE, + NPFCTL_LOAD, }; static const struct operations_s { @@ -69,23 +69,23 @@ static const struct operations_s { int action; } operations[] = { /* Start, stop, reload */ - { "start", NPFCTL_START }, - { "stop", NPFCTL_STOP }, - { "reload", NPFCTL_RELOAD }, - { "show", NPFCTL_SHOWCONF, }, - { "flush", NPFCTL_FLUSH }, - { "valid", NPFCTL_VALIDATE }, + { "start", NPFCTL_START }, + { "stop", NPFCTL_STOP }, + { "reload", NPFCTL_RELOAD }, + { "show", NPFCTL_SHOWCONF, }, + { "flush", NPFCTL_FLUSH }, + { "valid", NPFCTL_VALIDATE }, /* Table */ - { "table", NPFCTL_TABLE }, + { "table", NPFCTL_TABLE }, /* Rule */ - { "rule", NPFCTL_RULE }, + { "rule", NPFCTL_RULE }, /* Stats */ - { "stats", NPFCTL_STATS }, - /* Sessions */ - { "sess-save", NPFCTL_SESSIONS_SAVE }, - { "sess-load", NPFCTL_SESSIONS_LOAD }, + { "stats", NPFCTL_STATS }, + /* Full state save/load */ + { "save", NPFCTL_SAVE }, + { "load", NPFCTL_LOAD }, /* --- */ - { NULL, 0 } + { NULL, 0 } }; bool @@ -137,7 +137,7 @@ usage(void) "\t%s table <tid> { list | flush }\n", progname); fprintf(stderr, - "\t%s sess-load | sess-save\n", + "\t%s save | load\n", progname); exit(EXIT_FAILURE); } @@ -153,15 +153,15 @@ npfctl_print_stats(int fd) { -1, "Packets passed" }, { NPF_STAT_PASS_DEFAULT, "default pass" }, { NPF_STAT_PASS_RULESET, "ruleset pass" }, - { NPF_STAT_PASS_SESSION, "session pass" }, + { NPF_STAT_PASS_CONN, "state pass" }, { -1, "Packets blocked" }, { NPF_STAT_BLOCK_DEFAULT, "default block" }, { NPF_STAT_BLOCK_RULESET, "ruleset block" }, - { -1, "Session and NAT entries" }, - { NPF_STAT_SESSION_CREATE, "session allocations" }, - { NPF_STAT_SESSION_DESTROY, "session destructions" }, + { -1, "State and NAT entries" }, + { NPF_STAT_CONN_CREATE, "state allocations"}, + { NPF_STAT_CONN_DESTROY, "state destructions"}, { NPF_STAT_NAT_CREATE, "NAT entry allocations" }, { NPF_STAT_NAT_DESTROY, "NAT entry destructions"}, @@ -177,7 +177,7 @@ npfctl_print_stats(int fd) { -1, "Packet race cases" }, { NPF_STAT_RACE_NAT, "NAT association race" }, - { NPF_STAT_RACE_SESSION, "duplicate session race"}, + { NPF_STAT_RACE_CONN, "duplicate state race" }, { -1, "Fragmentation" }, { NPF_STAT_FRAGMENTS, "fragments" }, @@ -480,6 +480,37 @@ npfctl_rule(int fd, int argc, char **arg exit(EXIT_SUCCESS); } +static int +npfctl_save(int fd) +{ + nl_config_t *ncf; + bool active, loaded; + int error; + + ncf = npf_config_retrieve(fd, &active, &loaded); + if (ncf == NULL) { + return errno; + } + error = npf_config_export(ncf, NPF_DB_PATH); + npf_config_destroy(ncf); + return error; +} + +static int +npfctl_load(int fd) +{ + nl_config_t *ncf; + int error; + + ncf = npf_config_import(NPF_DB_PATH); + if (ncf == NULL) { + return errno; + } + error = npf_config_submit(ncf, fd); + npf_config_destroy(ncf); + return error; +} + static void npfctl(int action, int argc, char **argv) { @@ -544,22 +575,18 @@ npfctl(int action, int argc, char **argv argv += 2; npfctl_rule(fd, argc, argv); break; + case NPFCTL_LOAD: + ret = npfctl_load(fd); + fun = "npfctl_config_load"; + break; + case NPFCTL_SAVE: + fd = npfctl_save(fd); + fun = "npfctl_config_save"; + break; case NPFCTL_STATS: ret = npfctl_print_stats(fd); fun = "npfctl_print_stats"; break; - case NPFCTL_SESSIONS_SAVE: - if (npf_sessions_recv(fd, NPF_SESSDB_PATH) != 0) { - errx(EXIT_FAILURE, "could not save sessions to '%s'", - NPF_SESSDB_PATH); - } - break; - case NPFCTL_SESSIONS_LOAD: - if (npf_sessions_send(fd, NPF_SESSDB_PATH) != 0) { - errx(EXIT_FAILURE, "no sessions loaded from '%s'", - NPF_SESSDB_PATH); - } - break; } if (ret) { err(EXIT_FAILURE, "%s", fun); Index: src/usr.sbin/npf/npftest/README diff -u src/usr.sbin/npf/npftest/README:1.4 src/usr.sbin/npf/npftest/README:1.4.6.1 --- src/usr.sbin/npf/npftest/README:1.4 Sat Feb 9 03:35:33 2013 +++ src/usr.sbin/npf/npftest/README Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -$NetBSD: README,v 1.4 2013/02/09 03:35:33 rmind Exp $ +$NetBSD: README,v 1.4.6.1 2014/08/10 07:00:01 tls Exp $ npftest - a tool for regression testing and debugging NPF. It uses RUMP framework to run NPF kernel module in the userspace. @@ -12,12 +12,16 @@ npftest -c /tmp/npf.plist -t Stream: -tcpdump -w stream.pcap -i $INTERFACE "host $HOST and tcp" -npfctl debug -npftest -c /tmp/npf.plist -s stream.pcap -o stream_npf_data.txt +tcpdump -w stream.pcap -i $interface "host $host and tcp" +npfctl debug npftest.conf /tmp/npf.plist +npftest -c /tmp/npf.plist -s stream.pcap > stream_npf_data.txt Preferably, use MALLOC_OPTIONS="AJ" and/or other facilities. +Benchmark: + +npftest -b rule -c /tmp/npf.plist -p $ncpu + --- Update RUMP libraries once the kernel side has been changed. Hint: Index: src/usr.sbin/npf/npftest/libnpftest/npf_bpf_test.c diff -u src/usr.sbin/npf/npftest/libnpftest/npf_bpf_test.c:1.4 src/usr.sbin/npf/npftest/libnpftest/npf_bpf_test.c:1.4.2.1 --- src/usr.sbin/npf/npftest/libnpftest/npf_bpf_test.c:1.4 Sat Nov 23 19:40:11 2013 +++ src/usr.sbin/npf/npftest/libnpftest/npf_bpf_test.c Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_bpf_test.c,v 1.4 2013/11/23 19:40:11 rmind Exp $ */ +/* $NetBSD: npf_bpf_test.c,v 1.4.2.1 2014/08/10 07:00:01 tls Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -63,6 +63,7 @@ test_bpf_code(void *code, size_t size) { ifnet_t *dummy_ifp = npf_test_addif(IFNAME_TEST, false, false); npf_cache_t npc = { .npc_info = 0 }; + uint32_t memstore[BPF_MEMWORDS]; bpf_args_t bc_args; struct mbuf *m; nbuf_t nbuf; @@ -72,11 +73,13 @@ test_bpf_code(void *code, size_t size) /* Layer 3 (IP + TCP). */ m = fill_packet(IPPROTO_TCP); nbuf_init(&nbuf, m, dummy_ifp); - npf_cache_all(&npc, &nbuf); + npc.npc_nbuf = &nbuf; + npf_cache_all(&npc); - memset(&bc_args, 0, sizeof(bpf_args_t)); - bc_args.pkt = m; - bc_args.wirelen = m_length(m); + bc_args.pkt = (const uint8_t *)m; + bc_args.buflen = m_length(m); + bc_args.wirelen = bc_args.buflen; + bc_args.mem = memstore; bc_args.arg = &npc; ret = npf_bpf_filter(&bc_args, code, NULL); Index: src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c diff -u src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c:1.8 src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c:1.8.2.1 --- src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c:1.8 Thu Feb 13 03:34:40 2014 +++ src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_nat_test.c,v 1.8 2014/02/13 03:34:40 rmind Exp $ */ +/* $NetBSD: npf_nat_test.c,v 1.8.2.1 2014/08/10 07:00:01 tls Exp $ */ /* * NPF NAT test. @@ -166,7 +166,8 @@ checkresult(bool verbose, unsigned i, st } nbuf_init(&nbuf, m, ifp); - if (!npf_cache_all(&npc, &nbuf)) { + npc.npc_nbuf = &nbuf; + if (!npf_cache_all(&npc)) { printf("error: could not fetch the packet data"); return false; } Index: src/usr.sbin/npf/npftest/libnpftest/npf_perf_test.c diff -u src/usr.sbin/npf/npftest/libnpftest/npf_perf_test.c:1.3 src/usr.sbin/npf/npftest/libnpftest/npf_perf_test.c:1.3.2.1 --- src/usr.sbin/npf/npftest/libnpftest/npf_perf_test.c:1.3 Tue Sep 24 22:52:14 2013 +++ src/usr.sbin/npf/npftest/libnpftest/npf_perf_test.c Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_perf_test.c,v 1.3 2013/09/24 22:52:14 joerg Exp $ */ +/* $NetBSD: npf_perf_test.c,v 1.3.2.1 2014/08/10 07:00:01 tls Exp $ */ /* * NPF benchmarking. @@ -99,5 +99,5 @@ npf_test_conc(bool st, unsigned nthreads kmem_free(npackets, sizeof(uint64_t) * nthreads); kmem_free(l, sizeof(lwp_t *) * nthreads); - printf("%u\t%" PRIu64 "\n", nthreads, total); + printf("%u\t%" PRIu64 "\n", nthreads, total / NSECS); } Index: src/usr.sbin/npf/npftest/libnpftest/npf_rule_test.c diff -u src/usr.sbin/npf/npftest/libnpftest/npf_rule_test.c:1.10 src/usr.sbin/npf/npftest/libnpftest/npf_rule_test.c:1.10.2.1 --- src/usr.sbin/npf/npftest/libnpftest/npf_rule_test.c:1.10 Tue Sep 24 02:04:21 2013 +++ src/usr.sbin/npf/npftest/libnpftest/npf_rule_test.c Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_rule_test.c,v 1.10 2013/09/24 02:04:21 rmind Exp $ */ +/* $NetBSD: npf_rule_test.c,v 1.10.2.1 2014/08/10 07:00:01 tls Exp $ */ /* * NPF ruleset test. @@ -80,10 +80,11 @@ npf_rule_raw_test(bool verbose, struct m int retfl, error; nbuf_init(&nbuf, m, ifp); - npf_cache_all(&npc, &nbuf); + npc.npc_nbuf = &nbuf; + npf_cache_all(&npc); int slock = npf_config_read_enter(); - rl = npf_ruleset_inspect(&npc, &nbuf, npf_config_ruleset(), + rl = npf_ruleset_inspect(&npc, npf_config_ruleset(), di, NPF_LAYER_3); if (rl) { error = npf_rule_conclude(rl, &retfl); Index: src/usr.sbin/npf/npftest/libnpftest/npf_state_test.c diff -u src/usr.sbin/npf/npftest/libnpftest/npf_state_test.c:1.5 src/usr.sbin/npf/npftest/libnpftest/npf_state_test.c:1.5.2.1 --- src/usr.sbin/npf/npftest/libnpftest/npf_state_test.c:1.5 Fri Nov 8 00:38:27 2013 +++ src/usr.sbin/npf/npftest/libnpftest/npf_state_test.c Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_state_test.c,v 1.5 2013/11/08 00:38:27 rmind Exp $ */ +/* $NetBSD: npf_state_test.c,v 1.5.2.1 2014/08/10 07:00:01 tls Exp $ */ /* * NPF state tracking test. @@ -146,15 +146,16 @@ process_packet(const int i, npf_state_t } nbuf_init(&nbuf, construct_packet(p), dummy_ifp); - ret = npf_cache_all(&npc, &nbuf); + npc.npc_nbuf = &nbuf; + ret = npf_cache_all(&npc); KASSERT((ret & NPC_IPFRAG) == 0); if (*snew) { - ret = npf_state_init(&npc, &nbuf, nst); + ret = npf_state_init(&npc, nst); KASSERT(ret == true); *snew = false; } - ret = npf_state_inspect(&npc, &nbuf, nst, p->flags == OUT); + ret = npf_state_inspect(&npc, nst, p->flags == OUT); m_freem(nbuf.nb_mbuf); return ret ? true : (p->flags & ERR) != 0; Index: src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c diff -u src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c:1.9.2.1 src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c:1.9.2.2 --- src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c:1.9.2.1 Sat Aug 9 06:19:50 2014 +++ src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c Sun Aug 10 07:00:01 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_test_subr.c,v 1.9.2.1 2014/08/09 06:19:50 tls Exp $ */ +/* $NetBSD: npf_test_subr.c,v 1.9.2.2 2014/08/10 07:00:01 tls Exp $ */ /* * NPF initialisation and handler routines. @@ -40,7 +40,7 @@ int npf_test_load(const void *xml) { prop_dictionary_t npf_dict = prop_dictionary_internalize(xml); - return npfctl_reload(0, npf_dict); + return npfctl_load(0, npf_dict); } ifnet_t * Added files: Index: src/usr.sbin/npf/npf.7 diff -u /dev/null src/usr.sbin/npf/npf.7:1.1.2.2 --- /dev/null Sun Aug 10 07:00:01 2014 +++ src/usr.sbin/npf/npf.7 Sun Aug 10 07:00:01 2014 @@ -0,0 +1,91 @@ +.\" $NetBSD: npf.7,v 1.1.2.2 2014/08/10 07:00:01 tls Exp $ +.\" +.\" Copyright (c) 2009-2014 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This material is based upon work partially supported by The +.\" NetBSD Foundation under a contract with Mindaugas Rasiukevicius. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd August 2, 2014 +.Dt NPF 7 +.Os +.Sh NAME +.Nm NPF +.Nd NetBSD packet filter +.\" ----- +.Sh DESCRIPTION +NPF is a layer 3 packet filter, supporting IPv4 and IPv6 as well as +layer 4 protocols such as TCP, UDP, and ICMP. +It was designed with a focus on high performance, scalability, and +modularity. +.Pp +NPF was written from scratch in 2009 and is distributed under the +2-clause BSD license. +.\" ----- +.Sh FEATURES +NPF offers the traditional set of features provided by packet filters. +Some key features are: +.Bl -bullet -offset indent +.It +Stateful inspection (connection tracking). +.It +Network address translation (NAT). +This includes static (stateless) and dynamic (stateful) translation, +port translation, bi-directional NAT, etc. +.It +IPv6-to-IPv6 network prefix translation (NPTv6). +.It +Tables for efficient IP sets. +.It +Application Level Gateways (e.g., to support traceroute). +.It +NPF uses BPF with just-in-time (JIT) compilation. +.It +Rule procedures and a framework for NPF extensions. +.It +Traffic normalization (extension). +.It +Packet logging (extension). +.El +.Pp +For a full set features and their description, see the NPF +documentation and other manual pages. +.\" ----- +.Sh SEE ALSO +.Xr libnpf 3 , +.Xr bpf 4 , +.Xr bpfjit 4 , +.Xr npf.conf 5 , +.Xr pcap-filter 7 , +.Xr npfctl 8 +.Pp +.Lk http://www.netbsd.org/~rmind/npf/ "NPF documentation" +.Sh HISTORY +.Nm +first appeared in +.Nx 7.0 . +.Sh AUTHORS +.Nm +was designed and implemented by +.An Mindaugas Rasiukevicius .