git: ef661d4a5bf9 - main - pf: introduce ridentifier and labels to ether rules
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 26 Apr 2023 09:19:47 UTC
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=ef661d4a5bf912e4d4850faaf50664532d82541c
commit ef661d4a5bf912e4d4850faaf50664532d82541c
Author: Christian McDonald <cmcdonald@netgate.com>
AuthorDate: 2023-04-24 18:55:34 +0000
Commit: Kristof Provost <kp@FreeBSD.org>
CommitDate: 2023-04-26 09:14:41 +0000
pf: introduce ridentifier and labels to ether rules
Make Ethernet rules more similar to the usual layer 3 rules by also
allowing ridentifier and labels to be set on them.
Reviewed by: kp
Sponsored by: Rubicon Communications, LLC ("Netgate")
---
lib/libpfctl/libpfctl.c | 20 +++++++++++++++++++-
lib/libpfctl/libpfctl.h | 3 +++
sbin/pfctl/parse.y | 33 +++++++++++++++++++++++++++++++++
sbin/pfctl/pfctl_parser.c | 9 +++++++++
sbin/pfctl/tests/files/pf1013.in | 1 +
sbin/pfctl/tests/files/pf1013.ok | 1 +
sbin/pfctl/tests/files/pf1014.in | 1 +
sbin/pfctl/tests/files/pf1014.ok | 1 +
sbin/pfctl/tests/files/pf1015.in | 1 +
sbin/pfctl/tests/files/pf1015.ok | 1 +
sbin/pfctl/tests/files/pf1016.in | 1 +
sbin/pfctl/tests/files/pf1016.ok | 1 +
sbin/pfctl/tests/files/pf1017.in | 1 +
sbin/pfctl/tests/files/pf1017.ok | 1 +
sbin/pfctl/tests/pfctl_test_list.inc | 5 +++++
share/man/man5/pf.conf.5 | 5 +++--
sys/net/pfvar.h | 3 +++
sys/netpfil/pf/pf_nv.c | 27 +++++++++++++++++++++++++++
18 files changed, 112 insertions(+), 3 deletions(-)
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index c75f9ab12889..4f251e92d9aa 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -625,6 +625,9 @@ pfctl_eth_addr_to_nveth_addr(const struct pfctl_eth_addr *addr)
static void
pfctl_nveth_rule_to_eth_rule(const nvlist_t *nvl, struct pfctl_eth_rule *rule)
{
+ const char *const *labels;
+ size_t labelcount, i;
+
rule->nr = nvlist_get_number(nvl, "nr");
rule->quick = nvlist_get_bool(nvl, "quick");
strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ);
@@ -636,6 +639,12 @@ pfctl_nveth_rule_to_eth_rule(const nvlist_t *nvl, struct pfctl_eth_rule *rule)
rule->match_tag = nvlist_get_number(nvl, "match_tag");
rule->match_tag_not = nvlist_get_bool(nvl, "match_tag_not");
+ labels = nvlist_get_string_array(nvl, "labels", &labelcount);
+ assert(labelcount <= PF_RULE_MAX_LABEL_COUNT);
+ for (i = 0; i < labelcount; i++)
+ strlcpy(rule->label[i], labels[i], PF_RULE_LABEL_SIZE);
+ rule->ridentifier = nvlist_get_number(nvl, "ridentifier");
+
pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "src"),
&rule->src);
pfctl_nveth_addr_to_eth_addr(nvlist_get_nvlist(nvl, "dst"),
@@ -775,7 +784,7 @@ pfctl_add_eth_rule(int dev, const struct pfctl_eth_rule *r, const char *anchor,
nvlist_t *nvl, *addr;
void *packed;
int error = 0;
- size_t size;
+ size_t labelcount, size;
nvl = nvlist_create(0);
@@ -811,6 +820,15 @@ pfctl_add_eth_rule(int dev, const struct pfctl_eth_rule *r, const char *anchor,
pfctl_nv_add_rule_addr(nvl, "ipsrc", &r->ipsrc);
pfctl_nv_add_rule_addr(nvl, "ipdst", &r->ipdst);
+ labelcount = 0;
+ while (r->label[labelcount][0] != 0 &&
+ labelcount < PF_RULE_MAX_LABEL_COUNT) {
+ nvlist_append_string_array(nvl, "labels",
+ r->label[labelcount]);
+ labelcount++;
+ }
+ nvlist_add_number(nvl, "ridentifier", r->ridentifier);
+
nvlist_add_string(nvl, "qname", r->qname);
nvlist_add_string(nvl, "tagname", r->tagname);
nvlist_add_number(nvl, "dnpipe", r->dnpipe);
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index 1a07b74dc10f..064adafcf3ed 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -87,6 +87,9 @@ struct pfctl_eth_addr {
struct pfctl_eth_rule {
uint32_t nr;
+ char label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE];
+ uint32_t ridentifier;
+
bool quick;
/* Filter */
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index e5629f9fcd5f..b0f631a5998c 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -379,6 +379,7 @@ int expand_skip_interface(struct node_if *);
int check_rulestate(int);
int getservice(char *);
int rule_label(struct pfctl_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
+int eth_rule_label(struct pfctl_eth_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
int rt_tableid_max(void);
void mv_rules(struct pfctl_ruleset *, struct pfctl_ruleset *);
@@ -1243,6 +1244,11 @@ etherrule : ETHER action dir quick interface bridge etherproto etherfromto l3fro
memcpy(&r.qname, $10.queues.qname, sizeof(r.qname));
r.dnpipe = $10.dnpipe;
r.dnflags = $10.free_flags;
+ if (eth_rule_label(&r, $10.label))
+ YYERROR;
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
+ free($10.label[i]);
+ r.ridentifier = $10.ridentifier;
expand_eth_rule(&r, $5, $7, $8.src, $8.dst,
$9.src.host, $9.dst.host, $6, "");
@@ -1366,6 +1372,16 @@ etherfilter_opt : etherqname {
}
filter_opts.queues = $1;
}
+ | RIDENTIFIER number {
+ filter_opts.ridentifier = $2;
+ }
+ | label {
+ if (filter_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) {
+ yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT);
+ YYERROR;
+ }
+ filter_opts.label[filter_opts.labelcount++] = $1;
+ }
| TAG string {
filter_opts.tag = $2;
}
@@ -6945,6 +6961,23 @@ rule_label(struct pfctl_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT])
return (0);
}
+int
+eth_rule_label(struct pfctl_eth_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT])
+{
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
+ if (s[i] == NULL)
+ return (0);
+
+ if (strlcpy(r->label[i], s[i], sizeof(r->label[0])) >=
+ sizeof(r->label[0])) {
+ yyerror("rule label too long (max %d chars)",
+ sizeof(r->label[0])-1);
+ return (-1);
+ }
+ }
+ return (0);
+}
+
u_int16_t
parseicmpspec(char *w, sa_family_t af)
{
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index 1f8627f5e246..c3aa840bca40 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -755,6 +755,8 @@ print_eth_rule(struct pfctl_eth_rule *r, const char *anchor_call,
static const char *actiontypes[] = { "pass", "block", "", "", "", "",
"", "", "", "", "", "", "match" };
+ int i;
+
if (rule_numbers)
printf("@%u ", r->nr);
@@ -797,6 +799,13 @@ print_eth_rule(struct pfctl_eth_rule *r, const char *anchor_call,
print_fromto(&r->ipsrc, PF_OSFP_ANY, &r->ipdst,
r->proto == ETHERTYPE_IP ? AF_INET : AF_INET6, 0,
0, 0);
+
+ i = 0;
+ while (r->label[i][0])
+ printf(" label \"%s\"", r->label[i++]);
+ if (r->ridentifier)
+ printf(" ridentifier %u", r->ridentifier);
+
if (r->qname[0])
printf(" queue %s", r->qname);
if (r->tagname[0])
diff --git a/sbin/pfctl/tests/files/pf1013.in b/sbin/pfctl/tests/files/pf1013.in
new file mode 100644
index 000000000000..053804e1a35a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1013.in
@@ -0,0 +1 @@
+ether block out on igb0 ridentifier 12345678
diff --git a/sbin/pfctl/tests/files/pf1013.ok b/sbin/pfctl/tests/files/pf1013.ok
new file mode 100644
index 000000000000..7395f3fd6311
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1013.ok
@@ -0,0 +1 @@
+ether block out on igb0 l3 all ridentifier 12345678
diff --git a/sbin/pfctl/tests/files/pf1014.in b/sbin/pfctl/tests/files/pf1014.in
new file mode 100644
index 000000000000..8739034f1bda
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1014.in
@@ -0,0 +1 @@
+ether block out on igb0 label "test"
diff --git a/sbin/pfctl/tests/files/pf1014.ok b/sbin/pfctl/tests/files/pf1014.ok
new file mode 100644
index 000000000000..d0086cb25e54
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1014.ok
@@ -0,0 +1 @@
+ether block out on igb0 l3 all label "test"
diff --git a/sbin/pfctl/tests/files/pf1015.in b/sbin/pfctl/tests/files/pf1015.in
new file mode 100644
index 000000000000..11c7a211ae8a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1015.in
@@ -0,0 +1 @@
+ether block out on igb0 label "test" label "another label"
diff --git a/sbin/pfctl/tests/files/pf1015.ok b/sbin/pfctl/tests/files/pf1015.ok
new file mode 100644
index 000000000000..d3ea76f1875b
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1015.ok
@@ -0,0 +1 @@
+ether block out on igb0 l3 all label "test" label "another label"
diff --git a/sbin/pfctl/tests/files/pf1016.in b/sbin/pfctl/tests/files/pf1016.in
new file mode 100644
index 000000000000..a7b1f6bc0ca9
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1016.in
@@ -0,0 +1 @@
+ether block out on igb0 label "test" ridentifier 12345678
diff --git a/sbin/pfctl/tests/files/pf1016.ok b/sbin/pfctl/tests/files/pf1016.ok
new file mode 100644
index 000000000000..f1d59c988730
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1016.ok
@@ -0,0 +1 @@
+ether block out on igb0 l3 all label "test" ridentifier 12345678
diff --git a/sbin/pfctl/tests/files/pf1017.in b/sbin/pfctl/tests/files/pf1017.in
new file mode 100644
index 000000000000..ad523337bdc5
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1017.in
@@ -0,0 +1 @@
+ether block out on igb0 label "test" label "another test" ridentifier 12345678
diff --git a/sbin/pfctl/tests/files/pf1017.ok b/sbin/pfctl/tests/files/pf1017.ok
new file mode 100644
index 000000000000..0efdd55e27a0
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1017.ok
@@ -0,0 +1 @@
+ether block out on igb0 l3 all label "test" label "another test" ridentifier 12345678
diff --git a/sbin/pfctl/tests/pfctl_test_list.inc b/sbin/pfctl/tests/pfctl_test_list.inc
index 0b7d89099efe..7caf66221e2d 100644
--- a/sbin/pfctl/tests/pfctl_test_list.inc
+++ b/sbin/pfctl/tests/pfctl_test_list.inc
@@ -123,3 +123,8 @@ PFCTL_TEST(1009, "Ethernet rule with mask")
PFCTL_TEST(1010, "POM_STICKYADDRESS test")
PFCTL_TEST(1011, "Test disabling scrub fragment reassemble")
PFCTL_TEST(1012, "Test scrub fragment reassemble is default")
+PFCTL_TEST(1013, "Ethernet rule with ridentifier")
+PFCTL_TEST(1014, "Ethernet rule with one label")
+PFCTL_TEST(1015, "Ethernet rule with several labels")
+PFCTL_TEST(1016, "Ethernet rule with ridentifier and one label")
+PFCTL_TEST(1017, "Ethernet rule with ridentifier and several labels")
diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5
index 88c509f36ff7..8292812f7817 100644
--- a/share/man/man5/pf.conf.5
+++ b/share/man/man5/pf.conf.5
@@ -28,7 +28,7 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd April 21, 2023
+.Dd April 26, 2023
.Dt PF.CONF 5
.Os
.Sh NAME
@@ -3108,7 +3108,8 @@ logopts = logopt [ "," logopts ]
logopt = "all" | "user" | "to" interface-name
etherfilteropt-list = etherfilteropt-list etherfilteropt | etherfilteropt
-etherfilteropt = "tag" string | "tagged" string | "queue" ( string )
+etherfilteropt = "tag" string | "tagged" string | "queue" ( string ) |
+ "ridentifier" number | "label" 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
index 2f017923afa1..a82735f71c8c 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -703,6 +703,9 @@ struct pf_keth_rule {
uint8_t action;
uint16_t dnpipe;
uint32_t dnflags;
+
+ char label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE];
+ uint32_t ridentifier;
};
union pf_krule_ptr {
diff --git a/sys/netpfil/pf/pf_nv.c b/sys/netpfil/pf/pf_nv.c
index 544477407861..4391dc0ef8d5 100644
--- a/sys/netpfil/pf/pf_nv.c
+++ b/sys/netpfil/pf/pf_nv.c
@@ -1051,6 +1051,11 @@ pf_keth_rule_to_nveth_rule(const struct pf_keth_rule *krule)
if (nvl == NULL)
return (NULL);
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
+ nvlist_append_string_array(nvl, "labels", krule->label[i]);
+ }
+ nvlist_add_number(nvl, "ridentifier", krule->ridentifier);
+
nvlist_add_number(nvl, "nr", krule->nr);
nvlist_add_bool(nvl, "quick", krule->quick);
nvlist_add_string(nvl, "ifname", krule->ifname);
@@ -1126,8 +1131,29 @@ pf_nveth_rule_to_keth_rule(const nvlist_t *nvl,
{
int error = 0;
+#define ERROUT(x) ERROUT_FUNCTION(errout, x)
+
bzero(krule, sizeof(*krule));
+ if (nvlist_exists_string_array(nvl, "labels")) {
+ const char *const *strs;
+ size_t items;
+ int ret;
+
+ strs = nvlist_get_string_array(nvl, "labels", &items);
+ if (items > PF_RULE_MAX_LABEL_COUNT)
+ ERROUT(E2BIG);
+
+ for (size_t i = 0; i < items; i++) {
+ ret = strlcpy(krule->label[i], strs[i],
+ sizeof(krule->label[0]));
+ if (ret >= sizeof(krule->label[0]))
+ ERROUT(E2BIG);
+ }
+ }
+
+ PFNV_CHK(pf_nvuint32_opt(nvl, "ridentifier", &krule->ridentifier, 0));
+
PFNV_CHK(pf_nvuint32(nvl, "nr", &krule->nr));
PFNV_CHK(pf_nvbool(nvl, "quick", &krule->quick));
PFNV_CHK(pf_nvstring(nvl, "ifname", krule->ifname,
@@ -1192,6 +1218,7 @@ pf_nveth_rule_to_keth_rule(const nvlist_t *nvl,
krule->action != PF_MATCH)
return (EBADMSG);
+#undef ERROUT
errout:
return (error);
}