Module Name: src
Committed By: snj
Date: Sat Mar 21 17:49:03 UTC 2015
Modified Files:
src/sys/net/npf [netbsd-7]: npf_ctl.c npf_ruleset.c
src/usr.sbin/npf/npfctl [netbsd-7]: npf_build.c npf_show.c
Log Message:
Pull up following revision(s) (requested by rmind in ticket #630):
sys/net/npf/npf_ctl.c: revision 1.41
sys/net/npf/npf_ruleset.c: revision 1.42
usr.sbin/npf/npfctl/npf_build.c: revision 1.39
usr.sbin/npf/npfctl/npf_show.c: revision 1.18
NPF: replace the TAILQ of the dynamic rules with a linked list and fix the
inheriting of the active dynamic rules during the reload; also, fix a bug
in the insert path by putting a memory barrier in the right place.
--
npfctl:
- Fix the filter criteria when to/from is omitted but port used.
- Print more user-friendly error if an NPF table has a duplicate entry.
To generate a diff of this commit:
cvs rdiff -u -r1.38.2.1 -r1.38.2.2 src/sys/net/npf/npf_ctl.c
cvs rdiff -u -r1.37.2.3 -r1.37.2.4 src/sys/net/npf/npf_ruleset.c
cvs rdiff -u -r1.38 -r1.38.2.1 src/usr.sbin/npf/npfctl/npf_build.c
cvs rdiff -u -r1.15.2.1 -r1.15.2.2 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_ctl.c
diff -u src/sys/net/npf/npf_ctl.c:1.38.2.1 src/sys/net/npf/npf_ctl.c:1.38.2.2
--- src/sys/net/npf/npf_ctl.c:1.38.2.1 Fri Aug 29 11:14:14 2014
+++ src/sys/net/npf/npf_ctl.c Sat Mar 21 17:49:03 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_ctl.c,v 1.38.2.1 2014/08/29 11:14:14 martin Exp $ */
+/* $NetBSD: npf_ctl.c,v 1.38.2.2 2015/03/21 17:49:03 snj Exp $ */
/*-
* Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.38.2.1 2014/08/29 11:14:14 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.38.2.2 2015/03/21 17:49:03 snj Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@@ -778,6 +778,9 @@ npfctl_rule(u_long cmd, void *data)
}
case NPF_CMD_RULE_LIST: {
retdict = npf_ruleset_list(rlset, ruleset_name);
+ if (!retdict) {
+ error = ESRCH;
+ }
break;
}
case NPF_CMD_RULE_FLUSH: {
@@ -797,6 +800,7 @@ npfctl_rule(u_long cmd, void *data)
npf_config_exit();
if (rl) {
+ KASSERT(error);
npf_rule_free(rl);
}
out:
Index: src/sys/net/npf/npf_ruleset.c
diff -u src/sys/net/npf/npf_ruleset.c:1.37.2.3 src/sys/net/npf/npf_ruleset.c:1.37.2.4
--- src/sys/net/npf/npf_ruleset.c:1.37.2.3 Wed Feb 4 07:13:04 2015
+++ src/sys/net/npf/npf_ruleset.c Sat Mar 21 17:49:03 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_ruleset.c,v 1.37.2.3 2015/02/04 07:13:04 snj Exp $ */
+/* $NetBSD: npf_ruleset.c,v 1.37.2.4 2015/03/21 17:49:03 snj Exp $ */
/*-
* Copyright (c) 2009-2015 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.37.2.3 2015/02/04 07:13:04 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.37.2.4 2015/03/21 17:49:03 snj Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -89,21 +89,24 @@ struct npf_rule {
npf_natpolicy_t * r_natp;
npf_rproc_t * r_rproc;
- /* Rule priority: (highest) 1, 2 ... n (lowest). */
- pri_t r_priority;
-
- /*
- * Dynamic group: subset queue and a dynamic group list entry.
- * Dynamic rule: entry and the parent rule (the group).
- */
union {
- TAILQ_HEAD(npf_ruleq, npf_rule) r_subset;
- TAILQ_ENTRY(npf_rule) r_entry;
- } /* C11 */;
- union {
- LIST_ENTRY(npf_rule) r_dentry;
- npf_rule_t * r_parent;
- } /* C11 */;
+ /*
+ * Dynamic group: rule subset and a group list entry.
+ */
+ struct {
+ npf_rule_t * r_subset;
+ LIST_ENTRY(npf_rule) r_dentry;
+ };
+
+ /*
+ * Dynamic rule: priority, parent group and next rule.
+ */
+ struct {
+ int r_priority;
+ npf_rule_t * r_parent;
+ npf_rule_t * r_next;
+ };
+ };
/* Rule ID, name and the optional key. */
uint64_t r_id;
@@ -147,19 +150,6 @@ npf_ruleset_create(size_t slots)
return rlset;
}
-static void
-npf_ruleset_unlink(npf_ruleset_t *rlset, npf_rule_t *rl)
-{
- if (NPF_DYNAMIC_GROUP_P(rl->r_attr)) {
- LIST_REMOVE(rl, r_dentry);
- }
- if (NPF_DYNAMIC_RULE_P(rl->r_attr)) {
- npf_rule_t *rg = rl->r_parent;
- TAILQ_REMOVE(&rg->r_subset, rl, r_entry);
- }
- LIST_REMOVE(rl, r_aentry);
-}
-
void
npf_ruleset_destroy(npf_ruleset_t *rlset)
{
@@ -167,7 +157,19 @@ npf_ruleset_destroy(npf_ruleset_t *rlset
npf_rule_t *rl;
while ((rl = LIST_FIRST(&rlset->rs_all)) != NULL) {
- npf_ruleset_unlink(rlset, rl);
+ if (NPF_DYNAMIC_GROUP_P(rl->r_attr)) {
+ /*
+ * Note: r_subset may point to the rules which
+ * were inherited by a new ruleset.
+ */
+ rl->r_subset = NULL;
+ LIST_REMOVE(rl, r_dentry);
+ }
+ if (NPF_DYNAMIC_RULE_P(rl->r_attr)) {
+ /* Not removing from r_subset, see above. */
+ KASSERT(rl->r_parent != NULL);
+ }
+ LIST_REMOVE(rl, r_aentry);
npf_rule_free(rl);
}
KASSERT(LIST_EMPTY(&rlset->rs_dynamic));
@@ -222,16 +224,16 @@ npf_ruleset_lookup(npf_ruleset_t *rlset,
int
npf_ruleset_add(npf_ruleset_t *rlset, const char *rname, npf_rule_t *rl)
{
- npf_rule_t *rg, *it;
- pri_t priocmd;
+ npf_rule_t *rg, *it, *target;
+ int priocmd;
+ if (!NPF_DYNAMIC_RULE_P(rl->r_attr)) {
+ return EINVAL;
+ }
rg = npf_ruleset_lookup(rlset, rname);
if (rg == NULL) {
return ESRCH;
}
- if (!NPF_DYNAMIC_RULE_P(rl->r_attr)) {
- return EINVAL;
- }
/* Dynamic rule - assign a unique ID and save the parent. */
rl->r_id = ++rlset->rs_idcnt;
@@ -245,29 +247,32 @@ npf_ruleset_add(npf_ruleset_t *rlset, co
rl->r_priority = 0;
}
+ /*
+ * WARNING: once rg->subset or target->r_next of an *active*
+ * rule is set, then our rule becomes globally visible and active.
+ * Must issue a load fence to ensure rl->r_next visibility first.
+ */
switch (priocmd) {
- case NPF_PRI_FIRST:
- TAILQ_FOREACH(it, &rg->r_subset, r_entry) {
- if (rl->r_priority <= it->r_priority)
- break;
- }
- if (it) {
- TAILQ_INSERT_BEFORE(it, rl, r_entry);
- } else {
- TAILQ_INSERT_HEAD(&rg->r_subset, rl, r_entry);
- }
- break;
case NPF_PRI_LAST:
default:
- TAILQ_FOREACH(it, &rg->r_subset, r_entry) {
- if (rl->r_priority < it->r_priority)
- break;
- }
- if (it) {
- TAILQ_INSERT_BEFORE(it, rl, r_entry);
- } else {
- TAILQ_INSERT_TAIL(&rg->r_subset, rl, r_entry);
+ target = NULL;
+ it = rg->r_subset;
+ while (it && it->r_priority <= rl->r_priority) {
+ target = it;
+ it = it->r_next;
+ }
+ if (target) {
+ rl->r_next = target->r_next;
+ membar_producer();
+ target->r_next = rl;
+ break;
}
+ /* FALLTHROUGH */
+
+ case NPF_PRI_FIRST:
+ rl->r_next = rg->r_subset;
+ membar_producer();
+ rg->r_subset = rl;
break;
}
@@ -276,26 +281,41 @@ npf_ruleset_add(npf_ruleset_t *rlset, co
return 0;
}
+static void
+npf_ruleset_unlink(npf_rule_t *rl, npf_rule_t *prev)
+{
+ KASSERT(NPF_DYNAMIC_RULE_P(rl->r_attr));
+ if (prev) {
+ prev->r_next = rl->r_next;
+ } else {
+ npf_rule_t *rg = rl->r_parent;
+ rg->r_subset = rl->r_next;
+ }
+ LIST_REMOVE(rl, r_aentry);
+}
+
/*
* npf_ruleset_remove: remove the dynamic rule given the rule ID.
*/
int
npf_ruleset_remove(npf_ruleset_t *rlset, const char *rname, uint64_t id)
{
- npf_rule_t *rg, *rl;
+ npf_rule_t *rg, *prev = NULL;
if ((rg = npf_ruleset_lookup(rlset, rname)) == NULL) {
return ESRCH;
}
- TAILQ_FOREACH(rl, &rg->r_subset, r_entry) {
+ for (npf_rule_t *rl = rg->r_subset; rl; rl = rl->r_next) {
KASSERT(rl->r_parent == rg);
+ KASSERT(NPF_DYNAMIC_RULE_P(rl->r_attr));
/* Compare ID. On match, remove and return. */
if (rl->r_id == id) {
- npf_ruleset_unlink(rlset, rl);
+ npf_ruleset_unlink(rl, prev);
LIST_INSERT_HEAD(&rlset->rs_gc, rl, r_aentry);
return 0;
}
+ prev = rl;
}
return ENOENT;
}
@@ -307,7 +327,7 @@ int
npf_ruleset_remkey(npf_ruleset_t *rlset, const char *rname,
const void *key, size_t len)
{
- npf_rule_t *rg, *rl;
+ npf_rule_t *rg, *rlast = NULL, *prev = NULL, *lastprev = NULL;
KASSERT(len && len <= NPF_RULE_MAXKEYLEN);
@@ -315,18 +335,22 @@ npf_ruleset_remkey(npf_ruleset_t *rlset,
return ESRCH;
}
- /* Find the last in the list. */
- TAILQ_FOREACH_REVERSE(rl, &rg->r_subset, npf_ruleq, r_entry) {
+ /* Compare the key and find the last in the list. */
+ for (npf_rule_t *rl = rg->r_subset; rl; rl = rl->r_next) {
KASSERT(rl->r_parent == rg);
-
- /* Compare the key. On match, remove and return. */
+ KASSERT(NPF_DYNAMIC_RULE_P(rl->r_attr));
if (memcmp(rl->r_key, key, len) == 0) {
- npf_ruleset_unlink(rlset, rl);
- LIST_INSERT_HEAD(&rlset->rs_gc, rl, r_aentry);
- return 0;
+ lastprev = prev;
+ rlast = rl;
}
+ prev = rl;
}
- return ENOENT;
+ if (!rlast) {
+ return ENOENT;
+ }
+ npf_ruleset_unlink(rlast, lastprev);
+ LIST_INSERT_HEAD(&rlset->rs_gc, rlast, r_aentry);
+ return 0;
}
/*
@@ -337,7 +361,7 @@ npf_ruleset_list(npf_ruleset_t *rlset, c
{
prop_dictionary_t rgdict;
prop_array_t rules;
- npf_rule_t *rg, *rl;
+ npf_rule_t *rg;
KASSERT(npf_config_locked_p());
@@ -352,12 +376,13 @@ npf_ruleset_list(npf_ruleset_t *rlset, c
return NULL;
}
- TAILQ_FOREACH(rl, &rg->r_subset, r_entry) {
+ for (npf_rule_t *rl = rg->r_subset; rl; rl = rl->r_next) {
prop_dictionary_t rldict;
- rldict = prop_dictionary_create();
KASSERT(rl->r_parent == rg);
+ KASSERT(NPF_DYNAMIC_RULE_P(rl->r_attr));
+ rldict = prop_dictionary_create();
if (npf_rule_export(rlset, rl, rldict)) {
prop_object_release(rldict);
prop_object_release(rules);
@@ -387,10 +412,17 @@ npf_ruleset_flush(npf_ruleset_t *rlset,
if ((rg = npf_ruleset_lookup(rlset, rname)) == NULL) {
return ESRCH;
}
- while ((rl = TAILQ_FIRST(&rg->r_subset)) != NULL) {
+
+ rl = atomic_swap_ptr(&rg->r_subset, NULL);
+ membar_producer();
+
+ while (rl) {
+ KASSERT(NPF_DYNAMIC_RULE_P(rl->r_attr));
KASSERT(rl->r_parent == rg);
- npf_ruleset_unlink(rlset, rl);
+
+ LIST_REMOVE(rl, r_aentry);
LIST_INSERT_HEAD(&rlset->rs_gc, rl, r_aentry);
+ rl = rl->r_next;
}
return 0;
}
@@ -460,27 +492,33 @@ npf_ruleset_reload(npf_ruleset_t *newset
* Scan the dynamic rules and share (migrate) if needed.
*/
LIST_FOREACH(rg, &newset->rs_dynamic, r_dentry) {
- npf_rule_t *actrg;
+ npf_rule_t *active_rgroup;
/* Look for a dynamic ruleset group with such name. */
- actrg = npf_ruleset_lookup(oldset, rg->r_name);
- if (actrg == NULL) {
+ active_rgroup = npf_ruleset_lookup(oldset, rg->r_name);
+ if (active_rgroup == NULL) {
continue;
}
/*
- * Copy the list-head structure. This is necessary because
- * the rules are still active and therefore accessible for
- * inspection via the old ruleset.
+ * ATOMICITY: Copy the head pointer of the linked-list,
+ * but do not remove the rules from the active r_subset.
+ * This is necessary because the rules are still active
+ * and therefore are accessible for inspection via the
+ * old ruleset.
*/
- memcpy(&rg->r_subset, &actrg->r_subset, sizeof(rg->r_subset));
- TAILQ_FOREACH(rl, &rg->r_subset, r_entry) {
- /*
- * We can safely migrate to the new all-rule list
- * and re-set the parent rule, though.
- */
+ rg->r_subset = active_rgroup->r_subset;
+
+ /*
+ * We can safely migrate to the new all-rule list and
+ * reset the parent rule, though.
+ */
+ for (rl = rg->r_subset; rl; rl = rl->r_next) {
+ KASSERT(NPF_DYNAMIC_RULE_P(rl->r_attr));
LIST_REMOVE(rl, r_aentry);
LIST_INSERT_HEAD(&newset->rs_all, rl, r_aentry);
+
+ KASSERT(rl->r_parent == active_rgroup);
rl->r_parent = rg;
}
}
@@ -614,7 +652,6 @@ npf_rule_alloc(prop_dictionary_t rldict)
/* Allocate a rule structure. */
rl = kmem_zalloc(sizeof(npf_rule_t), KM_SLEEP);
- TAILQ_INIT(&rl->r_subset);
rl->r_natp = NULL;
/* Name (optional) */
@@ -626,9 +663,17 @@ npf_rule_alloc(prop_dictionary_t rldict)
/* Attributes, priority and interface ID (optional). */
prop_dictionary_get_uint32(rldict, "attr", &rl->r_attr);
- prop_dictionary_get_int32(rldict, "prio", &rl->r_priority);
rl->r_attr &= ~NPF_RULE_PRIVMASK;
+ if (NPF_DYNAMIC_RULE_P(rl->r_attr)) {
+ /* Priority of the dynamic rule. */
+ prop_dictionary_get_int32(rldict, "prio", &rl->r_priority);
+ } else {
+ /* The skip-to index. No need to validate it. */
+ prop_dictionary_get_uint32(rldict, "skip-to", &rl->r_skip_to);
+ }
+
+ /* Interface name; register and get the npf-if-id. */
if (prop_dictionary_get_cstring_nocopy(rldict, "ifname", &rname)) {
if ((rl->r_ifid = npf_ifmap_register(rname)) == 0) {
kmem_free(rl, sizeof(npf_rule_t));
@@ -638,9 +683,6 @@ npf_rule_alloc(prop_dictionary_t rldict)
rl->r_ifid = 0;
}
- /* Get the skip-to index. No need to validate it. */
- prop_dictionary_get_uint32(rldict, "skip-to", &rl->r_skip_to);
-
/* Key (optional). */
prop_object_t obj = prop_dictionary_get(rldict, "key");
const void *key = prop_data_data_nocopy(obj);
@@ -829,15 +871,16 @@ npf_rule_inspect(const npf_rule_t *rl, b
* npf_rule_reinspect: re-inspect the dynamic rule by iterating its list.
* This is only for the dynamic rules. Subrules cannot have nested rules.
*/
-static npf_rule_t *
-npf_rule_reinspect(const npf_rule_t *drl, bpf_args_t *bc_args,
+static inline npf_rule_t *
+npf_rule_reinspect(const npf_rule_t *rg, bpf_args_t *bc_args,
const int di_mask, const u_int ifid)
{
npf_rule_t *final_rl = NULL, *rl;
- KASSERT(NPF_DYNAMIC_GROUP_P(drl->r_attr));
+ KASSERT(NPF_DYNAMIC_GROUP_P(rg->r_attr));
- TAILQ_FOREACH(rl, &drl->r_subset, r_entry) {
+ for (rl = rg->r_subset; rl; rl = rl->r_next) {
+ KASSERT(!final_rl || rl->r_priority >= final_rl->r_priority);
if (!npf_rule_inspect(rl, bc_args, di_mask, ifid)) {
continue;
}
@@ -882,7 +925,6 @@ npf_ruleset_inspect(npf_cache_t *npc, co
const uint32_t attr = rl->r_attr;
KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
- KASSERT(!final_rl || rl->r_priority >= final_rl->r_priority);
KASSERT(n < skip_to);
/* Group is a barrier: return a matching if found any. */
@@ -948,7 +990,7 @@ npf_ruleset_dump(const char *name)
LIST_FOREACH(rg, &rlset->rs_dynamic, r_dentry) {
printf("ruleset '%s':\n", rg->r_name);
- TAILQ_FOREACH(rl, &rg->r_subset, r_entry) {
+ for (rl = rg->r_subset; rl; rl = rl->r_next) {
printf("\tid %"PRIu64", key: ", rl->r_id);
for (u_int i = 0; i < NPF_RULE_MAXKEYLEN; i++)
printf("%x", rl->r_key[i]);
Index: src/usr.sbin/npf/npfctl/npf_build.c
diff -u src/usr.sbin/npf/npfctl/npf_build.c:1.38 src/usr.sbin/npf/npfctl/npf_build.c:1.38.2.1
--- src/usr.sbin/npf/npfctl/npf_build.c:1.38 Sat May 31 22:41:37 2014
+++ src/usr.sbin/npf/npfctl/npf_build.c Sat Mar 21 17:49:03 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_build.c,v 1.38 2014/05/31 22:41:37 rmind Exp $ */
+/* $NetBSD: npf_build.c,v 1.38.2.1 2015/03/21 17:49:03 snj Exp $ */
/*-
* Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_build.c,v 1.38 2014/05/31 22:41:37 rmind Exp $");
+__RCSID("$NetBSD: npf_build.c,v 1.38.2.1 2015/03/21 17:49:03 snj Exp $");
#include <sys/types.h>
#include <sys/mman.h>
@@ -91,6 +91,10 @@ npfctl_config_send(int fd, const char *o
}
npf_rule_insert(npf_conf, NULL, defgroup);
error = npf_config_submit(npf_conf, fd);
+ if (error == EEXIST) { /* XXX */
+ errx(EXIT_FAILURE, "(re)load failed: "
+ "some table has a duplicate entry?");
+ }
if (error) {
nl_error_t ne;
_npf_config_error(npf_conf, &ne);
Index: src/usr.sbin/npf/npfctl/npf_show.c
diff -u src/usr.sbin/npf/npfctl/npf_show.c:1.15.2.1 src/usr.sbin/npf/npfctl/npf_show.c:1.15.2.2
--- src/usr.sbin/npf/npfctl/npf_show.c:1.15.2.1 Wed Feb 4 07:13:04 2015
+++ src/usr.sbin/npf/npfctl/npf_show.c Sat Mar 21 17:49:03 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_show.c,v 1.15.2.1 2015/02/04 07:13:04 snj Exp $ */
+/* $NetBSD: npf_show.c,v 1.15.2.2 2015/03/21 17:49:03 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.2.1 2015/02/04 07:13:04 snj Exp $");
+__RCSID("$NetBSD: npf_show.c,v 1.15.2.2 2015/03/21 17:49:03 snj Exp $");
#include <sys/socket.h>
#include <netinet/in.h>
@@ -53,13 +53,22 @@ __RCSID("$NetBSD: npf_show.c,v 1.15.2.1
#include "npfctl.h"
+#define SEEN_SRC 0x01
+#define SEEN_DST 0x02
+
typedef struct {
nl_config_t * conf;
FILE * fp;
long fpos;
+ u_int flags;
+ uint32_t curmark;
} npf_conf_info_t;
-static npf_conf_info_t stdout_ctx = { .fp = stdout, .fpos = 0 };
+static npf_conf_info_t stdout_ctx = {
+ .fp = stdout,
+ .fpos = 0,
+ .flags = 0
+};
static void print_indent(npf_conf_info_t *, u_int);
static void print_linesep(npf_conf_info_t *);
@@ -201,12 +210,18 @@ static char *
print_portrange(npf_conf_info_t *ctx, const uint32_t *words)
{
u_int fport = words[0], tport = words[1];
+ const char *any_str = "";
char *p;
+ if (ctx->curmark == BM_SRC_PORTS && (ctx->flags & SEEN_SRC) == 0)
+ any_str = "to any ";
+ if (ctx->curmark == BM_DST_PORTS && (ctx->flags & SEEN_DST) == 0)
+ any_str = "from any ";
+
if (fport != tport) {
- easprintf(&p, "%u:%u", fport, tport);
+ easprintf(&p, "%s%u:%u", any_str, fport, tport);
} else {
- easprintf(&p, "%u", fport);
+ easprintf(&p, "%s%u", any_str, fport);
}
return p;
}
@@ -244,22 +259,23 @@ static const struct mark_keyword_mapent
u_int mark;
const char * token;
const char * sep;
+ u_int set_flags;
char * (*printfn)(npf_conf_info_t *, const uint32_t *);
u_int fwords;
} mark_keyword_map[] = {
- { BM_IPVER, "family %s", NULL, print_family, 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 },
-
- { BM_SRC_CIDR, "from %s", ", ", print_address, 6 },
- { BM_SRC_TABLE, "from <%s>", NULL, print_table, 1 },
- { BM_SRC_PORTS, "port %s", ", ", print_portrange,2 },
-
- { BM_DST_CIDR, "to %s", ", ", print_address, 6 },
- { BM_DST_TABLE, "to <%s>", NULL, print_table, 1 },
- { BM_DST_PORTS, "port %s", ", ", print_portrange,2 },
+ { BM_IPVER, "family %s", NULL, 0, print_family, 1 },
+ { BM_PROTO, "proto %s", ", ", 0, print_proto, 1 },
+ { BM_TCPFL, "flags %s", NULL, 0, print_tcpflags, 2 },
+ { BM_ICMP_TYPE, "icmp-type %s", NULL, 0, print_number, 1 },
+ { BM_ICMP_CODE, "code %s", NULL, 0, print_number, 1 },
+
+ { BM_SRC_CIDR, "from %s", ", ", SEEN_SRC, print_address, 6 },
+ { BM_SRC_TABLE, "from <%s>", NULL, SEEN_SRC, print_table, 1 },
+ { BM_SRC_PORTS, "port %s", ", ", 0, print_portrange,2 },
+
+ { BM_DST_CIDR, "to %s", ", ", SEEN_DST, print_address, 6 },
+ { BM_DST_TABLE, "to <%s>", NULL, SEEN_DST, print_table, 1 },
+ { BM_DST_PORTS, "port %s", ", ", 0, print_portrange,2 },
};
static const char * __attribute__((format_arg(2)))
@@ -285,6 +301,10 @@ scan_marks(npf_conf_info_t *ctx, const s
errx(EXIT_FAILURE, "byte-code marking inconsistency");
}
if (m == mk->mark) {
+ /* Set the current mark and the flags. */
+ ctx->flags |= mk->set_flags;
+ ctx->curmark = m;
+
/* Value is processed by the print function. */
assert(mk->fwords == nwords);
vals[nvals++] = mk->printfn(ctx, marks);