From: Kirill A. Korinsky Subject: pfctl: clear statistic for the address To: OpenBSD tech Date: Wed, 20 Nov 2024 12:13:03 +0100 tech@, I'd like to propose a patch that adds to pfctl a way to clear statistics for specified address from the table. A usecase for this patch is explained here: https://marc.info/?l=openbsd-bugs&m=173206758904599&w=2 Feedback? Ok? Index: pfctl.8 =================================================================== RCS file: /home/cvs/src/sbin/pfctl/pfctl.8,v diff -u -p -r1.183 pfctl.8 --- pfctl.8 18 Nov 2022 18:11:10 -0000 1.183 +++ pfctl.8 20 Nov 2024 11:07:01 -0000 @@ -517,8 +517,8 @@ Automatically create a persistent table Show the content (addresses) of a table. .It Fl T Cm test Test if the given addresses match a table. -.It Fl T Cm zero -Clear all the statistics of a table. +.It Fl T Cm zero Op Ar address ... +Clear all the statistics of a table, or only for specified addresses. .El .Pp For the Index: pfctl.h =================================================================== RCS file: /home/cvs/src/sbin/pfctl/pfctl.h,v diff -u -p -r1.64 pfctl.h --- pfctl.h 14 Jul 2024 19:51:08 -0000 1.64 +++ pfctl.h 20 Nov 2024 11:03:06 -0000 @@ -82,6 +82,7 @@ int pfr_del_tables(struct pfr_table *, int pfr_get_tables(struct pfr_table *, struct pfr_table *, int *, int); int pfr_get_tstats(struct pfr_table *, struct pfr_tstats *, int *, int); int pfr_clr_tstats(struct pfr_table *, int, int *, int); +int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, int); int pfr_clr_addrs(struct pfr_table *, int *, int); int pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int); int pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int); Index: pfctl_radix.c =================================================================== RCS file: /home/cvs/src/sbin/pfctl/pfctl_radix.c,v diff -u -p -r1.39 pfctl_radix.c --- pfctl_radix.c 14 Jul 2024 19:51:08 -0000 1.39 +++ pfctl_radix.c 20 Nov 2024 11:02:55 -0000 @@ -314,6 +314,29 @@ pfr_get_astats(struct pfr_table *tbl, st } int +pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size, + int *nzero, int flags) +{ + struct pfioc_table io; + + if (size < 0 || (size && !tbl) || addr == NULL) { + errno = EINVAL; + return (-1); + } + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_table = *tbl; + io.pfrio_buffer = addr; + io.pfrio_esize = sizeof(*addr); + io.pfrio_size = size; + if (ioctl(dev, DIOCRCLRASTATS, &io) == -1) + return (-1); + if (nzero) + *nzero = io.pfrio_nzero; + return (0); +} + +int pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags) { struct pfioc_table io; Index: pfctl_table.c =================================================================== RCS file: /home/cvs/src/sbin/pfctl/pfctl_table.c,v diff -u -p -r1.90 pfctl_table.c --- pfctl_table.c 19 Aug 2024 13:01:47 -0000 1.90 +++ pfctl_table.c 20 Nov 2024 10:57:20 -0000 @@ -346,9 +346,22 @@ pfctl_table(int argc, char *argv[], char } if (nmatch < b.pfrb_size) rv = 2; + } else if (!strcmp(command, "zero") && (argc || file != NULL)) { + b.pfrb_type = PFRB_ADDRS; + if (load_addr(&b, argc, argv, file, 0, opts)) + goto _error; + if (opts & PF_OPT_VERBOSE) + flags |= PFR_FLAG_FEEDBACK; + RVTEST(pfr_clr_astats(&table, b.pfrb_caddr, b.pfrb_size, + &nzero, flags)); + xprintf(opts, "%d/%d addresses cleared", nzero, b.pfrb_size); + if (opts & PF_OPT_VERBOSE) + PFRB_FOREACH(a, &b) + if (opts & PF_OPT_VERBOSE2 || + a->pfra_fback != PFR_FB_NONE) + print_addrx(a, NULL, + opts & PF_OPT_USEDNS); } else if (!strcmp(command, "zero")) { - if (argc || file != NULL) - usage(); flags |= PFR_FLAG_ADDRSTOO; RVTEST(pfr_clr_tstats(&table, 1, &nzero, flags)); xprintf(opts, "%d table/stats cleared", nzero); -- wbr, Kirill