Page MenuHomeFreeBSD

D35362.diff
No OneTemporary

D35362.diff

diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -94,6 +94,9 @@
uint16_t proto;
struct pfctl_eth_addr src, dst;
struct pf_rule_addr ipsrc, ipdst;
+ char match_tagname[PF_TAG_NAME_SIZE];
+ uint16_t match_tag;
+ bool match_tag_not;
/* Stats */
uint64_t evaluations;
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -629,6 +629,10 @@
rule->ifnot = nvlist_get_bool(nvl, "ifnot");
rule->direction = nvlist_get_number(nvl, "direction");
rule->proto = nvlist_get_number(nvl, "proto");
+ strlcpy(rule->match_tagname, nvlist_get_string(nvl, "match_tagname"),
+ PF_TAG_NAME_SIZE);
+ rule->match_tag = nvlist_get_number(nvl, "match_tag");
+ rule->match_tag_not = nvlist_get_bool(nvl, "match_tag_not");
pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "src"),
&rule->src);
@@ -780,6 +784,8 @@
nvlist_add_bool(nvl, "ifnot", r->ifnot);
nvlist_add_number(nvl, "direction", r->direction);
nvlist_add_number(nvl, "proto", r->proto);
+ nvlist_add_string(nvl, "match_tagname", r->match_tagname);
+ nvlist_add_bool(nvl, "match_tag_not", r->match_tag_not);
addr = pfctl_eth_addr_to_nveth_addr(&r->src);
if (addr == NULL) {
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1197,6 +1197,14 @@
r.quick = $4.quick;
if ($9.tag != NULL)
memcpy(&r.tagname, $9.tag, sizeof(r.tagname));
+ if ($9.match_tag)
+ if (strlcpy(r.match_tagname, $9.match_tag,
+ PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
+ yyerror("tag too long, max %u chars",
+ PF_TAG_NAME_SIZE - 1);
+ YYERROR;
+ }
+ r.match_tag_not = $9.match_tag_not;
if ($9.queues.qname != NULL)
memcpy(&r.qname, $9.queues.qname, sizeof(r.qname));
r.dnpipe = $9.dnpipe;
@@ -1320,6 +1328,10 @@
| TAG string {
filter_opts.tag = $2;
}
+ | not TAGGED string {
+ filter_opts.match_tag = $3;
+ filter_opts.match_tag_not = $1;
+ }
| DNPIPE number {
filter_opts.dnpipe = $2;
filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
@@ -5772,6 +5784,18 @@
struct node_mac *srcs, struct node_mac *dsts,
struct node_host *ipsrcs, struct node_host *ipdsts, const char *anchor_call)
{
+ char tagname[PF_TAG_NAME_SIZE];
+ char match_tagname[PF_TAG_NAME_SIZE];
+ char qname[PF_QNAME_SIZE];
+
+ if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
+ errx(1, "expand_eth_rule: tagname");
+ if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
+ sizeof(match_tagname))
+ errx(1, "expand_eth_rule: match_tagname");
+ if (strlcpy(qname, r->qname, sizeof(qname)) >= sizeof(qname))
+ errx(1, "expand_eth_rule: qname");
+
LOOP_THROUGH(struct node_if, interface, interfaces,
LOOP_THROUGH(struct node_etherproto, proto, protos,
LOOP_THROUGH(struct node_mac, src, srcs,
@@ -5800,6 +5824,15 @@
r->dst.isset = dst->isset;
r->nr = pf->eastack[pf->asd]->match++;
+ if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
+ sizeof(r->tagname))
+ errx(1, "expand_eth_rule: r->tagname");
+ if (strlcpy(r->match_tagname, match_tagname,
+ sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
+ errx(1, "expand_eth_rule: r->match_tagname");
+ if (strlcpy(r->qname, qname, sizeof(r->qname)) >= sizeof(r->qname))
+ errx(1, "expand_eth_rule: r->qname");
+
pfctl_append_eth_rule(pf, r, anchor_call);
))))));
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -791,6 +791,11 @@
printf(" queue %s", r->qname);
if (r->tagname[0])
printf(" tag %s", r->tagname);
+ if (r->match_tagname[0]) {
+ if (r->match_tag_not)
+ printf(" !");
+ printf(" tagged %s", r->match_tagname);
+ }
if (r->dnpipe)
printf(" %s %d",
r->dnflags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue",
diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5
--- a/share/man/man5/pf.conf.5
+++ b/share/man/man5/pf.conf.5
@@ -744,6 +744,11 @@
Further matching rules can replace the tag with a
new one but will not remove a previously applied tag.
A packet is only ever assigned one tag at a time.
+.It Ar tagged Aq Ar string
+Used to specify that packets must already be tagged with the given tag in order
+to match the rule.
+Inverse tag matching can also be done by specifying the ! operator before the
+tagged keyword.
.Sh TRAFFIC NORMALIZATION
Traffic normalization is used to sanitize packet content in such
a way that there are no ambiguities in packet interpretation on
@@ -3083,7 +3088,7 @@
logopt = "all" | "user" | "to" interface-name
etherfilteropt-list = etherfilteropt-list etherfilteropt | etherfilteropt
-etherfilteropt = "tag" string | "queue" ( string )
+etherfilteropt = "tag" string | "tagged" string | "queue" ( string )
filteropt-list = filteropt-list filteropt | filteropt
filteropt = user | group | flags | icmp-type | icmp6-type | "tos" tos |
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -672,6 +672,10 @@
uint16_t proto;
struct pf_keth_rule_addr src, dst;
struct pf_rule_addr ipsrc, ipdst;
+ char match_tagname[PF_TAG_NAME_SIZE];
+ uint16_t match_tag;
+ bool match_tag_not;
+
/* Stats */
counter_u64_t evaluations;
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -3835,6 +3835,16 @@
return (match ^ r->neg);
}
+static int
+pf_match_eth_tag(struct mbuf *m, struct pf_keth_rule *r, int *tag, int mtag)
+{
+ if (*tag == -1)
+ *tag = mtag;
+
+ return ((!r->match_tag_not && r->match_tag == *tag) ||
+ (r->match_tag_not && r->match_tag != *tag));
+}
+
static int
pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct mbuf **m0)
{
@@ -3848,6 +3858,7 @@
sa_family_t af = 0;
uint16_t proto;
int asd = 0, match = 0;
+ int tag = -1;
uint8_t action;
struct pf_keth_anchor_stackframe anchor_stack[PF_ANCHOR_STACKSIZE];
@@ -3959,7 +3970,15 @@
"ip_dst");
r = TAILQ_NEXT(r, entries);
}
+ else if (r->match_tag && !pf_match_eth_tag(m, r, &tag,
+ mtag ? mtag->tag : 0)) {
+ SDT_PROBE3(pf, eth, test_rule, mismatch, r->nr, r,
+ "match_tag");
+ r = TAILQ_NEXT(r, entries);
+ }
else {
+ if (r->tag)
+ tag = r->tag;
if (r->anchor == NULL) {
/* Rule matches */
rm = r;
@@ -4001,7 +4020,7 @@
return (PF_DROP);
}
- if (r->tag > 0) {
+ if (tag > 0) {
if (mtag == NULL)
mtag = pf_get_mtag(m);
if (mtag == NULL) {
@@ -4009,7 +4028,7 @@
counter_u64_add(V_pf_status.counters[PFRES_MEMORY], 1);
return (PF_DROP);
}
- mtag->tag = r->tag;
+ mtag->tag = tag;
}
if (r->qid != 0) {
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -515,6 +515,8 @@
if (rule->tag)
tag_unref(&V_pf_tags, rule->tag);
+ if (rule->match_tag)
+ tag_unref(&V_pf_tags, rule->match_tag);
#ifdef ALTQ
pf_qid_unref(rule->qid);
#endif
@@ -2891,6 +2893,10 @@
if (rule->tagname[0])
if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
error = EBUSY;
+ if (rule->match_tagname[0])
+ if ((rule->match_tag = pf_tagname2tag(
+ rule->match_tagname)) == 0)
+ error = EBUSY;
if (error == 0 && rule->ipdst.addr.type == PF_ADDR_TABLE)
error = pf_eth_addr_setup(ruleset, &rule->ipdst.addr);
diff --git a/sys/netpfil/pf/pf_nv.c b/sys/netpfil/pf/pf_nv.c
--- a/sys/netpfil/pf/pf_nv.c
+++ b/sys/netpfil/pf/pf_nv.c
@@ -1057,6 +1057,9 @@
nvlist_add_bool(nvl, "ifnot", krule->ifnot);
nvlist_add_number(nvl, "direction", krule->direction);
nvlist_add_number(nvl, "proto", krule->proto);
+ nvlist_add_string(nvl, "match_tagname", krule->match_tagname);
+ nvlist_add_number(nvl, "match_tag", krule->match_tag);
+ nvlist_add_bool(nvl, "match_tag_not", krule->match_tag_not);
addr = pf_keth_rule_addr_to_nveth_rule_addr(&krule->src);
if (addr == NULL) {
@@ -1165,6 +1168,12 @@
return (EINVAL);
}
+ if (nvlist_exists_string(nvl, "match_tagname")) {
+ PFNV_CHK(pf_nvstring(nvl, "match_tagname", krule->match_tagname,
+ sizeof(krule->match_tagname)));
+ PFNV_CHK(pf_nvbool(nvl, "match_tag_not", &krule->match_tag_not));
+ }
+
PFNV_CHK(pf_nvstring(nvl, "qname", krule->qname, sizeof(krule->qname)));
PFNV_CHK(pf_nvstring(nvl, "tagname", krule->tagname,
sizeof(krule->tagname)));

File Metadata

Mime Type
text/plain
Expires
Wed, Jan 22, 7:41 AM (20 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16026771
Default Alt Text
D35362.diff (8 KB)

Event Timeline