Hello, this is the second patch in 3-patch series.
Patch changes DIOCRDELADDRS ioctl to DIOCRDELADDR, which accepts one IP address only per ioctl(2) call. Patch updates kernel and pfctl(8) only. Other components, which happen to use DIOCRDELADDRS will be updated by extra patch. thanks and regards sasha --------8<---------------8<---------------8<------------------8<-------- Index: sbin/pfctl/pfctl_radix.c =================================================================== RCS file: /cvs/src/sbin/pfctl/pfctl_radix.c,v retrieving revision 1.32 diff -u -p -r1.32 pfctl_radix.c --- sbin/pfctl/pfctl_radix.c 21 Jan 2015 21:50:33 -0000 1.32 +++ sbin/pfctl/pfctl_radix.c 27 Oct 2015 22:56:54 -0000 @@ -207,6 +207,7 @@ pfr_del_addrs(struct pfr_table *tbl, str int *ndel, int flags) { struct pfioc_table io; + int i, rv, del = 0; if (tbl == NULL || size < 0 || (size && addr == NULL)) { errno = EINVAL; @@ -215,14 +216,18 @@ pfr_del_addrs(struct pfr_table *tbl, str 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, DIOCRDELADDRS, &io)) - return (-1); - if (ndel != NULL) - *ndel = io.pfrio_ndel; - return (0); + io.pfrio_size = 1; + for (i = 0; (i < size) && (rv == 0); i++) { + io.pfrio_buffer = addr++; + rv = ioctl(dev, DIOCRDELADDR, &io); + del++; + } + + if ((rv == 0) && (ndel != NULL)) + *ndel = del; + + return (rv); } int Index: sys/net/pf_ioctl.c =================================================================== RCS file: /cvs/src/sys/net/pf_ioctl.c,v retrieving revision 1.291 diff -u -p -r1.291 pf_ioctl.c --- sys/net/pf_ioctl.c 13 Oct 2015 19:32:31 -0000 1.291 +++ sys/net/pf_ioctl.c 27 Oct 2015 22:57:20 -0000 @@ -835,7 +835,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a case DIOCRCLRTSTATS: case DIOCRCLRADDRS: case DIOCRADDADDRS: - case DIOCRDELADDRS: + case DIOCRDELADDR: case DIOCRSETADDRS: case DIOCRGETASTATS: case DIOCRCLRASTATS: @@ -888,7 +888,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a case DIOCRCLRTSTATS: case DIOCRCLRADDRS: case DIOCRADDADDRS: - case DIOCRDELADDRS: + case DIOCRDELADDR: case DIOCRSETADDRS: case DIOCRSETTFLAGS: if (((struct pfioc_table *)addr)->pfrio_flags & @@ -1829,16 +1829,15 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a break; } - case DIOCRDELADDRS: { + case DIOCRDELADDR: { struct pfioc_table *io = (struct pfioc_table *)addr; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; break; } - error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer, - io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags | - PFR_FLAG_USERIOCTL); + error = pfr_del_addr(&io->pfrio_table, io->pfrio_buffer, + io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); break; } Index: sys/net/pf_table.c =================================================================== RCS file: /cvs/src/sys/net/pf_table.c,v retrieving revision 1.115 diff -u -p -r1.115 pf_table.c --- sys/net/pf_table.c 7 Oct 2015 11:57:44 -0000 1.115 +++ sys/net/pf_table.c 27 Oct 2015 22:57:24 -0000 @@ -152,6 +152,8 @@ void pfr_destroy_kentries(struct pfr_ void pfr_destroy_kentry(struct pfr_kentry *); void pfr_insert_kentries(struct pfr_ktable *, struct pfr_kentryworkq *, time_t); +void pfr_remove_kentry(struct pfr_ktable *, + struct pfr_kentry *); void pfr_remove_kentries(struct pfr_ktable *, struct pfr_kentryworkq *); void pfr_clstats_kentries(struct pfr_kentryworkq *, time_t, @@ -343,14 +345,12 @@ _bad: } int -pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, - int *ndel, int flags) +pfr_del_addr(struct pfr_table *tbl, struct pfr_addr *addr, int size, int flags) { struct pfr_ktable *kt; - struct pfr_kentryworkq workq; struct pfr_kentry *p; struct pfr_addr ad; - int i, rv, xdel = 0, log = 1; + int rv; ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK); if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) @@ -360,70 +360,29 @@ pfr_del_addrs(struct pfr_table *tbl, str return (ESRCH); if (kt->pfrkt_flags & PFR_TFLAG_CONST) return (EPERM); - /* - * there are two algorithms to choose from here. - * with: - * n: number of addresses to delete - * N: number of addresses in the table - * - * one is O(N) and is better for large 'n' - * one is O(n*LOG(N)) and is better for small 'n' - * - * following code try to decide which one is best. - */ - for (i = kt->pfrkt_cnt; i > 0; i >>= 1) - log++; - if (size > kt->pfrkt_cnt/log) { - /* full table scan */ - pfr_mark_addrs(kt); - } else { - /* iterate over addresses to delete */ - for (i = 0; i < size; i++) { - YIELD(i, flags & PFR_FLAG_USERIOCTL); - if (COPYIN(addr+i, &ad, sizeof(ad), flags)) - return (EFAULT); - if (pfr_validate_addr(&ad)) - return (EINVAL); - p = pfr_lookup_addr(kt, &ad, 1); - if (p != NULL) - p->pfrke_flags &= ~PFRKE_FLAG_MARK; - } - } - SLIST_INIT(&workq); - for (i = 0; i < size; i++) { - YIELD(i, flags & PFR_FLAG_USERIOCTL); - if (COPYIN(addr+i, &ad, sizeof(ad), flags)) + + if (COPYIN(addr, &ad, sizeof(ad), flags)) + senderr(EFAULT); + if (pfr_validate_addr(&ad)) + senderr(EINVAL); + p = pfr_lookup_addr(kt, &ad, 1); + if (flags & PFR_FLAG_FEEDBACK) { + if (p == NULL) + ad.pfra_fback = PFR_FB_NONE; + else if ((p->pfrke_flags & PFRKE_FLAG_NOT) != + ad.pfra_not) + ad.pfra_fback = PFR_FB_CONFLICT; + else + ad.pfra_fback = PFR_FB_DELETED; + + if (COPYOUT(&ad, addr, sizeof(ad), flags)) senderr(EFAULT); - if (pfr_validate_addr(&ad)) - senderr(EINVAL); - p = pfr_lookup_addr(kt, &ad, 1); - if (flags & PFR_FLAG_FEEDBACK) { - if (p == NULL) - ad.pfra_fback = PFR_FB_NONE; - else if ((p->pfrke_flags & PFRKE_FLAG_NOT) != - ad.pfra_not) - ad.pfra_fback = PFR_FB_CONFLICT; - else if (p->pfrke_flags & PFRKE_FLAG_MARK) - ad.pfra_fback = PFR_FB_DUPLICATE; - else - ad.pfra_fback = PFR_FB_DELETED; - } - if (p != NULL && - (p->pfrke_flags & PFRKE_FLAG_NOT) == ad.pfra_not && - !(p->pfrke_flags & PFRKE_FLAG_MARK)) { - p->pfrke_flags |= PFRKE_FLAG_MARK; - SLIST_INSERT_HEAD(&workq, p, pfrke_workq); - xdel++; - } - if (flags & PFR_FLAG_FEEDBACK) - if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) - senderr(EFAULT); } - if (!(flags & PFR_FLAG_DUMMY)) { - pfr_remove_kentries(kt, &workq); + + if (!(flags & PFR_FLAG_DUMMY) && (p != NULL)) { + pfr_remove_kentry(kt, p); } - if (ndel != NULL) - *ndel = xdel; + return (0); _bad: if (flags & PFR_FLAG_FEEDBACK) @@ -947,6 +906,25 @@ pfr_insert_kentry(struct pfr_ktable *kt, pfr_ktable_winfo_update(kt, p); return (0); +} + +void +pfr_remove_kentry(struct pfr_ktable *kt, struct pfr_kentry *p) +{ + struct pfr_kentryworkq addrq; + + pfr_unroute_kentry(kt, p); + if (p->pfrke_type == PFRKE_COST) + kt->pfrkt_refcntcost--; + kt->pfrkt_cnt--; + + if (kt->pfrkt_refcntcost > 0) { + kt->pfrkt_gcdweight = 0; + kt->pfrkt_maxweight = 1; + pfr_enqueue_addrs(kt, &addrq, NULL, 0); + SLIST_FOREACH(p, &addrq, pfrke_workq) + pfr_ktable_winfo_update(kt, p); + } } void Index: sys/net/pfvar.h =================================================================== RCS file: /cvs/src/sys/net/pfvar.h,v retrieving revision 1.421 diff -u -p -r1.421 pfvar.h --- sys/net/pfvar.h 13 Oct 2015 19:32:32 -0000 1.421 +++ sys/net/pfvar.h 27 Oct 2015 22:57:25 -0000 @@ -1614,7 +1614,7 @@ struct pfioc_iface { #define DIOCRCLRTSTATS _IOWR('D', 65, struct pfioc_table) #define DIOCRCLRADDRS _IOWR('D', 66, struct pfioc_table) #define DIOCRADDADDRS _IOWR('D', 67, struct pfioc_table) -#define DIOCRDELADDRS _IOWR('D', 68, struct pfioc_table) +#define DIOCRDELADDR _IOWR('D', 68, struct pfioc_table) #define DIOCRSETADDRS _IOWR('D', 69, struct pfioc_table) #define DIOCRGETADDRS _IOWR('D', 70, struct pfioc_table) #define DIOCRGETASTATS _IOWR('D', 71, struct pfioc_table) @@ -1791,8 +1791,7 @@ int pfr_clr_addrs(struct pfr_table *, in int pfr_insert_kentry(struct pfr_ktable *, struct pfr_addr *, time_t); 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); +int pfr_del_addr(struct pfr_table *, struct pfr_addr *, int, int); int pfr_set_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int *, int *, int *, int, u_int32_t); int pfr_get_addrs(struct pfr_table *, struct pfr_addr *, int *, int); Index: sbin/pfctl/pfctl_radix.c =================================================================== RCS file: /cvs/src/sbin/pfctl/pfctl_radix.c,v retrieving revision 1.32 diff -u -p -r1.32 pfctl_radix.c --- sbin/pfctl/pfctl_radix.c 21 Jan 2015 21:50:33 -0000 1.32 +++ sbin/pfctl/pfctl_radix.c 27 Oct 2015 22:59:35 -0000 @@ -207,6 +207,7 @@ pfr_del_addrs(struct pfr_table *tbl, str int *ndel, int flags) { struct pfioc_table io; + int i, rv, del = 0; if (tbl == NULL || size < 0 || (size && addr == NULL)) { errno = EINVAL; @@ -215,14 +216,18 @@ pfr_del_addrs(struct pfr_table *tbl, str 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, DIOCRDELADDRS, &io)) - return (-1); - if (ndel != NULL) - *ndel = io.pfrio_ndel; - return (0); + io.pfrio_size = 1; + for (i = 0; (i < size) && (rv == 0); i++) { + io.pfrio_buffer = addr++; + rv = ioctl(dev, DIOCRDELADDR, &io); + del++; + } + + if ((rv == 0) && (ndel != NULL)) + *ndel = del; + + return (rv); } int