FreeBSD Bugzilla – Attachment 255628 Details for
Bug 282984
pfctl: add -T `makezero` to touch pfras_tzero _only_ for non-zero entries
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
pfctl: add -T reset command
pfctl-add-T-reset-command.patch (text/plain), 7.85 KB, created by
Leonid Evdokimov
on 2024-12-04 15:44:26 UTC
(
hide
)
Description:
pfctl: add -T reset command
Filename:
MIME Type:
Creator:
Leonid Evdokimov
Created:
2024-12-04 15:44:26 UTC
Size:
7.85 KB
patch
obsolete
>From d05c510884e50caedd3e24f4b0db36c17a625990 Mon Sep 17 00:00:00 2001 >From: Leonid Evdokimov <leon@darkk.net.ru> >Date: Wed, 4 Dec 2024 18:17:03 +0300 >Subject: [PATCH] pfctl: add -T reset command > >`pfctl -t table -T reset` resets pfras_tzero only for the entries having >non-zero counters. That compliments -T expire with a built-in command >using counters as an indicator of network activity. > >It allows to implement a somewhat common pf table management pattern "keep >an entry in pf table while the address is active and ${TTL} seconds more" >without parsing pfctl output. > >PR: 282984 >Signed-off-by: Leonid Evdokimov <leon@darkk.net.ru> >--- > sbin/pfctl/pfctl.8 | 7 ++- > sbin/pfctl/pfctl.c | 2 +- > sbin/pfctl/pfctl_radix.c | 2 +- > sbin/pfctl/pfctl_table.c | 42 ++++++++++++++++++ > tests/sys/netpfil/pf/table.sh | 80 +++++++++++++++++++++++++++++++++++ > 5 files changed, 130 insertions(+), 3 deletions(-) > >diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8 >index 3a75c9a62ee..74d7d77fd87 100644 >--- a/sbin/pfctl/pfctl.8 >+++ b/sbin/pfctl/pfctl.8 >@@ -24,7 +24,7 @@ > .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > .\" >-.Dd November 20, 2024 >+.Dd November 25, 2024 > .Dt PFCTL 8 > .Os > .Sh NAME >@@ -503,6 +503,11 @@ Show the content (addresses) of a table. > Test if the given addresses match a table. > .It Fl T Cm zero Op Ar address ... > Clear all the statistics of a table, or only for specified addresses. >+.It Fl T Cm reset >+Clear statistics only for addresses having non-zero statistics. Addresses >+having zero counters and their >+.Dq Cleared >+timestamp are left untouched. > .It Fl T Cm load > Load only the table definitions from > .Xr pf.conf 5 . >diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c >index 621d97d6c55..5b5bfc63680 100644 >--- a/sbin/pfctl/pfctl.c >+++ b/sbin/pfctl/pfctl.c >@@ -238,7 +238,7 @@ static const char * const showopt_list[] = { > > static const char * const tblcmdopt_list[] = { > "kill", "flush", "add", "delete", "load", "replace", "show", >- "test", "zero", "expire", NULL >+ "test", "zero", "expire", "reset", NULL > }; > > static const char * const debugopt_list[] = { >diff --git a/sbin/pfctl/pfctl_radix.c b/sbin/pfctl/pfctl_radix.c >index 7d8c146c1dd..c921a029365 100644 >--- a/sbin/pfctl/pfctl_radix.c >+++ b/sbin/pfctl/pfctl_radix.c >@@ -293,7 +293,7 @@ pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size, > { > struct pfioc_table io; > >- if (size < 0 || (size && !tbl) || addr == NULL) { >+ if (size < 0 || !tbl || (size && !addr)) { > errno = EINVAL; > return (-1); > } >diff --git a/sbin/pfctl/pfctl_table.c b/sbin/pfctl/pfctl_table.c >index 95a0d0c9171..73ab0263242 100644 >--- a/sbin/pfctl/pfctl_table.c >+++ b/sbin/pfctl/pfctl_table.c >@@ -61,6 +61,7 @@ static void print_table(struct pfr_table *, int, int); > static void print_tstats(struct pfr_tstats *, int); > static int load_addr(struct pfr_buffer *, int, char *[], char *, int); > static void print_addrx(struct pfr_addr *, struct pfr_addr *, int); >+static int nonzero_astats(struct pfr_astats *); > static void print_astats(struct pfr_astats *, int); > static void radix_perror(void); > static void xprintf(int, const char *, ...); >@@ -294,6 +295,36 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, > if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) > print_addrx(a, NULL, > opts & PF_OPT_USEDNS); >+ } else if (!strcmp(command, "reset")) { >+ struct pfr_astats *as; >+ >+ b.pfrb_type = PFRB_ASTATS; >+ b2.pfrb_type = PFRB_ADDRS; >+ if (argc || file != NULL) >+ usage(); >+ do { >+ pfr_buf_grow(&b, b.pfrb_size); >+ b.pfrb_size = b.pfrb_msize; >+ RVTEST(pfr_get_astats(&table, b.pfrb_caddr, >+ &b.pfrb_size, flags)); >+ } while (b.pfrb_size > b.pfrb_msize); >+ PFRB_FOREACH(as, &b) { >+ as->pfras_a.pfra_fback = 0; >+ if (nonzero_astats(as)) >+ if (pfr_buf_add(&b2, &as->pfras_a)) >+ err(1, "duplicate buffer"); >+ } >+ >+ if (opts & PF_OPT_VERBOSE) >+ flags |= PFR_FLAG_FEEDBACK; >+ RVTEST(pfr_clr_astats(&table, b2.pfrb_caddr, b2.pfrb_size, >+ &nzero, flags)); >+ xprintf(opts, "%d/%d stats cleared", nzero, b.pfrb_size); >+ if (opts & PF_OPT_VERBOSE) >+ PFRB_FOREACH(a, &b2) >+ if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) >+ print_addrx(a, NULL, >+ opts & PF_OPT_USEDNS); > } else if (!strcmp(command, "show")) { > b.pfrb_type = (opts & PF_OPT_VERBOSE) ? > PFRB_ASTATS : PFRB_ADDRS; >@@ -485,6 +516,17 @@ print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns) > printf("\n"); > } > >+int >+nonzero_astats(struct pfr_astats *as) >+{ >+ u_int64_t s = 0; >+ for (int dir = 0; dir < PFR_DIR_MAX; dir++) >+ for (int op = 0; op < PFR_OP_ADDR_MAX; op++) >+ s |= as->pfras_packets[dir][op] | >+ as->pfras_bytes[dir][op]; >+ return !!s; >+} >+ > void > print_astats(struct pfr_astats *as, int dns) > { >diff --git a/tests/sys/netpfil/pf/table.sh b/tests/sys/netpfil/pf/table.sh >index 828d76a998b..62c9d66d80c 100644 >--- a/tests/sys/netpfil/pf/table.sh >+++ b/tests/sys/netpfil/pf/table.sh >@@ -165,6 +165,85 @@ zero_one_cleanup() > pft_cleanup > } > >+atf_test_case "reset_nonzero" "cleanup" >+reset_nonzero_head() >+{ >+ atf_set descr 'Test zeroing an address with non-zero counters' >+ atf_set require.user root >+} >+ >+reset_nonzero_body() >+{ >+ epair_send=$(vnet_mkepair) >+ ifconfig ${epair_send}a 192.0.2.1/24 up >+ ifconfig ${epair_send}a inet alias 192.0.2.3/24 >+ >+ vnet_mkjail alcatraz ${epair_send}b >+ jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up >+ jexec alcatraz pfctl -e >+ >+ pft_set_rules alcatraz \ >+ "table <foo> counters { 192.0.2.1, 192.0.2.3 }" \ >+ "table <bar> counters { }" \ >+ "block all" \ >+ "pass in from <foo> to any" \ >+ "pass out from any to <foo>" \ >+ "pass on notReallyAnIf from <bar> to <bar>" \ >+ "set skip on lo" >+ >+ # Nonexisting table can't be reset, following `-T show`. >+ atf_check -o ignore \ >+ -s not-exit:0 \ >+ -e inline:"pfctl: Table does not exist.\n" \ >+ jexec alcatraz pfctl -t nonexistent -T reset >+ >+ atf_check -o ignore \ >+ -s exit:0 \ >+ -e inline:"0/0 stats cleared.\n" \ >+ jexec alcatraz pfctl -t bar -T reset >+ >+ # No-op is a valid operation. >+ atf_check -s exit:0 \ >+ -e inline:"0/2 stats cleared.\n" \ >+ jexec alcatraz pfctl -t foo -T reset >+ >+ atf_check -s exit:0 -o ignore ping -c 3 -S 192.0.2.3 192.0.2.2 >+ >+ atf_check -s exit:0 -e ignore \ >+ -o match:'In/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ >+ -o match:'In/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ >+ -o match:'Out/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ >+ -o match:'Out/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ >+ jexec alcatraz pfctl -t foo -vvT show >+ >+ local clrd uniq >+ clrd=`jexec alcatraz pfctl -t foo -vvT show | grep -c Cleared` >+ uniq=`jexec alcatraz pfctl -t foo -vvT show | sort -u | grep -c Cleared` >+ atf_check_equal "$clrd" 2 >+ atf_check_equal "$uniq" 1 # time they were added >+ >+ atf_check -s exit:0 -e ignore \ >+ -e inline:"1/2 stats cleared.\n" \ >+ jexec alcatraz pfctl -t foo -T reset >+ >+ clrd=`jexec alcatraz pfctl -t foo -vvT show | grep -c Cleared` >+ uniq=`jexec alcatraz pfctl -t foo -vvT show | sort -u | grep -c Cleared` >+ atf_check_equal "$clrd" 2 >+ atf_check_equal "$uniq" 2 # 192.0.2.3 should get new timestamp >+ >+ atf_check -s exit:0 -e ignore \ >+ -o not-match:'In/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ >+ -o not-match:'Out/Pass:.*'"$TABLE_STATS_NONZERO_REGEXP" \ >+ -o match:'In/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ >+ -o match:'Out/Pass:.*'"$TABLE_STATS_ZERO_REGEXP" \ >+ jexec alcatraz pfctl -t foo -vvT show >+} >+ >+reset_nonzero_cleanup() >+{ >+ pft_cleanup >+} >+ > atf_test_case "pr251414" "cleanup" > pr251414_head() > { >@@ -381,6 +460,7 @@ atf_init_test_cases() > atf_add_test_case "v4_counters" > atf_add_test_case "v6_counters" > atf_add_test_case "zero_one" >+ atf_add_test_case "reset_nonzero" > atf_add_test_case "pr251414" > atf_add_test_case "automatic" > atf_add_test_case "network" >-- >2.47.0 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 282984
:
255466
|
255471
| 255628 |
256136