Module Name: src Committed By: snj Date: Wed Feb 4 07:13:04 UTC 2015
Modified Files: src/lib/libnpf [netbsd-7]: npf.c npf.h src/sys/net/npf [netbsd-7]: npf_conn.c npf_impl.h npf_ruleset.c src/usr.sbin/npf/npfctl [netbsd-7]: npf.conf.5 npf_parse.y npf_show.c npfctl.c Log Message: Pull up following revision(s) (requested by rmind in ticket #479): lib/libnpf/npf.c: revision 1.35 lib/libnpf/npf.h: revision 1.28 sys/net/npf/npf_conn.c: revision 1.15 sys/net/npf/npf_impl.h: revision 1.61 sys/net/npf/npf_ruleset.c: revision 1.41 usr.sbin/npf/npfctl/npf.conf.5: revision 1.44 usr.sbin/npf/npfctl/npf_parse.y: revision 1.37 usr.sbin/npf/npfctl/npf_show.c: revisions 1.16, 1.17 usr.sbin/npf/npfctl/npfctl.c: revision 1.46 load the config file before bpfjit so that we can disable the warning. -- Don't depend on yacc to include stdlib.h or string.h. -- - npf_conn_establish: remove a rare race condition when we might destroy a connection when it is still referenced by another thread. - npf_conn_destroy: remove the backwards entry using the saved key, PR/49488. - Sprinkle some asserts. -- npf.conf(5): mention alg, include in the example, minor fix. -- npfctl(8): report dynamic rule ID in a comment, print the case when libpcap is used correctly. Also, add npf_ruleset_dump() helper in the kernel. -- libnpf: add npf_rule_getid() and npf_rule_getcode(). Missed in the previous commit. -- npfctl_print_rule: print the ID in hex, not decimal. To generate a diff of this commit: cvs rdiff -u -r1.32.2.1 -r1.32.2.2 src/lib/libnpf/npf.c cvs rdiff -u -r1.27 -r1.27.2.1 src/lib/libnpf/npf.h cvs rdiff -u -r1.10.2.3 -r1.10.2.4 src/sys/net/npf/npf_conn.c cvs rdiff -u -r1.58.2.2 -r1.58.2.3 src/sys/net/npf/npf_impl.h cvs rdiff -u -r1.37.2.2 -r1.37.2.3 src/sys/net/npf/npf_ruleset.c cvs rdiff -u -r1.42.2.1 -r1.42.2.2 src/usr.sbin/npf/npfctl/npf.conf.5 cvs rdiff -u -r1.35.4.1 -r1.35.4.2 src/usr.sbin/npf/npfctl/npf_parse.y cvs rdiff -u -r1.15 -r1.15.2.1 src/usr.sbin/npf/npfctl/npf_show.c cvs rdiff -u -r1.42.2.2 -r1.42.2.3 src/usr.sbin/npf/npfctl/npfctl.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libnpf/npf.c diff -u src/lib/libnpf/npf.c:1.32.2.1 src/lib/libnpf/npf.c:1.32.2.2 --- src/lib/libnpf/npf.c:1.32.2.1 Fri Aug 29 11:14:14 2014 +++ src/lib/libnpf/npf.c Wed Feb 4 07:13:04 2015 @@ -1,7 +1,7 @@ -/* $NetBSD: npf.c,v 1.32.2.1 2014/08/29 11:14:14 martin Exp $ */ +/* $NetBSD: npf.c,v 1.32.2.2 2015/02/04 07:13:04 snj Exp $ */ /*- - * Copyright (c) 2010-2014 The NetBSD Foundation, Inc. + * Copyright (c) 2010-2015 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> -__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.32.2.1 2014/08/29 11:14:14 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.32.2.2 2015/02/04 07:13:04 snj Exp $"); #include <sys/types.h> #include <netinet/in_systm.h> @@ -715,6 +715,27 @@ npf_rule_getproc(nl_rule_t *rl) return rpname; } +uint64_t +npf_rule_getid(nl_rule_t *rl) +{ + prop_dictionary_t rldict = rl->nrl_dict; + uint64_t id = 0; + + (void)prop_dictionary_get_uint64(rldict, "id", &id); + return id; +} + +const void * +npf_rule_getcode(nl_rule_t *rl, int *type, size_t *len) +{ + prop_dictionary_t rldict = rl->nrl_dict; + prop_object_t obj = prop_dictionary_get(rldict, "code"); + + prop_dictionary_get_uint32(rldict, "code-type", (uint32_t *)type); + *len = prop_data_size(obj); + return prop_data_data_nocopy(obj); +} + int _npf_ruleset_list(int fd, const char *rname, nl_config_t *ncf) { Index: src/lib/libnpf/npf.h diff -u src/lib/libnpf/npf.h:1.27 src/lib/libnpf/npf.h:1.27.2.1 --- src/lib/libnpf/npf.h:1.27 Wed Jul 23 01:25:34 2014 +++ src/lib/libnpf/npf.h Wed Feb 4 07:13:04 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: npf.h,v 1.27 2014/07/23 01:25:34 rmind Exp $ */ +/* $NetBSD: npf.h,v 1.27.2.1 2015/02/04 07:13:04 snj Exp $ */ /*- * Copyright (c) 2011-2014 The NetBSD Foundation, Inc. @@ -129,6 +129,8 @@ uint32_t npf_rule_getattr(nl_rule_t *); const char * npf_rule_getinterface(nl_rule_t *); const void * npf_rule_getinfo(nl_rule_t *, size_t *); const char * npf_rule_getproc(nl_rule_t *); +uint64_t npf_rule_getid(nl_rule_t *); +const void * npf_rule_getcode(nl_rule_t *, int *, size_t *); nl_table_t * npf_table_iterate(nl_config_t *); const char * npf_table_getname(nl_table_t *); Index: src/sys/net/npf/npf_conn.c diff -u src/sys/net/npf/npf_conn.c:1.10.2.3 src/sys/net/npf/npf_conn.c:1.10.2.4 --- src/sys/net/npf/npf_conn.c:1.10.2.3 Mon Dec 22 02:10:30 2014 +++ src/sys/net/npf/npf_conn.c Wed Feb 4 07:13:04 2015 @@ -1,7 +1,7 @@ -/* $NetBSD: npf_conn.c,v 1.10.2.3 2014/12/22 02:10:30 msaitoh Exp $ */ +/* $NetBSD: npf_conn.c,v 1.10.2.4 2015/02/04 07:13:04 snj Exp $ */ /*- - * Copyright (c) 2014 Mindaugas Rasiukevicius <rmind at netbsd org> + * Copyright (c) 2014-2015 Mindaugas Rasiukevicius <rmind at netbsd org> * Copyright (c) 2010-2014 The NetBSD Foundation, Inc. * All rights reserved. * @@ -99,7 +99,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_conn.c,v 1.10.2.3 2014/12/22 02:10:30 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_conn.c,v 1.10.2.4 2015/02/04 07:13:04 snj Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -369,7 +369,6 @@ npf_conn_lookup(const npf_cache_t *npc, /* Check if connection is active and not expired. */ flags = con->c_flags; ok = (flags & (CONN_ACTIVE | CONN_EXPIRE)) == CONN_ACTIVE; - if (__predict_false(!ok)) { atomic_dec_uint(&con->c_refcnt); return NULL; @@ -453,6 +452,7 @@ npf_conn_establish(npf_cache_t *npc, int { const nbuf_t *nbuf = npc->npc_nbuf; npf_conn_t *con; + int error = 0; KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET)); @@ -468,16 +468,16 @@ npf_conn_establish(npf_cache_t *npc, int NPF_PRINTF(("NPF: create conn %p\n", con)); npf_stats_inc(NPF_STAT_CONN_CREATE); - /* Reference count and flags (indicate direction). */ mutex_init(&con->c_lock, MUTEX_DEFAULT, IPL_SOFTNET); con->c_flags = (di & PFIL_ALL); - con->c_refcnt = 1; + con->c_refcnt = 0; con->c_rproc = NULL; con->c_nat = NULL; - /* Initialize protocol state. */ + /* Initialize the protocol state. */ if (!npf_state_init(npc, &con->c_state)) { - goto err; + npf_conn_destroy(con); + return NULL; } KASSERT(npf_iscached(npc, NPC_IP46)); @@ -488,45 +488,65 @@ npf_conn_establish(npf_cache_t *npc, int * Construct "forwards" and "backwards" keys. Also, set the * interface ID for this connection (unless it is global). */ - if (!npf_conn_conkey(npc, fw, true)) { - goto err; - } - if (!npf_conn_conkey(npc, bk, false)) { - goto err; + if (!npf_conn_conkey(npc, fw, true) || + !npf_conn_conkey(npc, bk, false)) { + npf_conn_destroy(con); + return NULL; } fw->ck_backptr = bk->ck_backptr = con; con->c_ifid = per_if ? nbuf->nb_ifid : 0; con->c_proto = npc->npc_proto; - /* Set last activity time for a new connection. */ + /* + * Set last activity time for a new connection and acquire + * a reference for the caller before we make it visible. + */ getnanouptime(&con->c_atime); + con->c_refcnt = 1; /* * Insert both keys (entries representing directions) of the - * connection. At this point, it becomes visible. + * connection. At this point it becomes visible, but we activate + * the connection later. */ + mutex_enter(&con->c_lock); if (!npf_conndb_insert(conn_db, fw, con)) { + error = EISCONN; goto err; } if (!npf_conndb_insert(conn_db, bk, con)) { - /* We have hit the duplicate. */ - npf_conndb_remove(conn_db, fw); - npf_stats_inc(NPF_STAT_RACE_CONN); + npf_conn_t *ret __diagused; + ret = npf_conndb_remove(conn_db, fw); + KASSERT(ret == con); + error = EISCONN; goto err; } +err: + /* + * If we have hit the duplicate: mark the connection as expired + * and let the G/C thread to take care of it. We cannot do it + * here since there might be references acquired already. + */ + if (error) { + const u_int dflags = CONN_REMOVED | CONN_EXPIRE; + atomic_or_uint(&con->c_flags, dflags); + npf_stats_inc(NPF_STAT_RACE_CONN); + } else { + NPF_PRINTF(("NPF: establish conn %p\n", con)); + } /* Finally, insert into the connection list. */ - NPF_PRINTF(("NPF: establish conn %p\n", con)); npf_conndb_enqueue(conn_db, con); - return con; -err: - npf_conn_destroy(con); - return NULL; + mutex_exit(&con->c_lock); + + return error ? NULL : con; } static void npf_conn_destroy(npf_conn_t *con) { + KASSERT(con->c_refcnt == 0); + if (con->c_nat) { /* Release any NAT structures. */ npf_nat_destroy(con->c_nat); @@ -582,6 +602,8 @@ npf_conn_setnat(const npf_cache_t *npc, mutex_exit(&con->c_lock); return EINVAL; } + KASSERT((con->c_flags & CONN_REMOVED) == 0); + if (__predict_false(con->c_nat != NULL)) { /* Race with a duplicate packet. */ mutex_exit(&con->c_lock); @@ -590,7 +612,7 @@ npf_conn_setnat(const npf_cache_t *npc, } /* Remove the "backwards" entry. */ - ret = npf_conndb_remove(conn_db, &key); + ret = npf_conndb_remove(conn_db, &con->c_back_entry); KASSERT(ret == con); /* Set the source/destination IDs to the translation values. */ @@ -606,7 +628,9 @@ npf_conn_setnat(const npf_cache_t *npc, * Race: we have hit the duplicate, remove the "forwards" * entry and expire our connection; it is no longer valid. */ - (void)npf_conndb_remove(conn_db, &con->c_forw_entry); + ret = npf_conndb_remove(conn_db, &con->c_forw_entry); + KASSERT(ret == con); + atomic_or_uint(&con->c_flags, CONN_REMOVED | CONN_EXPIRE); mutex_exit(&con->c_lock); Index: src/sys/net/npf/npf_impl.h diff -u src/sys/net/npf/npf_impl.h:1.58.2.2 src/sys/net/npf/npf_impl.h:1.58.2.3 --- src/sys/net/npf/npf_impl.h:1.58.2.2 Mon Dec 1 13:05:26 2014 +++ src/sys/net/npf/npf_impl.h Wed Feb 4 07:13:04 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_impl.h,v 1.58.2.2 2014/12/01 13:05:26 martin Exp $ */ +/* $NetBSD: npf_impl.h,v 1.58.2.3 2015/02/04 07:13:04 snj Exp $ */ /*- * Copyright (c) 2009-2014 The NetBSD Foundation, Inc. @@ -344,6 +344,7 @@ prop_array_t npf_alg_export(void); const char * npf_addr_dump(const npf_addr_t *, int); void npf_state_dump(const npf_state_t *); void npf_nat_dump(const npf_nat_t *); +void npf_ruleset_dump(const char *); void npf_state_setsampler(void (*)(npf_state_t *, bool)); #endif /* _NPF_IMPL_H_ */ Index: src/sys/net/npf/npf_ruleset.c diff -u src/sys/net/npf/npf_ruleset.c:1.37.2.2 src/sys/net/npf/npf_ruleset.c:1.37.2.3 --- src/sys/net/npf/npf_ruleset.c:1.37.2.2 Mon Dec 1 13:05:26 2014 +++ src/sys/net/npf/npf_ruleset.c Wed Feb 4 07:13:04 2015 @@ -1,7 +1,7 @@ -/* $NetBSD: npf_ruleset.c,v 1.37.2.2 2014/12/01 13:05:26 martin Exp $ */ +/* $NetBSD: npf_ruleset.c,v 1.37.2.3 2015/02/04 07:13:04 snj Exp $ */ /*- - * Copyright (c) 2009-2013 The NetBSD Foundation, Inc. + * Copyright (c) 2009-2015 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> -__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.37.2.2 2014/12/01 13:05:26 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.37.2.3 2015/02/04 07:13:04 snj Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -936,3 +936,25 @@ npf_rule_conclude(const npf_rule_t *rl, *retfl = rl->r_attr; return (rl->r_attr & NPF_RULE_PASS) ? 0 : ENETUNREACH; } + + +#if defined(DDB) || defined(_NPF_TESTING) + +void +npf_ruleset_dump(const char *name) +{ + npf_ruleset_t *rlset = npf_config_ruleset(); + npf_rule_t *rg, *rl; + + LIST_FOREACH(rg, &rlset->rs_dynamic, r_dentry) { + printf("ruleset '%s':\n", rg->r_name); + TAILQ_FOREACH(rl, &rg->r_subset, r_entry) { + printf("\tid %"PRIu64", key: ", rl->r_id); + for (u_int i = 0; i < NPF_RULE_MAXKEYLEN; i++) + printf("%x", rl->r_key[i]); + printf("\n"); + } + } +} + +#endif Index: src/usr.sbin/npf/npfctl/npf.conf.5 diff -u src/usr.sbin/npf/npfctl/npf.conf.5:1.42.2.1 src/usr.sbin/npf/npfctl/npf.conf.5:1.42.2.2 --- src/usr.sbin/npf/npfctl/npf.conf.5:1.42.2.1 Mon Dec 29 17:31:47 2014 +++ src/usr.sbin/npf/npfctl/npf.conf.5 Wed Feb 4 07:13:04 2015 @@ -1,6 +1,6 @@ -.\" $NetBSD: npf.conf.5,v 1.42.2.1 2014/12/29 17:31:47 martin Exp $ +.\" $NetBSD: npf.conf.5,v 1.42.2.2 2015/02/04 07:13:04 snj Exp $ .\" -.\" Copyright (c) 2009-2014 The NetBSD Foundation, Inc. +.\" Copyright (c) 2009-2015 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 December 26, 2014 +.Dd February 1, 2015 .Dt NPF.CONF 5 .Os .Sh NAME @@ -232,7 +232,8 @@ is more flexible. ; Syntax of a single line. Lines can be separated by LF (\\n) or ; a semicolon. Comments start with a hash (#) character. -syntax = var-def | table-def | map | group | rproc | comment +syntax = var-def | set-param | alg | table-def | + map | group | rproc | comment ; Variable definition. Names can be alpha-numeric, including "_" character. @@ -240,8 +241,12 @@ var-name = "$" . string interface = interface-name | var-name var-def = var "=" ( var-value | "{" value *[ "," value ] "}" ) -; Parameter setting -set-statement = "set" parameter value +; Parameter setting. +set-param = "set" param-value + +; Application level gateway. The name should be in the double quotes. + +alg = "alg" alg-name ; Table definition. Table ID shall be numeric. Path is in the double quotes. @@ -306,8 +311,8 @@ directory containing further examples .\" ----- .Sh EXAMPLES .Bd -literal -$ext_if = { inet4(wm0), inet6(wm0) } -$int_if = { inet4(wm1), inet6(wm1) } +$ext_if = { inet4(wm0) } +$int_if = { inet4(wm1) } table <blacklist> type hash file "/etc/npf_blacklist" table <limited> type tree dynamic @@ -316,6 +321,8 @@ $services_tcp = { http, https, smtp, dom $services_udp = { domain, ntp, 6000 } $localnet = { 10.1.1.0/24 } +alg "icmp" + # Note: if $ext_if has multiple IP address (e.g. IPv6 as well), # then the translation address has to be specified explicitly. map $ext_if dynamic 10.1.1.0/24 -> $ext_if Index: src/usr.sbin/npf/npfctl/npf_parse.y diff -u src/usr.sbin/npf/npfctl/npf_parse.y:1.35.4.1 src/usr.sbin/npf/npfctl/npf_parse.y:1.35.4.2 --- src/usr.sbin/npf/npfctl/npf_parse.y:1.35.4.1 Mon Dec 29 17:31:47 2014 +++ src/usr.sbin/npf/npfctl/npf_parse.y Wed Feb 4 07:13:04 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_parse.y,v 1.35.4.1 2014/12/29 17:31:47 martin Exp $ */ +/* $NetBSD: npf_parse.y,v 1.35.4.2 2015/02/04 07:13:04 snj Exp $ */ /*- * Copyright (c) 2011-2014 The NetBSD Foundation, Inc. @@ -31,10 +31,12 @@ %{ -#include <stdio.h> #include <err.h> -#include <vis.h> #include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <vis.h> #include "npfctl.h" Index: src/usr.sbin/npf/npfctl/npf_show.c diff -u src/usr.sbin/npf/npfctl/npf_show.c:1.15 src/usr.sbin/npf/npfctl/npf_show.c:1.15.2.1 --- src/usr.sbin/npf/npfctl/npf_show.c:1.15 Sun Jul 20 00:48:51 2014 +++ src/usr.sbin/npf/npfctl/npf_show.c Wed Feb 4 07:13:04 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_show.c,v 1.15 2014/07/20 00:48:51 rmind Exp $ */ +/* $NetBSD: npf_show.c,v 1.15.2.1 2015/02/04 07:13:04 snj Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_show.c,v 1.15 2014/07/20 00:48:51 rmind Exp $"); +__RCSID("$NetBSD: npf_show.c,v 1.15.2.1 2015/02/04 07:13:04 snj Exp $"); #include <sys/socket.h> #include <netinet/in.h> @@ -316,10 +316,25 @@ static void npfctl_print_filter(npf_conf_info_t *ctx, nl_rule_t *rl) { const void *marks; - size_t mlen; + size_t mlen, len; + const void *code; + int type; - /* BPF filter criteria described by the byte-code marks. */ marks = npf_rule_getinfo(rl, &mlen); + if (!marks && (code = npf_rule_getcode(rl, &type, &len)) != NULL) { + /* + * No marks, but the byte-code is present. This must + * have been filled by libpcap(3) or possibly an unknown + * to us byte-code. + */ + fprintf(ctx->fp, "%s ", type == NPF_CODE_BPF ? + "pcap-filter \"...\"" : "unrecognized-bytecode"); + return; + } + + /* + * BPF filter criteria described by the byte-code marks. + */ for (u_int i = 0; i < __arraycount(mark_keyword_map); i++) { const struct mark_keyword_mapent *mk = &mark_keyword_map[i]; char *val; @@ -356,7 +371,7 @@ npfctl_print_rule(npf_conf_info_t *ctx, fprintf(ctx->fp, "on %s ", ifname); } - if ((attr & (NPF_RULE_GROUP | NPF_RULE_DYNAMIC)) == NPF_RULE_GROUP) { + if ((attr & NPF_DYNAMIC_GROUP) == NPF_RULE_GROUP) { /* Group; done. */ fputs("\n", ctx->fp); return; @@ -367,8 +382,15 @@ npfctl_print_rule(npf_conf_info_t *ctx, /* Rule procedure. */ if ((rproc = npf_rule_getproc(rl)) != NULL) { - fprintf(ctx->fp, "apply \"%s\"", rproc); + fprintf(ctx->fp, "apply \"%s\" ", rproc); + } + + /* If dynamic rule - print its ID. */ + if ((attr & NPF_DYNAMIC_GROUP) == NPF_RULE_DYNAMIC) { + uint64_t id = npf_rule_getid(rl); + fprintf(ctx->fp, "# id = \"%" PRIx64 "\" ", id); } + fputs("\n", ctx->fp); } Index: src/usr.sbin/npf/npfctl/npfctl.c diff -u src/usr.sbin/npf/npfctl/npfctl.c:1.42.2.2 src/usr.sbin/npf/npfctl/npfctl.c:1.42.2.3 --- src/usr.sbin/npf/npfctl/npfctl.c:1.42.2.2 Mon Dec 29 17:31:47 2014 +++ src/usr.sbin/npf/npfctl/npfctl.c Wed Feb 4 07:13:04 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: npfctl.c,v 1.42.2.2 2014/12/29 17:31:47 martin Exp $ */ +/* $NetBSD: npfctl.c,v 1.42.2.3 2015/02/04 07:13:04 snj Exp $ */ /*- * Copyright (c) 2009-2014 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npfctl.c,v 1.42.2.2 2014/12/29 17:31:47 martin Exp $"); +__RCSID("$NetBSD: npfctl.c,v 1.42.2.3 2015/02/04 07:13:04 snj Exp $"); #include <sys/ioctl.h> #include <sys/stat.h> @@ -580,9 +580,9 @@ npfctl(int action, int argc, char **argv fun = "ioctl(IOC_NPF_SWITCH)"; break; case NPFCTL_RELOAD: - npfctl_preload_bpfjit(); npfctl_config_init(false); npfctl_parse_file(argc < 3 ? NPF_CONF_PATH : argv[2]); + npfctl_preload_bpfjit(); errno = ret = npfctl_config_send(fd, NULL); fun = "npfctl_config_send"; break;