From nobody Mon Dec 09 09:39:27 2024 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Y6GzM4zdMz5g3KF; Mon, 09 Dec 2024 09:39:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Y6GzM4B5pz4fcQ; Mon, 9 Dec 2024 09:39:27 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1733737167; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=6bN0iGWFQ//gbPW4wDAmnBa7P4Ojd1szo27M2Xnnckw=; b=kBwaJ8+1c6Xkyc+HB3351QABrE9zKvaE3/xvBS14mhIBclCn26lLrsZqWeO3+H6LAnxnhe JPS/6Y6kt5cdkE77sPbU1Jp9olQhC1Kh9/jwe8fFqNnDA10i5Cmt2YXKwX1gjy8sI2/Cnr NrCm03r7xiM2J47zEhE4q7XPyP2QQ0/2tW1Gz8bjKZKCD7bWEeJi/dxJtGMMW6yxjS4vsk ip4StrtHWCTM5zc6/SWE1LEEUDLhOuIj/HBIrei78pUn2DE7AkVlwA/SA/M7H1yeulelED a78B20QFeVwi9vEeIlhJQjLYm2v4+DTXkA6mXFUUG7qTqUyu/JLtPakXiFohzA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1733737167; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=6bN0iGWFQ//gbPW4wDAmnBa7P4Ojd1szo27M2Xnnckw=; b=EaDBsh7ZfnNU/cVGtSvbnq3lBQtrUXPol1/PEC7+OlaCQVdi932y7+GsAoYq5qjmGoZ8Dy e0sGKDfq671uIyY49H71DMqfvv3stLBS9+y/aU12YJtlIMDJci5+kpGvB3Y8+20EiNqACv Sw3ToRWhE24VICrVpd8UckVuubT2nY5m90dbeNRvcDX4Z1gspo0lbv3Qg+OnmMEmhBvONl N5wqUWaEcdvqUaWQ7RyT/uh7/v50m64e4CkqosFoHaRdb9o1HGvDy4xFuF+qI1UxYeJ1x5 iWn3i30wAYOCTGdxdRKjQHjGEGqs8938KCTuRKTwAM2xH+JkSP5YfngmqFQiVQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1733737167; a=rsa-sha256; cv=none; b=irvV5YhFJIZ+0jJ52kxkyZw71VvWKOD8TGxlPsNIUnsHoubyc3avKi+xmubPxCPAcHWJWE fcwE8mKSprATtwi3n9F1SUTkPVK+rmQGw9TbCG38eeQ2/yYSi1ngZycbVrXjNq3/wVmYhg PwS6tlmpex6eY+MWg1uxlaMOWvSXD8Cxtul0SydXdHDASRsJUtSGl5qhp2zeD+KoKVzgVi yhCWAEZqiooeRECs9dPne8ewJryWEkLFfGTjEZQolpdsTYct00w3jeYnttVclizKC4jChi YN+5y8eXXqjg6CKbuTaVLwuPLlMsTCgnPI519O8uiyndMe4ia7d3tU1GeRNfQg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Y6GzM3nJJzXcb; Mon, 9 Dec 2024 09:39:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 4B99dRXD072157; Mon, 9 Dec 2024 09:39:27 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 4B99dRhr072153; Mon, 9 Dec 2024 09:39:27 GMT (envelope-from git) Date: Mon, 9 Dec 2024 09:39:27 GMT Message-Id: <202412090939.4B99dRhr072153@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: 5b59b0c61e29 - main - pfctl: add -T `reset` to touch pfras_tzero only for non-zero entries List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 5b59b0c61e29f684a019afdd2848ffe2d5604e0c Auto-Submitted: auto-generated The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=5b59b0c61e29f684a019afdd2848ffe2d5604e0c commit 5b59b0c61e29f684a019afdd2848ffe2d5604e0c Author: Leonid Evdokimov AuthorDate: 2024-12-06 12:08:54 +0000 Commit: Kristof Provost CommitDate: 2024-12-09 09:36:34 +0000 pfctl: add -T `reset` to touch pfras_tzero only for non-zero entries This will make it easier for scripts to detect idle hosts in tables. PR: 282984 Reviewed by: kp MFC after: 2 weeks --- sbin/pfctl/pfctl.8 | 7 +++- sbin/pfctl/pfctl.c | 2 +- sbin/pfctl/pfctl_radix.c | 2 +- sbin/pfctl/pfctl_table.c | 44 ++++++++++++++++++++++++ tests/sys/netpfil/pf/table.sh | 80 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 3 deletions(-) diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8 index 45a6ea525694..00fbda042b7c 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 @@ -508,6 +508,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 with non-zero statistics. Addresses +with counter values at zero 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 555c5181eac8..aa3db4619972 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -239,7 +239,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 749e8b4affc9..9bea219a7d81 100644 --- a/sbin/pfctl/pfctl_radix.c +++ b/sbin/pfctl/pfctl_radix.c @@ -292,7 +292,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 25d9b87d8718..aac031ce26b2 100644 --- a/sbin/pfctl/pfctl_table.c +++ b/sbin/pfctl/pfctl_table.c @@ -60,6 +60,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 *, ...); @@ -293,6 +294,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; @@ -484,6 +515,19 @@ print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns) printf("\n"); } +int +nonzero_astats(struct pfr_astats *as) +{ + uint64_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 828d76a998be..62c9d66d80ce 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 counters { 192.0.2.1, 192.0.2.3 }" \ + "table counters { }" \ + "block all" \ + "pass in from to any" \ + "pass out from any to " \ + "pass on notReallyAnIf from to " \ + "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"