The branch main has been updated by mjg:

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

commit c4a08ef2af6fe0b0d1b03f7ec4f20bed96de20e8
Author:     Mateusz Guzik <[email protected]>
AuthorDate: 2022-04-01 15:04:03 +0000
Commit:     Mateusz Guzik <[email protected]>
CommitDate: 2022-04-01 18:01:48 +0000

    pf: handle duplicate rules gracefully
    
    Reviewed by:    kp
    Reported by:    dch
    PR:             262971
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 lib/libpfctl/libpfctl.c   |  2 ++
 sbin/pfctl/pfctl.c        | 19 +++++++++++++++++--
 sys/netpfil/pf/pf_ioctl.c |  5 +++--
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index 8696ef1ace25..991d3fce9780 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -961,6 +961,8 @@ pfctl_add_rule(int dev, const struct pfctl_rule *r, const 
char *anchor,
        nv.size = nv.len;
 
        ret = ioctl(dev, DIOCADDRULENV, &nv);
+       if (ret == -1)
+               ret = errno;
 
        free(nv.data);
        nvlist_destroy(nvl);
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 67358a325f77..13e8e825c1ab 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1846,6 +1846,8 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct 
pfctl_rule *r, int depth)
        u_int32_t               ticket;
        char                    anchor[PF_ANCHOR_NAME_SIZE];
        int                     len = strlen(path);
+       int                     error;
+       bool                    was_present;
 
        /* set up anchor before adding to path for anchor_call */
        if ((pf->opts & PF_OPT_NOACTION) == 0)
@@ -1867,12 +1869,23 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct 
pfctl_rule *r, int depth)
        } else
                name = "";
 
+       was_present = false;
        if ((pf->opts & PF_OPT_NOACTION) == 0) {
                if (pfctl_add_pool(pf, &r->rpool, r->af))
                        return (1);
-               if (pfctl_add_rule(pf->dev, r, anchor, name, ticket,
-                   pf->paddr.ticket))
+               error = pfctl_add_rule(pf->dev, r, anchor, name, ticket,
+                   pf->paddr.ticket);
+               switch (error) {
+               case 0:
+                       /* things worked, do nothing */
+                       break;
+               case EEXIST:
+                       /* an identical rule is already present */
+                       was_present = true;
+                       break;
+               default:
                        err(1, "DIOCADDRULENV");
+               }
        }
 
        if (pf->opts & PF_OPT_VERBOSE) {
@@ -1880,6 +1893,8 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct 
pfctl_rule *r, int depth)
                print_rule(r, r->anchor ? r->anchor->name : "",
                    pf->opts & PF_OPT_VERBOSE2,
                    pf->opts & PF_OPT_NUMERIC);
+               if (was_present)
+                       printf(" -- rule was already present");
        }
        path[len] = '\0';
        pfctl_clear_pool(&r->rpool);
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index eae7b3bf1fa0..c170a270454b 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -2240,10 +2240,11 @@ pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
        pf_hash_rule(rule);
        if (RB_INSERT(pf_krule_global, ruleset->rules[rs_num].inactive.tree, 
rule) != NULL) {
                PF_RULES_WLOCK();
+               TAILQ_REMOVE(ruleset->rules[rs_num].inactive.ptr, rule, 
entries);
+               ruleset->rules[rs_num].inactive.rcount--;
                pf_free_rule(rule);
                rule = NULL;
-               error = EINVAL;
-               ERROUT(error);
+               ERROUT(EEXIST);
        }
        PF_CONFIG_UNLOCK();
 

Reply via email to