From owner-svn-src-projects@FreeBSD.ORG Tue Apr 10 19:11:10 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 6730B1065674; Tue, 10 Apr 2012 19:11:10 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 513228FC17; Tue, 10 Apr 2012 19:11:10 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q3AJBAO8036661; Tue, 10 Apr 2012 19:11:10 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q3AJBAfK036655; Tue, 10 Apr 2012 19:11:10 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201204101911.q3AJBAfK036655@svn.freebsd.org> From: Gleb Smirnoff Date: Tue, 10 Apr 2012 19:11:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r234108 - projects/pf/head/sys/contrib/pf/net X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 10 Apr 2012 19:11:10 -0000 Author: glebius Date: Tue Apr 10 19:11:09 2012 New Revision: 234108 URL: http://svn.freebsd.org/changeset/base/234108 Log: Get rid of copyin/copyout under locks in the pf table ioctls. This is done by allocation enough memory before entering the locked code. Ioctls fixed: DIOCRADDTABLES + DIOCRDELTABLES + DIOCRGETTABLES + DIOCRGETTSTATS + DIOCRCLRTSTATS + DIOCRSETTFLAGS DIOCRADDADDRS + DIOCRDELADDRS + DIOCRSETADDRS + DIOCRGETADDRS + DIOCRCLRASTATS DIOCRTSTADDRS + DIOCRINADEFINE + Lack of + means that the ioctl wasn't tested, due to absence of it in the pfctl. However, code is quite similar, so I think these couple is also okay. While here, clean up some more code: - Don't pretend that we can use M_WAITOK in ioctl path. We can't. We need to acquire lock quite prior to allocating memory, and to fix that quite a lot needs to be redesigned. - Remove spl(9) Modified: projects/pf/head/sys/contrib/pf/net/pf.c projects/pf/head/sys/contrib/pf/net/pf_if.c projects/pf/head/sys/contrib/pf/net/pf_ioctl.c projects/pf/head/sys/contrib/pf/net/pf_table.c projects/pf/head/sys/contrib/pf/net/pfvar.h Modified: projects/pf/head/sys/contrib/pf/net/pf.c ============================================================================== --- projects/pf/head/sys/contrib/pf/net/pf.c Tue Apr 10 17:37:24 2012 (r234107) +++ projects/pf/head/sys/contrib/pf/net/pf.c Tue Apr 10 19:11:09 2012 (r234108) @@ -1425,7 +1425,7 @@ pf_tbladdr_setup(struct pf_ruleset *rs, { if (aw->type != PF_ADDR_TABLE) return (0); - if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname, 1)) == NULL) + if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname)) == NULL) return (1); return (0); } Modified: projects/pf/head/sys/contrib/pf/net/pf_if.c ============================================================================== --- projects/pf/head/sys/contrib/pf/net/pf_if.c Tue Apr 10 17:37:24 2012 (r234107) +++ projects/pf/head/sys/contrib/pf/net/pf_if.c Tue Apr 10 19:11:09 2012 (r234108) @@ -429,7 +429,7 @@ pfi_dynaddr_setup(struct pf_addr_wrap *a goto _bad; } - if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname, 1)) == NULL) { + if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) { rv = 1; goto _bad; } Modified: projects/pf/head/sys/contrib/pf/net/pf_ioctl.c ============================================================================== --- projects/pf/head/sys/contrib/pf/net/pf_ioctl.c Tue Apr 10 17:37:24 2012 (r234107) +++ projects/pf/head/sys/contrib/pf/net/pf_ioctl.c Tue Apr 10 19:11:09 2012 (r234108) @@ -1304,7 +1304,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca if (rule->overload_tblname[0]) { if ((rule->overload_tbl = pfr_attach_table(ruleset, - rule->overload_tblname, 0)) == NULL) + rule->overload_tblname)) == NULL) error = EINVAL; else rule->overload_tbl->pfrkt_flags |= @@ -1573,7 +1573,7 @@ pfioctl(struct cdev *dev, u_long cmd, ca if (newrule->overload_tblname[0]) { if ((newrule->overload_tbl = pfr_attach_table( - ruleset, newrule->overload_tblname, 0)) == + ruleset, newrule->overload_tblname)) == NULL) error = EINVAL; else @@ -1847,7 +1847,7 @@ DIOCGETSTATES_full: sizeof(struct pfsync_state) * nr); if (error) { free(pstore, M_TEMP); - goto fail; + break; } ps->ps_len = sizeof(struct pfsync_state) * nr; free(pstore, M_TEMP); @@ -1943,7 +1943,7 @@ DIOCGETSTATES_full: if (pt->timeout < 0 || pt->timeout >= PFTM_MAX || pt->seconds < 0) { error = EINVAL; - goto fail; + break; } PF_LOCK(); old = V_pf_default_rule.timeout[pt->timeout]; @@ -1962,7 +1962,7 @@ DIOCGETSTATES_full: if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) { error = EINVAL; - goto fail; + break; } pt->seconds = V_pf_default_rule.timeout[pt->timeout]; break; @@ -1973,7 +1973,7 @@ DIOCGETSTATES_full: if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) { error = EINVAL; - goto fail; + break; } pl->limit = V_pf_pool_limits[pl->index].limit; break; @@ -1988,7 +1988,7 @@ DIOCGETSTATES_full: V_pf_pool_limits[pl->index].pp == NULL) { PF_UNLOCK(); error = EINVAL; - goto fail; + break; } uma_zone_set_max(V_pf_pool_limits[pl->index].pp, pl->limit); old_limit = V_pf_pool_limits[pl->index].limit; @@ -2544,86 +2544,140 @@ DIOCGETSTATES_full: case DIOCRADDTABLES: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_table *pfrts; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_table); + pfrts = malloc(totlen, M_TEMP, M_WAITOK); + error = copyin(io->pfrio_buffer, pfrts, totlen); + if (error) { + free(pfrts, M_TEMP); + break; + } PF_LOCK(); - error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size, + error = pfr_add_tables(pfrts, io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + free(pfrts, M_TEMP); break; } case DIOCRDELTABLES: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_table *pfrts; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_table); + pfrts = malloc(totlen, M_TEMP, M_WAITOK); + error = copyin(io->pfrio_buffer, pfrts, totlen); + if (error) { + free(pfrts, M_TEMP); + break; + } PF_LOCK(); - error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size, + error = pfr_del_tables(pfrts, io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + free(pfrts, M_TEMP); break; } case DIOCRGETTABLES: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_table *pfrts; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_table); + pfrts = malloc(totlen, M_TEMP, M_WAITOK); PF_LOCK(); - error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer, + error = pfr_get_tables(&io->pfrio_table, pfrts, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + if (error == 0) + error = copyout(pfrts, io->pfrio_buffer, totlen); + free(pfrts, M_TEMP); break; } case DIOCRGETTSTATS: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_tstats *pfrtstats; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_tstats)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_tstats); + pfrtstats = malloc(totlen, M_TEMP, M_WAITOK); PF_LOCK(); - error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer, + error = pfr_get_tstats(&io->pfrio_table, pfrtstats, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + if (error == 0) + error = copyout(pfrtstats, io->pfrio_buffer, totlen); + free(pfrtstats, M_TEMP); break; } case DIOCRCLRTSTATS: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_table *pfrts; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_table); + pfrts = malloc(totlen, M_TEMP, M_WAITOK); + error = copyin(io->pfrio_buffer, pfrts, totlen); + if (error) { + free(pfrts, M_TEMP); + break; + } PF_LOCK(); - error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size, + error = pfr_clr_tstats(pfrts, io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + free(pfrts, M_TEMP); break; } case DIOCRSETTFLAGS: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_table *pfrts; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_table)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_table); + pfrts = malloc(totlen, M_TEMP, M_WAITOK); + error = copyin(io->pfrio_buffer, pfrts, totlen); + if (error) { + free(pfrts, M_TEMP); + break; + } PF_LOCK(); - error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size, + error = pfr_set_tflags(pfrts, io->pfrio_size, io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + free(pfrts, M_TEMP); break; } @@ -2643,61 +2697,105 @@ DIOCGETSTATES_full: case DIOCRADDADDRS: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_addr *pfras; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_addr); + pfras = malloc(totlen, M_TEMP, M_WAITOK); + error = copyin(io->pfrio_buffer, pfras, totlen); + if (error) { + free(pfras, M_TEMP); + break; + } PF_LOCK(); - error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer, + error = pfr_add_addrs(&io->pfrio_table, pfras, io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK) + error = copyout(pfras, io->pfrio_buffer, totlen); + free(pfras, M_TEMP); break; } case DIOCRDELADDRS: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_addr *pfras; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_addr); + pfras = malloc(totlen, M_TEMP, M_WAITOK); + error = copyin(io->pfrio_buffer, pfras, totlen); + if (error) { + free(pfras, M_TEMP); + break; + } PF_LOCK(); - error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer, + error = pfr_del_addrs(&io->pfrio_table, pfras, io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK) + error = copyout(pfras, io->pfrio_buffer, totlen); + free(pfras, M_TEMP); break; } case DIOCRSETADDRS: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_addr *pfras; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; break; } + totlen = (io->pfrio_size + io->pfrio_size2) * + sizeof(struct pfr_addr); + pfras = malloc(totlen, M_TEMP, M_WAITOK); + error = copyin(io->pfrio_buffer, pfras, totlen); + if (error) { + free(pfras, M_TEMP); + break; + } PF_LOCK(); - error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer, + error = pfr_set_addrs(&io->pfrio_table, pfras, io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd, &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags | PFR_FLAG_USERIOCTL, 0); PF_UNLOCK(); + if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK) + error = copyout(pfras, io->pfrio_buffer, totlen); + free(pfras, M_TEMP); break; } case DIOCRGETADDRS: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_addr *pfras; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_addr); + pfras = malloc(totlen, M_TEMP, M_WAITOK); PF_LOCK(); - error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer, + error = pfr_get_addrs(&io->pfrio_table, pfras, &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + if (error == 0) + error = copyout(pfras, io->pfrio_buffer, totlen); + free(pfras, M_TEMP); break; } @@ -2717,46 +2815,80 @@ DIOCGETSTATES_full: case DIOCRCLRASTATS: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_addr *pfras; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_addr); + pfras = malloc(totlen, M_TEMP, M_WAITOK); + error = copyin(io->pfrio_buffer, pfras, totlen); + if (error) { + free(pfras, M_TEMP); + break; + } PF_LOCK(); - error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer, + error = pfr_clr_astats(&io->pfrio_table, pfras, io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + if (error == 0 && io->pfrio_flags & PFR_FLAG_FEEDBACK) + error = copyout(pfras, io->pfrio_buffer, totlen); + free(pfras, M_TEMP); break; } case DIOCRTSTADDRS: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_addr *pfras; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_addr); + pfras = malloc(totlen, M_TEMP, M_WAITOK); + error = copyin(io->pfrio_buffer, pfras, totlen); + if (error) { + free(pfras, M_TEMP); + break; + } PF_LOCK(); - error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer, + error = pfr_tst_addrs(&io->pfrio_table, pfras, io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + if (error == 0) + error = copyout(pfras, io->pfrio_buffer, totlen); + free(pfras, M_TEMP); break; } case DIOCRINADEFINE: { struct pfioc_table *io = (struct pfioc_table *)addr; + struct pfr_addr *pfras; + size_t totlen; if (io->pfrio_esize != sizeof(struct pfr_addr)) { error = ENODEV; break; } + totlen = io->pfrio_size * sizeof(struct pfr_addr); + pfras = malloc(totlen, M_TEMP, M_WAITOK); + error = copyin(io->pfrio_buffer, pfras, totlen); + if (error) { + free(pfras, M_TEMP); + break; + } PF_LOCK(); - error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer, + error = pfr_ina_define(&io->pfrio_table, pfras, io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr, io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL); PF_UNLOCK(); + free(pfras, M_TEMP); break; } @@ -2784,14 +2916,14 @@ DIOCGETSTATES_full: if (io->esize != sizeof(*ioe)) { error = ENODEV; - goto fail; + break; } totlen = sizeof(struct pfioc_trans_e) * io->size; ioes = malloc(totlen, M_TEMP, M_WAITOK); error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); - goto fail; + break; } PF_LOCK(); for (i = 0, ioe = ioes; i < io->size; i++, ioe++) { @@ -2850,14 +2982,14 @@ DIOCGETSTATES_full: if (io->esize != sizeof(*ioe)) { error = ENODEV; - goto fail; + break; } totlen = sizeof(struct pfioc_trans_e) * io->size; ioes = malloc(totlen, M_TEMP, M_WAITOK); error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); - goto fail; + break; } PF_LOCK(); for (i = 0, ioe = ioes; i < io->size; i++, ioe++) { @@ -2916,14 +3048,14 @@ DIOCGETSTATES_full: if (io->esize != sizeof(*ioe)) { error = ENODEV; - goto fail; + break; } totlen = sizeof(struct pfioc_trans_e) * io->size; ioes = malloc(totlen, M_TEMP, M_WAITOK); error = copyin(io->array, ioes, totlen); if (error) { free(ioes, M_TEMP); - goto fail; + break; } PF_LOCK(); /* First makes sure everything will succeed. */ @@ -3066,7 +3198,7 @@ DIOCGETSTATES_full: sizeof(struct pf_src_node) * nr); if (error) { free(pstore, M_TEMP); - goto fail; + break; } psn->psn_len = sizeof(struct pf_src_node) * nr; free(pstore, M_TEMP); Modified: projects/pf/head/sys/contrib/pf/net/pf_table.c ============================================================================== --- projects/pf/head/sys/contrib/pf/net/pf_table.c Tue Apr 10 17:37:24 2012 (r234107) +++ projects/pf/head/sys/contrib/pf/net/pf_table.c Tue Apr 10 19:11:09 2012 (r234108) @@ -55,41 +55,6 @@ __FBSDID("$FreeBSD$"); return (EINVAL); \ } while (0) -static inline int -_copyin(const void *uaddr, void *kaddr, size_t len) -{ - int r; - - PF_UNLOCK(); - r = copyin(uaddr, kaddr, len); - PF_LOCK(); - - return (r); -} - -static inline int -_copyout(const void *uaddr, void *kaddr, size_t len) -{ - int r; - - PF_UNLOCK(); - r = copyout(uaddr, kaddr, len); - PF_LOCK(); - - return (r); -} - -#define COPYIN(from, to, size, flags) \ - ((flags & PFR_FLAG_USERIOCTL) ? \ - _copyin((from), (to), (size)) : \ - (bcopy((from), (to), (size)), 0)) - -#define COPYOUT(from, to, size, flags) \ - ((flags & PFR_FLAG_USERIOCTL) ? \ - _copyout((from), (to), (size)) : \ - (bcopy((from), (to), (size)), 0)) - - #define FILLIN_SIN(sin, addr) \ do { \ (sin).sin_len = sizeof(sin); \ @@ -143,7 +108,6 @@ struct pfr_walktree { struct pfi_dynaddr *pfrw1_dyn; } pfrw_1; int pfrw_free; - int pfrw_flags; }; #define pfrw_addr pfrw_1.pfrw1_addr #define pfrw_astats pfrw_1.pfrw1_astats @@ -176,7 +140,7 @@ static void pfr_mark_addrs(struct pfr_ static struct pfr_kentry *pfr_lookup_addr(struct pfr_ktable *, struct pfr_addr *, int); -static struct pfr_kentry *pfr_create_kentry(struct pfr_addr *, int); +static struct pfr_kentry *pfr_create_kentry(struct pfr_addr *); static void pfr_destroy_kentries(struct pfr_kentryworkq *); static void pfr_destroy_kentry(struct pfr_kentry *); static void pfr_insert_kentries(struct pfr_ktable *, @@ -185,7 +149,7 @@ static void pfr_remove_kentries(struct struct pfr_kentryworkq *); static void pfr_clstats_kentries(struct pfr_kentryworkq *, long, int); -static void pfr_reset_feedback(struct pfr_addr *, int, int); +static void pfr_reset_feedback(struct pfr_addr *, int); static void pfr_prepare_network(union sockaddr_union *, int, int); static int pfr_route_kentry(struct pfr_ktable *, struct pfr_kentry *); @@ -203,7 +167,7 @@ static void pfr_clstats_ktables(struct int); static void pfr_clstats_ktable(struct pfr_ktable *, long, int); static struct pfr_ktable - *pfr_create_ktable(struct pfr_table *, long, int, int); + *pfr_create_ktable(struct pfr_table *, long, int); static void pfr_destroy_ktables(struct pfr_ktableworkq *, int); static void pfr_destroy_ktable(struct pfr_ktable *, int); static int pfr_ktable_compare(struct pfr_ktable *, @@ -241,9 +205,8 @@ pfr_clr_addrs(struct pfr_table *tbl, int { struct pfr_ktable *kt; struct pfr_kentryworkq workq; - int s; - ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY); + ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) return (EINVAL); kt = pfr_lookup_table(tbl); @@ -254,11 +217,7 @@ pfr_clr_addrs(struct pfr_table *tbl, int pfr_enqueue_addrs(kt, &workq, ndel, 0); if (!(flags & PFR_FLAG_DUMMY)) { - if (flags & PFR_FLAG_ATOMIC) - s = splnet(); pfr_remove_kentries(kt, &workq); - if (flags & PFR_FLAG_ATOMIC) - splx(s); if (kt->pfrkt_cnt) { printf("pfr_clr_addrs: corruption detected (%d).\n", kt->pfrkt_cnt); @@ -275,12 +234,11 @@ pfr_add_addrs(struct pfr_table *tbl, str struct pfr_ktable *kt, *tmpkt; struct pfr_kentryworkq workq; struct pfr_kentry *p, *q; - struct pfr_addr ad; - int i, rv, s, xadd = 0; + struct pfr_addr *ad; + int i, rv, xadd = 0; long tzero = time_second; - ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY | - PFR_FLAG_FEEDBACK); + ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK); if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) return (EINVAL); kt = pfr_lookup_table(tbl); @@ -288,53 +246,42 @@ pfr_add_addrs(struct pfr_table *tbl, str return (ESRCH); if (kt->pfrkt_flags & PFR_TFLAG_CONST) return (EPERM); - tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0, - !(flags & PFR_FLAG_USERIOCTL)); + tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0); if (tmpkt == NULL) return (ENOMEM); SLIST_INIT(&workq); - for (i = 0; i < size; i++) { - if (COPYIN(addr+i, &ad, sizeof(ad), flags)) - senderr(EFAULT); - if (pfr_validate_addr(&ad)) + for (i = 0, ad = addr; i < size; i++, ad++) { + if (pfr_validate_addr(ad)) senderr(EINVAL); - p = pfr_lookup_addr(kt, &ad, 1); - q = pfr_lookup_addr(tmpkt, &ad, 1); + p = pfr_lookup_addr(kt, ad, 1); + q = pfr_lookup_addr(tmpkt, ad, 1); if (flags & PFR_FLAG_FEEDBACK) { if (q != NULL) - ad.pfra_fback = PFR_FB_DUPLICATE; + ad->pfra_fback = PFR_FB_DUPLICATE; else if (p == NULL) - ad.pfra_fback = PFR_FB_ADDED; - else if (p->pfrke_not != ad.pfra_not) - ad.pfra_fback = PFR_FB_CONFLICT; + ad->pfra_fback = PFR_FB_ADDED; + else if (p->pfrke_not != ad->pfra_not) + ad->pfra_fback = PFR_FB_CONFLICT; else - ad.pfra_fback = PFR_FB_NONE; + ad->pfra_fback = PFR_FB_NONE; } if (p == NULL && q == NULL) { - p = pfr_create_kentry(&ad, - !(flags & PFR_FLAG_USERIOCTL)); + p = pfr_create_kentry(ad); if (p == NULL) senderr(ENOMEM); if (pfr_route_kentry(tmpkt, p)) { pfr_destroy_kentry(p); - ad.pfra_fback = PFR_FB_NONE; + ad->pfra_fback = PFR_FB_NONE; } else { SLIST_INSERT_HEAD(&workq, p, pfrke_workq); xadd++; } } - if (flags & PFR_FLAG_FEEDBACK) - if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) - senderr(EFAULT); } pfr_clean_node_mask(tmpkt, &workq); - if (!(flags & PFR_FLAG_DUMMY)) { - if (flags & PFR_FLAG_ATOMIC) - s = splnet(); + if (!(flags & PFR_FLAG_DUMMY)) pfr_insert_kentries(kt, &workq, tzero); - if (flags & PFR_FLAG_ATOMIC) - splx(s); - } else + else pfr_destroy_kentries(&workq); if (nadd != NULL) *nadd = xadd; @@ -344,7 +291,7 @@ _bad: pfr_clean_node_mask(tmpkt, &workq); pfr_destroy_kentries(&workq); if (flags & PFR_FLAG_FEEDBACK) - pfr_reset_feedback(addr, size, flags); + pfr_reset_feedback(addr, size); pfr_destroy_ktable(tmpkt, 0); return (rv); } @@ -356,11 +303,10 @@ pfr_del_addrs(struct pfr_table *tbl, str struct pfr_ktable *kt; struct pfr_kentryworkq workq; struct pfr_kentry *p; - struct pfr_addr ad; - int i, rv, s, xdel = 0, log = 1; + struct pfr_addr *ad; + int i, rv, xdel = 0, log = 1; - ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY | - PFR_FLAG_FEEDBACK); + ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK); if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) return (EINVAL); kt = pfr_lookup_table(tbl); @@ -386,56 +332,44 @@ pfr_del_addrs(struct pfr_table *tbl, str pfr_mark_addrs(kt); } else { /* iterate over addresses to delete */ - for (i = 0; i < size; i++) { - if (COPYIN(addr+i, &ad, sizeof(ad), flags)) - return (EFAULT); - if (pfr_validate_addr(&ad)) + for (i = 0, ad = addr; i < size; i++, ad++) { + if (pfr_validate_addr(ad)) return (EINVAL); - p = pfr_lookup_addr(kt, &ad, 1); + p = pfr_lookup_addr(kt, ad, 1); if (p != NULL) p->pfrke_mark = 0; } } SLIST_INIT(&workq); - for (i = 0; i < size; i++) { - if (COPYIN(addr+i, &ad, sizeof(ad), flags)) - senderr(EFAULT); - if (pfr_validate_addr(&ad)) + for (i = 0, ad = addr; i < size; i++, ad++) { + if (pfr_validate_addr(ad)) senderr(EINVAL); - p = pfr_lookup_addr(kt, &ad, 1); + 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_not != ad.pfra_not) - ad.pfra_fback = PFR_FB_CONFLICT; + ad->pfra_fback = PFR_FB_NONE; + else if (p->pfrke_not != ad->pfra_not) + ad->pfra_fback = PFR_FB_CONFLICT; else if (p->pfrke_mark) - ad.pfra_fback = PFR_FB_DUPLICATE; + ad->pfra_fback = PFR_FB_DUPLICATE; else - ad.pfra_fback = PFR_FB_DELETED; + ad->pfra_fback = PFR_FB_DELETED; } - if (p != NULL && p->pfrke_not == ad.pfra_not && + if (p != NULL && p->pfrke_not == ad->pfra_not && !p->pfrke_mark) { p->pfrke_mark = 1; 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)) { - if (flags & PFR_FLAG_ATOMIC) - s = splnet(); + if (!(flags & PFR_FLAG_DUMMY)) pfr_remove_kentries(kt, &workq); - if (flags & PFR_FLAG_ATOMIC) - splx(s); - } if (ndel != NULL) *ndel = xdel; return (0); _bad: if (flags & PFR_FLAG_FEEDBACK) - pfr_reset_feedback(addr, size, flags); + pfr_reset_feedback(addr, size); return (rv); } @@ -448,11 +382,10 @@ pfr_set_addrs(struct pfr_table *tbl, str struct pfr_kentryworkq addq, delq, changeq; struct pfr_kentry *p, *q; struct pfr_addr ad; - int i, rv, s, xadd = 0, xdel = 0, xchange = 0; + int i, rv, xadd = 0, xdel = 0, xchange = 0; long tzero = time_second; - ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY | - PFR_FLAG_FEEDBACK); + ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK); if (pfr_validate_table(tbl, ignore_pfrt_flags, flags & PFR_FLAG_USERIOCTL)) return (EINVAL); @@ -461,8 +394,7 @@ pfr_set_addrs(struct pfr_table *tbl, str return (ESRCH); if (kt->pfrkt_flags & PFR_TFLAG_CONST) return (EPERM); - tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0, - !(flags & PFR_FLAG_USERIOCTL)); + tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0); if (tmpkt == NULL) return (ENOMEM); pfr_mark_addrs(kt); @@ -470,8 +402,11 @@ pfr_set_addrs(struct pfr_table *tbl, str SLIST_INIT(&delq); SLIST_INIT(&changeq); for (i = 0; i < size; i++) { - if (COPYIN(addr+i, &ad, sizeof(ad), flags)) - senderr(EFAULT); + /* + * XXXGL: undertand pf_if usage of this function + * and make ad a moving pointer + */ + bcopy(addr + i, &ad, sizeof(ad)); if (pfr_validate_addr(&ad)) senderr(EINVAL); ad.pfra_fback = PFR_FB_NONE; @@ -493,8 +428,7 @@ pfr_set_addrs(struct pfr_table *tbl, str ad.pfra_fback = PFR_FB_DUPLICATE; goto _skip; } - p = pfr_create_kentry(&ad, - !(flags & PFR_FLAG_USERIOCTL)); + p = pfr_create_kentry(&ad); if (p == NULL) senderr(ENOMEM); if (pfr_route_kentry(tmpkt, p)) { @@ -508,8 +442,7 @@ pfr_set_addrs(struct pfr_table *tbl, str } _skip: if (flags & PFR_FLAG_FEEDBACK) - if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) - senderr(EFAULT); + bcopy(&ad, addr + i, sizeof(ad)); } pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY); if ((flags & PFR_FLAG_FEEDBACK) && *size2) { @@ -521,20 +454,15 @@ _skip: SLIST_FOREACH(p, &delq, pfrke_workq) { pfr_copyout_addr(&ad, p); ad.pfra_fback = PFR_FB_DELETED; - if (COPYOUT(&ad, addr+size+i, sizeof(ad), flags)) - senderr(EFAULT); + bcopy(&ad, addr + size + i, sizeof(ad)); i++; } } pfr_clean_node_mask(tmpkt, &addq); if (!(flags & PFR_FLAG_DUMMY)) { - if (flags & PFR_FLAG_ATOMIC) - s = splnet(); pfr_insert_kentries(kt, &addq, tzero); pfr_remove_kentries(kt, &delq); pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG); - if (flags & PFR_FLAG_ATOMIC) - splx(s); } else pfr_destroy_kentries(&addq); if (nadd != NULL) @@ -551,7 +479,7 @@ _bad: pfr_clean_node_mask(tmpkt, &addq); pfr_destroy_kentries(&addq); if (flags & PFR_FLAG_FEEDBACK) - pfr_reset_feedback(addr, size, flags); + pfr_reset_feedback(addr, size); pfr_destroy_ktable(tmpkt, 0); return (rv); } @@ -562,7 +490,7 @@ pfr_tst_addrs(struct pfr_table *tbl, str { struct pfr_ktable *kt; struct pfr_kentry *p; - struct pfr_addr ad; + struct pfr_addr *ad; int i, xmatch = 0; ACCEPT_FLAGS(flags, PFR_FLAG_REPLACE); @@ -572,22 +500,18 @@ pfr_tst_addrs(struct pfr_table *tbl, str if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) return (ESRCH); - for (i = 0; i < size; i++) { - if (COPYIN(addr+i, &ad, sizeof(ad), flags)) - return (EFAULT); - if (pfr_validate_addr(&ad)) + for (i = 0, ad = addr; i < size; i++, ad++) { + if (pfr_validate_addr(ad)) return (EINVAL); - if (ADDR_NETWORK(&ad)) + if (ADDR_NETWORK(ad)) return (EINVAL); - p = pfr_lookup_addr(kt, &ad, 0); + p = pfr_lookup_addr(kt, ad, 0); if (flags & PFR_FLAG_REPLACE) - pfr_copyout_addr(&ad, p); - ad.pfra_fback = (p == NULL) ? PFR_FB_NONE : + pfr_copyout_addr(ad, p); + ad->pfra_fback = (p == NULL) ? PFR_FB_NONE : (p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH); if (p != NULL && !p->pfrke_not) xmatch++; - if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) - return (EFAULT); } if (nmatch != NULL) *nmatch = xmatch; @@ -617,7 +541,6 @@ pfr_get_addrs(struct pfr_table *tbl, str w.pfrw_op = PFRW_GET_ADDRS; w.pfrw_addr = addr; w.pfrw_free = kt->pfrkt_cnt; - w.pfrw_flags = flags; rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w); if (!rv) rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, @@ -625,11 +548,9 @@ pfr_get_addrs(struct pfr_table *tbl, str if (rv) return (rv); - if (w.pfrw_free) { - printf("pfr_get_addrs: corruption detected (%d).\n", - w.pfrw_free); - return (ENOTTY); - } + KASSERT(w.pfrw_free == 0, ("%s: corruption detected (%d)", __func__, + w.pfrw_free)); + *size = kt->pfrkt_cnt; return (0); } @@ -641,11 +562,11 @@ pfr_get_astats(struct pfr_table *tbl, st struct pfr_ktable *kt; struct pfr_walktree w; struct pfr_kentryworkq workq; - int rv, s; + int rv; long tzero = time_second; /* XXX PFR_FLAG_CLSTATS disabled */ - ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC); + ACCEPT_FLAGS(flags, 0); if (pfr_validate_table(tbl, 0, 0)) return (EINVAL); kt = pfr_lookup_table(tbl); @@ -660,9 +581,6 @@ pfr_get_astats(struct pfr_table *tbl, st w.pfrw_op = PFRW_GET_ASTATS; w.pfrw_astats = addr; w.pfrw_free = kt->pfrkt_cnt; - w.pfrw_flags = flags; - if (flags & PFR_FLAG_ATOMIC) - s = splnet(); rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w); if (!rv) rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, @@ -671,8 +589,6 @@ pfr_get_astats(struct pfr_table *tbl, st pfr_enqueue_addrs(kt, &workq, NULL, 0); pfr_clstats_kentries(&workq, tzero, 0); } - if (flags & PFR_FLAG_ATOMIC) - splx(s); if (rv) return (rv); @@ -692,28 +608,23 @@ pfr_clr_astats(struct pfr_table *tbl, st struct pfr_ktable *kt; struct pfr_kentryworkq workq; struct pfr_kentry *p; - struct pfr_addr ad; - int i, rv, s, xzero = 0; + struct pfr_addr *ad; + int i, rv, xzero = 0; - ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY | - PFR_FLAG_FEEDBACK); + ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK); if (pfr_validate_table(tbl, 0, 0)) return (EINVAL); kt = pfr_lookup_table(tbl); if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) return (ESRCH); SLIST_INIT(&workq); - for (i = 0; i < size; i++) { - if (COPYIN(addr+i, &ad, sizeof(ad), flags)) - senderr(EFAULT); - if (pfr_validate_addr(&ad)) + for (i = 0, ad = addr; i < size; i++, ad++) { + if (pfr_validate_addr(ad)) senderr(EINVAL); - p = pfr_lookup_addr(kt, &ad, 1); + p = pfr_lookup_addr(kt, ad, 1); if (flags & PFR_FLAG_FEEDBACK) { - ad.pfra_fback = (p != NULL) ? + ad->pfra_fback = (p != NULL) ? PFR_FB_CLEARED : PFR_FB_NONE; - if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) - senderr(EFAULT); } if (p != NULL) { SLIST_INSERT_HEAD(&workq, p, pfrke_workq); @@ -721,19 +632,14 @@ pfr_clr_astats(struct pfr_table *tbl, st } } - if (!(flags & PFR_FLAG_DUMMY)) { - if (flags & PFR_FLAG_ATOMIC) - s = splnet(); + if (!(flags & PFR_FLAG_DUMMY)) pfr_clstats_kentries(&workq, 0, 0); - if (flags & PFR_FLAG_ATOMIC) - splx(s); - } *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***