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" },