Module Name: src Committed By: rmind Date: Fri Mar 14 11:29:45 UTC 2014
Modified Files: src/sys/net/npf: npf.h npf_handler.c npf_impl.h npf_nat.c npf_session.c src/usr.sbin/npf/npfctl: npf_parse.y npf_scan.l npf_show.c Log Message: NPF: add support for "stateful-ends". To generate a diff of this commit: cvs rdiff -u -r1.37 -r1.38 src/sys/net/npf/npf.h cvs rdiff -u -r1.28 -r1.29 src/sys/net/npf/npf_handler.c cvs rdiff -u -r1.49 -r1.50 src/sys/net/npf/npf_impl.h cvs rdiff -u -r1.26 -r1.27 src/sys/net/npf/npf_nat.c cvs rdiff -u -r1.30 -r1.31 src/sys/net/npf/npf_session.c cvs rdiff -u -r1.33 -r1.34 src/usr.sbin/npf/npfctl/npf_parse.y cvs rdiff -u -r1.19 -r1.20 src/usr.sbin/npf/npfctl/npf_scan.l cvs rdiff -u -r1.12 -r1.13 src/usr.sbin/npf/npfctl/npf_show.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.h diff -u src/sys/net/npf/npf.h:1.37 src/sys/net/npf/npf.h:1.38 --- src/sys/net/npf/npf.h:1.37 Thu Feb 13 03:34:40 2014 +++ src/sys/net/npf/npf.h Fri Mar 14 11:29:44 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf.h,v 1.37 2014/02/13 03:34:40 rmind Exp $ */ +/* $NetBSD: npf.h,v 1.38 2014/03/14 11:29:44 rmind Exp $ */ /*- * Copyright (c) 2009-2014 The NetBSD Foundation, Inc. @@ -210,6 +210,7 @@ bool npf_autounload_p(void); #define NPF_RULE_RETRST 0x0010 #define NPF_RULE_RETICMP 0x0020 #define NPF_RULE_DYNAMIC 0x0040 +#define NPF_RULE_MULTIENDS 0x0080 #define NPF_DYNAMIC_GROUP (NPF_RULE_GROUP | NPF_RULE_DYNAMIC) Index: src/sys/net/npf/npf_handler.c diff -u src/sys/net/npf/npf_handler.c:1.28 src/sys/net/npf/npf_handler.c:1.29 --- src/sys/net/npf/npf_handler.c:1.28 Fri Nov 8 00:38:26 2013 +++ src/sys/net/npf/npf_handler.c Fri Mar 14 11:29:44 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_handler.c,v 1.28 2013/11/08 00:38:26 rmind Exp $ */ +/* $NetBSD: npf_handler.c,v 1.29 2014/03/14 11:29:44 rmind Exp $ */ /*- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.28 2013/11/08 00:38:26 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.29 2014/03/14 11:29:44 rmind Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -229,7 +229,8 @@ npf_packet_handler(void *arg, struct mbu * if session creation fails (e.g. due to unsupported protocol). */ if ((retfl & NPF_RULE_STATEFUL) != 0 && !se) { - se = npf_session_establish(&npc, &nbuf, di); + se = npf_session_establish(&npc, &nbuf, di, + (retfl & NPF_RULE_MULTIENDS) == 0); if (se) { /* * Note: the reference on the rule procedure is Index: src/sys/net/npf/npf_impl.h diff -u src/sys/net/npf/npf_impl.h:1.49 src/sys/net/npf/npf_impl.h:1.50 --- src/sys/net/npf/npf_impl.h:1.49 Wed Feb 19 03:51:31 2014 +++ src/sys/net/npf/npf_impl.h Fri Mar 14 11:29:44 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_impl.h,v 1.49 2014/02/19 03:51:31 rmind Exp $ */ +/* $NetBSD: npf_impl.h,v 1.50 2014/03/14 11:29:44 rmind Exp $ */ /*- * Copyright (c) 2009-2014 The NetBSD Foundation, Inc. @@ -311,7 +311,7 @@ void sess_htable_destroy(npf_sehash_t * npf_session_t * npf_session_lookup(const npf_cache_t *, const nbuf_t *, const int, bool *); npf_session_t * npf_session_inspect(npf_cache_t *, nbuf_t *, const int, int *); -npf_session_t * npf_session_establish(npf_cache_t *, nbuf_t *, const int); +npf_session_t * npf_session_establish(npf_cache_t *, nbuf_t *, int, bool); void npf_session_release(npf_session_t *); void npf_session_expire(npf_session_t *); bool npf_session_pass(const npf_session_t *, npf_rproc_t **); Index: src/sys/net/npf/npf_nat.c diff -u src/sys/net/npf/npf_nat.c:1.26 src/sys/net/npf/npf_nat.c:1.27 --- src/sys/net/npf/npf_nat.c:1.26 Wed Feb 19 03:51:31 2014 +++ src/sys/net/npf/npf_nat.c Fri Mar 14 11:29:44 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_nat.c,v 1.26 2014/02/19 03:51:31 rmind Exp $ */ +/* $NetBSD: npf_nat.c,v 1.27 2014/03/14 11:29:44 rmind Exp $ */ /*- * Copyright (c) 2014 Mindaugas Rasiukevicius <rmind at netbsd org> @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.26 2014/02/19 03:51:31 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.27 2014/03/14 11:29:44 rmind Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -669,7 +669,7 @@ npf_do_nat(npf_cache_t *npc, npf_session * stream depends on other, stateless filtering rules. */ if (se == NULL) { - nse = npf_session_establish(npc, nbuf, di); + nse = npf_session_establish(npc, nbuf, di, true); if (nse == NULL) { atomic_dec_uint(&np->n_refcnt); return ENOMEM; Index: src/sys/net/npf/npf_session.c diff -u src/sys/net/npf/npf_session.c:1.30 src/sys/net/npf/npf_session.c:1.31 --- src/sys/net/npf/npf_session.c:1.30 Fri Dec 6 01:33:37 2013 +++ src/sys/net/npf/npf_session.c Fri Mar 14 11:29:44 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_session.c,v 1.30 2013/12/06 01:33:37 rmind Exp $ */ +/* $NetBSD: npf_session.c,v 1.31 2014/03/14 11:29:44 rmind Exp $ */ /*- * Copyright (c) 2010-2013 The NetBSD Foundation, Inc. @@ -92,7 +92,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.30 2013/12/06 01:33:37 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.31 2014/03/14 11:29:44 rmind Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -260,19 +260,12 @@ sess_rbtree_cmp_nodes(void *ctx, const v const int sz = sen1->se_alen; int ret; - /* - * Ports are expected to vary most, therefore they are first. - */ if (sen1->se_src_id != sen2->se_src_id) { return (sen1->se_src_id < sen2->se_src_id) ? -1 : 1; } if (sen1->se_dst_id != sen2->se_dst_id) { return (sen1->se_dst_id < sen2->se_dst_id) ? -1 : 1; } - - /* - * Note that hash should minimise differentiation on addresses. - */ if (sen1->se_alen != sen2->se_alen) { return (sen1->se_alen < sen2->se_alen) ? -1 : 1; } @@ -285,7 +278,19 @@ sess_rbtree_cmp_nodes(void *ctx, const v const npf_secomid_t *id1 = &sen1->se_backptr->s_common_id; const npf_secomid_t *id2 = ctx ? ctx : &sen2->se_backptr->s_common_id; - return memcmp(id1, id2, sizeof(npf_secomid_t)); + + if (id1->proto != id2->proto) { + return (id1->proto < id2->proto) ? -1 : 1; + } + + /* + * Zero interface ID is a special case indicating a global state, + * in which case we match straight away. + */ + if (id1->ifid && id1->ifid != id2->ifid) { + return (id1->ifid < id2->ifid) ? -1 : 1; + } + return 0; } static signed int @@ -312,8 +317,7 @@ sess_hash_bucket(npf_sehash_t *stbl, con const int sz = sen->se_alen; uint32_t hash, mix[2]; - mix[0] = (scid->proto ^ scid->ifid) << 16; - mix[0] |= sen->se_src_id ^ sen->se_dst_id; + mix[0] = (scid->proto << 16) | (sen->se_src_id ^ sen->se_dst_id); mix[1] = npf_addr_mix(sz, &sen->se_src_addr, &sen->se_dst_addr); hash = murmurhash2(mix, sizeof(mix), sess_hash_seed); @@ -486,6 +490,7 @@ npf_session_lookup(const npf_cache_t *np const int di, bool *forw) { const u_int proto = npc->npc_proto; + const u_int ifid = nbuf->nb_ifid; npf_sentry_t senkey, *sen; npf_session_t *se; npf_sehash_t *sh; @@ -505,9 +510,7 @@ npf_session_lookup(const npf_cache_t *np * Note: this is a special case where we use common ID pointer * to pass the structure for the key comparator. */ - npf_secomid_t scid; - memset(&scid, 0, sizeof(npf_secomid_t)); - scid = (npf_secomid_t){ .proto = proto, .ifid = nbuf->nb_ifid }; + npf_secomid_t scid = { .proto = proto, .ifid = ifid }; senkey.se_common_id = &scid; /* @@ -528,7 +531,7 @@ npf_session_lookup(const npf_cache_t *np } se = sen->se_backptr; KASSERT(se->s_common_id.proto == proto); - KASSERT(se->s_common_id.ifid == nbuf->nb_ifid); + KASSERT(se->s_common_id.ifid == 0 || se->s_common_id.ifid == ifid); flags = se->s_flags; /* Check if session is active and not expired. */ @@ -597,13 +600,13 @@ npf_session_inspect(npf_cache_t *npc, nb } /* - * npf_establish_session: create a new session, insert into the global list. + * npf_session_establish: create a new session, insert into the global list. * * => Session is created with the reference held for the caller. * => Session will be activated on the first reference release. */ npf_session_t * -npf_session_establish(npf_cache_t *npc, nbuf_t *nbuf, const int di) +npf_session_establish(npf_cache_t *npc, nbuf_t *nbuf, int di, bool per_if) { npf_sentry_t *fw, *bk; npf_sehash_t *sh; @@ -612,6 +615,7 @@ npf_session_establish(npf_cache_t *npc, bool ok; KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET)); + if (!npf_session_trackable_p(npc)) { return NULL; } @@ -644,9 +648,8 @@ npf_session_establish(npf_cache_t *npc, memcpy(&fw->se_dst_addr, npc->npc_ips[NPF_DST], alen); /* Protocol and interface. */ - memset(&se->s_common_id, 0, sizeof(npf_secomid_t)); se->s_common_id.proto = npc->npc_proto; - se->s_common_id.ifid = nbuf->nb_ifid; + se->s_common_id.ifid = per_if ? nbuf->nb_ifid : 0; /* Setup "forwards" entry. */ if (!npf_session_fillent(npc, fw)) { Index: src/usr.sbin/npf/npfctl/npf_parse.y diff -u src/usr.sbin/npf/npfctl/npf_parse.y:1.33 src/usr.sbin/npf/npfctl/npf_parse.y:1.34 --- src/usr.sbin/npf/npfctl/npf_parse.y:1.33 Mon Feb 17 00:45:24 2014 +++ src/usr.sbin/npf/npfctl/npf_parse.y Fri Mar 14 11:29:45 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_parse.y,v 1.33 2014/02/17 00:45:24 rmind Exp $ */ +/* $NetBSD: npf_parse.y,v 1.34 2014/03/14 11:29:45 rmind Exp $ */ /*- * Copyright (c) 2011-2014 The NetBSD Foundation, Inc. @@ -136,6 +136,7 @@ yyerror(const char *fmt, ...) %token SEPLINE %token SLASH %token STATEFUL +%token STATEFUL_ENDS %token TABLE %token TCP %token TO @@ -553,6 +554,7 @@ all_or_filt_opts opt_stateful : STATEFUL { $$ = NPF_RULE_STATEFUL; } + | STATEFUL_ENDS { $$ = NPF_RULE_STATEFUL | NPF_RULE_MULTIENDS; } | { $$ = 0; } ; Index: src/usr.sbin/npf/npfctl/npf_scan.l diff -u src/usr.sbin/npf/npfctl/npf_scan.l:1.19 src/usr.sbin/npf/npfctl/npf_scan.l:1.20 --- src/usr.sbin/npf/npfctl/npf_scan.l:1.19 Thu Feb 13 03:34:40 2014 +++ src/usr.sbin/npf/npfctl/npf_scan.l Fri Mar 14 11:29:45 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_scan.l,v 1.19 2014/02/13 03:34:40 rmind Exp $ */ +/* $NetBSD: npf_scan.l,v 1.20 2014/03/14 11:29:45 rmind Exp $ */ /*- * Copyright (c) 2011-2012 The NetBSD Foundation, Inc. @@ -118,6 +118,7 @@ block return BLOCK; pass return PASS; pcap-filter return PCAP_FILTER; stateful return STATEFUL; +stateful-ends return STATEFUL_ENDS; apply return APPLY; final return FINAL; quick return FINAL; Index: src/usr.sbin/npf/npfctl/npf_show.c diff -u src/usr.sbin/npf/npfctl/npf_show.c:1.12 src/usr.sbin/npf/npfctl/npf_show.c:1.13 --- src/usr.sbin/npf/npfctl/npf_show.c:1.12 Wed Feb 19 01:43:16 2014 +++ src/usr.sbin/npf/npfctl/npf_show.c Fri Mar 14 11:29:45 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_show.c,v 1.12 2014/02/19 01:43:16 rmind Exp $ */ +/* $NetBSD: npf_show.c,v 1.13 2014/03/14 11:29:45 rmind Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: npf_show.c,v 1.12 2014/02/19 01:43:16 rmind Exp $"); +__RCSID("$NetBSD: npf_show.c,v 1.13 2014/03/14 11:29:45 rmind Exp $"); #include <sys/socket.h> #include <netinet/in.h> @@ -218,6 +218,7 @@ print_portrange(npf_conf_info_t *ctx, co */ #define F(name) __CONCAT(NPF_RULE_, name) +#define STATEFUL_ENDS (NPF_RULE_STATEFUL | NPF_RULE_MULTIENDS) #define NAME_AT 2 static const struct attr_keyword_mapent { @@ -232,7 +233,8 @@ static const struct attr_keyword_mapent { F(RETRST)|F(RETICMP), F(RETRST)|F(RETICMP), "return" }, { F(RETRST)|F(RETICMP), F(RETRST), "return-rst" }, { F(RETRST)|F(RETICMP), F(RETICMP), "return-icmp" }, - { F(STATEFUL), F(STATEFUL), "stateful" }, + { STATEFUL_ENDS, F(STATEFUL), "stateful" }, + { STATEFUL_ENDS, STATEFUL_ENDS, "stateful-ends" }, { F(DIMASK), F(IN), "in" }, { F(DIMASK), F(OUT), "out" }, { F(FINAL), F(FINAL), "final" },