The branch main has been updated by kp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ef661d4a5bf912e4d4850faaf50664532d82541c

commit ef661d4a5bf912e4d4850faaf50664532d82541c
Author:     Christian McDonald <[email protected]>
AuthorDate: 2023-04-24 18:55:34 +0000
Commit:     Kristof Provost <[email protected]>
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);
 }

Reply via email to