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 (da64f6e047), which is
no longer needed.

Add a regression test.

Reviewed by:		kp
Approved by:		kp (mentor)
Fixes:			08ed87a4a2 ("pf: convert DIOCRSETADDRS to netlink")
MFC after:		1 week
Sponsored by:		Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D60174
This commit is contained in:
R. Christian McDonald committed 2026-09-30 19:23:21 -04:00
1 parent c1241c6e30
commit 55a69b9be8
3 files changed
+54 -3

No files matched your search

+16
View File
@@ -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,
-3
View File
@@ -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;
+38
View File
@@ -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"