git: 55a69b9be886 - main - libpfctl: zero the counters before summing per-chunk results
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 30 Sep 2026 23:31:21 UTC
The branch main has been updated by rcm:
URL: https://cgit.FreeBSD.org/src/commit/?id=55a69b9be886731087894ab0b3851215ff791ef9
commit 55a69b9be886731087894ab0b3851215ff791ef9
Author: R. Christian McDonald <rcm@FreeBSD.org>
AuthorDate: 2026-09-30 23:23:21 +0000
Commit: R. Christian McDonald <rcm@FreeBSD.org>
CommitDate: 2026-09-30 23:23:21 +0000
libpfctl: zero the counters before summing per-chunk results
The chunked table address functions (set, add, del, clr_astats) add
each chunk's result to the caller's counter without initialising it.
pfctl reuses nadd for the number of tables created, so a replace that
also creates the table is off by one:
pfctl -t foo -T replace 192.0.2.1
reports "2 addresses added".
Zero the counters first, as pfctl_test_addrs() already does. Remove
the workaround for the add case from pfctl (da64f6e047b5), which is
no longer needed.
Add a regression test.
Reviewed by: kp
Approved by: kp (mentor)
Fixes: 08ed87a4a276 ("pf: convert DIOCRSETADDRS to netlink")
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D60174
---
lib/libpfctl/libpfctl.c | 16 ++++++++++++++++
sbin/pfctl/pfctl_radix.c | 3 ---
tests/sys/netpfil/pf/table.sh | 38 ++++++++++++++++++++++++++++++++++++++
3 files changed, 54 insertions(+), 3 deletions(-)
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index a7dbc0a412aa..aa3f4ec30f74 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -2517,6 +2517,9 @@ pfctl_table_add_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl, struct pf
int partial_added;
int chunk_size;
+ if (nadd)
+ *nadd = 0;
+
do {
chunk_size = MIN(size - off, 256);
ret = _pfctl_table_add_addrs_h(h, tbl, &addr[off], chunk_size, &partial_added, flags);
@@ -2609,6 +2612,9 @@ pfctl_table_del_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl, struct pf
int partial_deleted;
int chunk_size;
+ if (ndel)
+ *ndel = 0;
+
do {
chunk_size = MIN(size - off, 256);
ret = _pfctl_table_del_addrs_h(h, tbl, &addr[off], chunk_size,
@@ -2694,6 +2700,13 @@ pfctl_table_set_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl,
int partial_add, partial_del, partial_change;
int chunk_size;
+ if (nadd)
+ *nadd = 0;
+ if (ndel)
+ *ndel = 0;
+ if (nchange)
+ *nchange = 0;
+
do {
flags &= ~(PFR_FLAG_START | PFR_FLAG_DONE);
if (off == 0)
@@ -3984,6 +3997,9 @@ pfctl_clr_astats(struct pfctl_handle *h, const struct pfr_table *tbl,
int partial_zeroed;
int chunk_size;
+ if (nzero)
+ *nzero = 0;
+
do {
chunk_size = MIN(size - off, 256);
ret = _pfctl_clr_astats(h, tbl, &addrs[off], chunk_size,
diff --git a/sbin/pfctl/pfctl_radix.c b/sbin/pfctl/pfctl_radix.c
index d99923e4fb67..088c41e0583e 100644
--- a/sbin/pfctl/pfctl_radix.c
+++ b/sbin/pfctl/pfctl_radix.c
@@ -136,9 +136,6 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
{
int ret;
- if (*nadd)
- *nadd = 0;
-
ret = pfctl_table_add_addrs_h(pfh, tbl, addr, size, nadd, flags);
if (ret) {
errno = ret;
diff --git a/tests/sys/netpfil/pf/table.sh b/tests/sys/netpfil/pf/table.sh
index 24201588ddbf..9c93df781852 100644
--- a/tests/sys/netpfil/pf/table.sh
+++ b/tests/sys/netpfil/pf/table.sh
@@ -878,6 +878,43 @@ replace_verbose_cleanup()
pft_cleanup
}
+atf_test_case "replace_create" "cleanup"
+replace_create_head()
+{
+ atf_set descr 'Test the counts of a replace that creates the table'
+ atf_set require.user root
+}
+
+replace_create_body()
+{
+ pft_init
+ pwd=$(pwd)
+
+ vnet_mkjail alcatraz
+ jexec alcatraz pfctl -e
+
+ # libpfctl used to add the number of addresses to whatever the
+ # caller's counter held, which here is the number of tables created.
+ atf_check -s exit:0 -e "match:^1 table created\.$" \
+ -e "match:^1 addresses added\.$" \
+ jexec alcatraz pfctl -t foo -T replace 192.0.2.1
+
+ # More than one chunk of addresses.
+ for i in `seq 1 2`; do
+ for j in `seq 1 150`; do
+ echo "1.${i}.${j}.1" >> ${pwd}/bar.lst
+ done
+ done
+ atf_check -s exit:0 -e "match:^1 table created\.$" \
+ -e "match:^300 addresses added\.$" \
+ jexec alcatraz pfctl -t bar -T replace -f ${pwd}/bar.lst
+}
+
+replace_create_cleanup()
+{
+ pft_cleanup
+}
+
atf_test_case "load" "cleanup"
load_head()
{
@@ -1002,6 +1039,7 @@ atf_init_test_cases()
atf_add_test_case "in_anchor"
atf_add_test_case "replace"
atf_add_test_case "replace_verbose"
+ atf_add_test_case "replace_create"
atf_add_test_case "load"
atf_add_test_case "test"
atf_add_test_case "show_no_counters"