git: c4a08ef2af6f - main - pf: handle duplicate rules gracefully
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 01 Apr 2022 18:02:09 UTC
The branch main has been updated by mjg:
URL: https://cgit.FreeBSD.org/src/commit/?id=c4a08ef2af6fe0b0d1b03f7ec4f20bed96de20e8
commit c4a08ef2af6fe0b0d1b03f7ec4f20bed96de20e8
Author: Mateusz Guzik <mjg@FreeBSD.org>
AuthorDate: 2022-04-01 15:04:03 +0000
Commit: Mateusz Guzik <mjg@FreeBSD.org>
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();