Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108092124
D35362.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D35362.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D35362: pf: support matching on tags for Ethernet rules
Attached
Detach File
Event Timeline
Log In to Comment