1*aca3beaaSApple OSS Distributions /*
2*aca3beaaSApple OSS Distributions * Copyright (c) 2007-2020 Apple Inc. All rights reserved.
3*aca3beaaSApple OSS Distributions *
4*aca3beaaSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*aca3beaaSApple OSS Distributions *
6*aca3beaaSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*aca3beaaSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*aca3beaaSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*aca3beaaSApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*aca3beaaSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*aca3beaaSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*aca3beaaSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*aca3beaaSApple OSS Distributions * terms of an Apple operating system software license agreement.
14*aca3beaaSApple OSS Distributions *
15*aca3beaaSApple OSS Distributions * Please obtain a copy of the License at
16*aca3beaaSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*aca3beaaSApple OSS Distributions *
18*aca3beaaSApple OSS Distributions * The Original Code and all software distributed under the License are
19*aca3beaaSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*aca3beaaSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*aca3beaaSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*aca3beaaSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*aca3beaaSApple OSS Distributions * Please see the License for the specific language governing rights and
24*aca3beaaSApple OSS Distributions * limitations under the License.
25*aca3beaaSApple OSS Distributions *
26*aca3beaaSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*aca3beaaSApple OSS Distributions */
28*aca3beaaSApple OSS Distributions
29*aca3beaaSApple OSS Distributions /* $apfw: pf_table.c,v 1.4 2008/08/27 00:01:32 jhw Exp $ */
30*aca3beaaSApple OSS Distributions /* $OpenBSD: pf_table.c,v 1.68 2006/05/02 10:08:45 dhartmei Exp $ */
31*aca3beaaSApple OSS Distributions
32*aca3beaaSApple OSS Distributions /*
33*aca3beaaSApple OSS Distributions * Copyright (c) 2002 Cedric Berger
34*aca3beaaSApple OSS Distributions * All rights reserved.
35*aca3beaaSApple OSS Distributions *
36*aca3beaaSApple OSS Distributions * Redistribution and use in source and binary forms, with or without
37*aca3beaaSApple OSS Distributions * modification, are permitted provided that the following conditions
38*aca3beaaSApple OSS Distributions * are met:
39*aca3beaaSApple OSS Distributions *
40*aca3beaaSApple OSS Distributions * - Redistributions of source code must retain the above copyright
41*aca3beaaSApple OSS Distributions * notice, this list of conditions and the following disclaimer.
42*aca3beaaSApple OSS Distributions * - Redistributions in binary form must reproduce the above
43*aca3beaaSApple OSS Distributions * copyright notice, this list of conditions and the following
44*aca3beaaSApple OSS Distributions * disclaimer in the documentation and/or other materials provided
45*aca3beaaSApple OSS Distributions * with the distribution.
46*aca3beaaSApple OSS Distributions *
47*aca3beaaSApple OSS Distributions * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
48*aca3beaaSApple OSS Distributions * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
49*aca3beaaSApple OSS Distributions * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
50*aca3beaaSApple OSS Distributions * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
51*aca3beaaSApple OSS Distributions * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
52*aca3beaaSApple OSS Distributions * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
53*aca3beaaSApple OSS Distributions * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54*aca3beaaSApple OSS Distributions * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
55*aca3beaaSApple OSS Distributions * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56*aca3beaaSApple OSS Distributions * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
57*aca3beaaSApple OSS Distributions * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58*aca3beaaSApple OSS Distributions * POSSIBILITY OF SUCH DAMAGE.
59*aca3beaaSApple OSS Distributions *
60*aca3beaaSApple OSS Distributions */
61*aca3beaaSApple OSS Distributions
62*aca3beaaSApple OSS Distributions #include <sys/param.h>
63*aca3beaaSApple OSS Distributions #include <sys/systm.h>
64*aca3beaaSApple OSS Distributions #include <sys/socket.h>
65*aca3beaaSApple OSS Distributions #include <sys/mbuf.h>
66*aca3beaaSApple OSS Distributions #include <sys/kernel.h>
67*aca3beaaSApple OSS Distributions #include <sys/malloc.h>
68*aca3beaaSApple OSS Distributions
69*aca3beaaSApple OSS Distributions #include <net/if.h>
70*aca3beaaSApple OSS Distributions #include <net/route.h>
71*aca3beaaSApple OSS Distributions #include <netinet/in.h>
72*aca3beaaSApple OSS Distributions #include <net/radix.h>
73*aca3beaaSApple OSS Distributions #include <net/pfvar.h>
74*aca3beaaSApple OSS Distributions
75*aca3beaaSApple OSS Distributions #define ACCEPT_FLAGS(flags, oklist) \
76*aca3beaaSApple OSS Distributions do { \
77*aca3beaaSApple OSS Distributions if ((flags & ~(oklist)) & \
78*aca3beaaSApple OSS Distributions PFR_FLAG_ALLMASK) \
79*aca3beaaSApple OSS Distributions return (EINVAL); \
80*aca3beaaSApple OSS Distributions } while (0)
81*aca3beaaSApple OSS Distributions
82*aca3beaaSApple OSS Distributions #define COPYIN(from, to, size, flags) \
83*aca3beaaSApple OSS Distributions ((flags & PFR_FLAG_USERIOCTL) ? \
84*aca3beaaSApple OSS Distributions copyin((from), (to), (size)) : \
85*aca3beaaSApple OSS Distributions (bcopy((void *)(uintptr_t)(from), (to), (size)), 0))
86*aca3beaaSApple OSS Distributions
87*aca3beaaSApple OSS Distributions #define COPYOUT(from, to, size, flags) \
88*aca3beaaSApple OSS Distributions ((flags & PFR_FLAG_USERIOCTL) ? \
89*aca3beaaSApple OSS Distributions copyout((from), (to), (size)) : \
90*aca3beaaSApple OSS Distributions (bcopy((from), (void *)(uintptr_t)(to), (size)), 0))
91*aca3beaaSApple OSS Distributions
92*aca3beaaSApple OSS Distributions #define FILLIN_SIN(sin, addr) \
93*aca3beaaSApple OSS Distributions do { \
94*aca3beaaSApple OSS Distributions (sin).sin_len = sizeof (sin); \
95*aca3beaaSApple OSS Distributions (sin).sin_family = AF_INET; \
96*aca3beaaSApple OSS Distributions (sin).sin_addr = (addr); \
97*aca3beaaSApple OSS Distributions } while (0)
98*aca3beaaSApple OSS Distributions
99*aca3beaaSApple OSS Distributions #define FILLIN_SIN6(sin6, addr) \
100*aca3beaaSApple OSS Distributions do { \
101*aca3beaaSApple OSS Distributions (sin6).sin6_len = sizeof (sin6); \
102*aca3beaaSApple OSS Distributions (sin6).sin6_family = AF_INET6; \
103*aca3beaaSApple OSS Distributions (sin6).sin6_addr = (addr); \
104*aca3beaaSApple OSS Distributions } while (0)
105*aca3beaaSApple OSS Distributions
106*aca3beaaSApple OSS Distributions #define SWAP(type, a1, a2) \
107*aca3beaaSApple OSS Distributions do { \
108*aca3beaaSApple OSS Distributions type tmp = a1; \
109*aca3beaaSApple OSS Distributions a1 = a2; \
110*aca3beaaSApple OSS Distributions a2 = tmp; \
111*aca3beaaSApple OSS Distributions } while (0)
112*aca3beaaSApple OSS Distributions
113*aca3beaaSApple OSS Distributions #define SUNION2PF(su, af) (((af) == AF_INET) ? \
114*aca3beaaSApple OSS Distributions (struct pf_addr *)&(su)->sin.sin_addr : \
115*aca3beaaSApple OSS Distributions (struct pf_addr *)&(su)->sin6.sin6_addr)
116*aca3beaaSApple OSS Distributions
117*aca3beaaSApple OSS Distributions #define AF_BITS(af) (((af) == AF_INET) ? 32 : 128)
118*aca3beaaSApple OSS Distributions #define ADDR_NETWORK(ad) ((ad)->pfra_net < AF_BITS((ad)->pfra_af))
119*aca3beaaSApple OSS Distributions #define KENTRY_NETWORK(ke) ((ke)->pfrke_net < AF_BITS((ke)->pfrke_af))
120*aca3beaaSApple OSS Distributions #define KENTRY_RNF_ROOT(ke) \
121*aca3beaaSApple OSS Distributions ((((struct radix_node *)(ke))->rn_flags & RNF_ROOT) != 0)
122*aca3beaaSApple OSS Distributions
123*aca3beaaSApple OSS Distributions #define NO_ADDRESSES (-1)
124*aca3beaaSApple OSS Distributions #define ENQUEUE_UNMARKED_ONLY (1)
125*aca3beaaSApple OSS Distributions #define INVERT_NEG_FLAG (1)
126*aca3beaaSApple OSS Distributions
127*aca3beaaSApple OSS Distributions struct pfr_walktree {
128*aca3beaaSApple OSS Distributions enum pfrw_op {
129*aca3beaaSApple OSS Distributions PFRW_MARK,
130*aca3beaaSApple OSS Distributions PFRW_SWEEP,
131*aca3beaaSApple OSS Distributions PFRW_ENQUEUE,
132*aca3beaaSApple OSS Distributions PFRW_GET_ADDRS,
133*aca3beaaSApple OSS Distributions PFRW_GET_ASTATS,
134*aca3beaaSApple OSS Distributions PFRW_POOL_GET,
135*aca3beaaSApple OSS Distributions PFRW_DYNADDR_UPDATE
136*aca3beaaSApple OSS Distributions } pfrw_op;
137*aca3beaaSApple OSS Distributions union {
138*aca3beaaSApple OSS Distributions user_addr_t pfrw1_addr;
139*aca3beaaSApple OSS Distributions user_addr_t pfrw1_astats;
140*aca3beaaSApple OSS Distributions struct pfr_kentryworkq *pfrw1_workq;
141*aca3beaaSApple OSS Distributions struct pfr_kentry *pfrw1_kentry;
142*aca3beaaSApple OSS Distributions struct pfi_dynaddr *pfrw1_dyn;
143*aca3beaaSApple OSS Distributions } pfrw_1;
144*aca3beaaSApple OSS Distributions int pfrw_free;
145*aca3beaaSApple OSS Distributions int pfrw_flags;
146*aca3beaaSApple OSS Distributions };
147*aca3beaaSApple OSS Distributions #define pfrw_addr pfrw_1.pfrw1_addr
148*aca3beaaSApple OSS Distributions #define pfrw_astats pfrw_1.pfrw1_astats
149*aca3beaaSApple OSS Distributions #define pfrw_workq pfrw_1.pfrw1_workq
150*aca3beaaSApple OSS Distributions #define pfrw_kentry pfrw_1.pfrw1_kentry
151*aca3beaaSApple OSS Distributions #define pfrw_dyn pfrw_1.pfrw1_dyn
152*aca3beaaSApple OSS Distributions #define pfrw_cnt pfrw_free
153*aca3beaaSApple OSS Distributions
154*aca3beaaSApple OSS Distributions #define senderr(e) do { rv = (e); goto _bad; } while (0)
155*aca3beaaSApple OSS Distributions
156*aca3beaaSApple OSS Distributions struct pool pfr_ktable_pl;
157*aca3beaaSApple OSS Distributions struct pool pfr_kentry_pl;
158*aca3beaaSApple OSS Distributions
159*aca3beaaSApple OSS Distributions static struct pool pfr_kentry_pl2;
160*aca3beaaSApple OSS Distributions static struct sockaddr_in pfr_sin;
161*aca3beaaSApple OSS Distributions static struct sockaddr_in6 pfr_sin6;
162*aca3beaaSApple OSS Distributions static union sockaddr_union pfr_mask;
163*aca3beaaSApple OSS Distributions static struct pf_addr pfr_ffaddr;
164*aca3beaaSApple OSS Distributions
165*aca3beaaSApple OSS Distributions static void pfr_copyout_addr(struct pfr_addr *, struct pfr_kentry *ke);
166*aca3beaaSApple OSS Distributions static int pfr_validate_addr(struct pfr_addr *);
167*aca3beaaSApple OSS Distributions static void pfr_enqueue_addrs(struct pfr_ktable *, struct pfr_kentryworkq *,
168*aca3beaaSApple OSS Distributions int *, int);
169*aca3beaaSApple OSS Distributions static void pfr_mark_addrs(struct pfr_ktable *);
170*aca3beaaSApple OSS Distributions static struct pfr_kentry *pfr_lookup_addr(struct pfr_ktable *,
171*aca3beaaSApple OSS Distributions struct pfr_addr *, int);
172*aca3beaaSApple OSS Distributions static struct pfr_kentry *pfr_create_kentry(struct pfr_addr *, boolean_t);
173*aca3beaaSApple OSS Distributions static void pfr_destroy_kentries(struct pfr_kentryworkq *);
174*aca3beaaSApple OSS Distributions static void pfr_destroy_kentry(struct pfr_kentry *);
175*aca3beaaSApple OSS Distributions static void pfr_insert_kentries(struct pfr_ktable *,
176*aca3beaaSApple OSS Distributions struct pfr_kentryworkq *, u_int64_t);
177*aca3beaaSApple OSS Distributions static void pfr_remove_kentries(struct pfr_ktable *, struct pfr_kentryworkq *);
178*aca3beaaSApple OSS Distributions static void pfr_clstats_kentries(struct pfr_kentryworkq *, u_int64_t, int);
179*aca3beaaSApple OSS Distributions static void pfr_reset_feedback(user_addr_t, int, int);
180*aca3beaaSApple OSS Distributions static void pfr_prepare_network(union sockaddr_union *, int, int);
181*aca3beaaSApple OSS Distributions static int pfr_route_kentry(struct pfr_ktable *, struct pfr_kentry *);
182*aca3beaaSApple OSS Distributions static int pfr_unroute_kentry(struct pfr_ktable *, struct pfr_kentry *);
183*aca3beaaSApple OSS Distributions static int pfr_walktree(struct radix_node *, void *);
184*aca3beaaSApple OSS Distributions static int pfr_validate_table(struct pfr_table *, int, int);
185*aca3beaaSApple OSS Distributions static int pfr_fix_anchor(char *);
186*aca3beaaSApple OSS Distributions static void pfr_commit_ktable(struct pfr_ktable *, u_int64_t);
187*aca3beaaSApple OSS Distributions static void pfr_insert_ktables(struct pfr_ktableworkq *);
188*aca3beaaSApple OSS Distributions static void pfr_insert_ktable(struct pfr_ktable *);
189*aca3beaaSApple OSS Distributions static void pfr_setflags_ktables(struct pfr_ktableworkq *);
190*aca3beaaSApple OSS Distributions static void pfr_setflags_ktable(struct pfr_ktable *, int);
191*aca3beaaSApple OSS Distributions static void pfr_clstats_ktables(struct pfr_ktableworkq *, u_int64_t, int);
192*aca3beaaSApple OSS Distributions static void pfr_clstats_ktable(struct pfr_ktable *, u_int64_t, int);
193*aca3beaaSApple OSS Distributions static struct pfr_ktable *pfr_create_ktable(struct pfr_table *, u_int64_t, int);
194*aca3beaaSApple OSS Distributions static void pfr_destroy_ktables(struct pfr_ktableworkq *, int);
195*aca3beaaSApple OSS Distributions static void pfr_destroy_ktable(struct pfr_ktable *, int);
196*aca3beaaSApple OSS Distributions static int pfr_ktable_compare(struct pfr_ktable *, struct pfr_ktable *);
197*aca3beaaSApple OSS Distributions static struct pfr_ktable *pfr_lookup_table(struct pfr_table *);
198*aca3beaaSApple OSS Distributions static void pfr_clean_node_mask(struct pfr_ktable *, struct pfr_kentryworkq *);
199*aca3beaaSApple OSS Distributions static int pfr_table_count(struct pfr_table *, int);
200*aca3beaaSApple OSS Distributions static int pfr_skip_table(struct pfr_table *, struct pfr_ktable *, int);
201*aca3beaaSApple OSS Distributions static struct pfr_kentry *pfr_kentry_byidx(struct pfr_ktable *, int, int);
202*aca3beaaSApple OSS Distributions
203*aca3beaaSApple OSS Distributions RB_PROTOTYPE_SC(static, pfr_ktablehead, pfr_ktable, pfrkt_tree,
204*aca3beaaSApple OSS Distributions pfr_ktable_compare);
205*aca3beaaSApple OSS Distributions RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
206*aca3beaaSApple OSS Distributions
207*aca3beaaSApple OSS Distributions static struct pfr_ktablehead pfr_ktables;
208*aca3beaaSApple OSS Distributions static struct pfr_table pfr_nulltable;
209*aca3beaaSApple OSS Distributions static int pfr_ktable_cnt;
210*aca3beaaSApple OSS Distributions
211*aca3beaaSApple OSS Distributions void
pfr_initialize(void)212*aca3beaaSApple OSS Distributions pfr_initialize(void)
213*aca3beaaSApple OSS Distributions {
214*aca3beaaSApple OSS Distributions pool_init(&pfr_ktable_pl, sizeof(struct pfr_ktable), 0, 0, 0,
215*aca3beaaSApple OSS Distributions "pfrktable", NULL);
216*aca3beaaSApple OSS Distributions pool_init(&pfr_kentry_pl, sizeof(struct pfr_kentry), 0, 0, 0,
217*aca3beaaSApple OSS Distributions "pfrkentry", NULL);
218*aca3beaaSApple OSS Distributions pool_init(&pfr_kentry_pl2, sizeof(struct pfr_kentry), 0, 0, 0,
219*aca3beaaSApple OSS Distributions "pfrkentry2", NULL);
220*aca3beaaSApple OSS Distributions
221*aca3beaaSApple OSS Distributions pfr_sin.sin_len = sizeof(pfr_sin);
222*aca3beaaSApple OSS Distributions pfr_sin.sin_family = AF_INET;
223*aca3beaaSApple OSS Distributions pfr_sin6.sin6_len = sizeof(pfr_sin6);
224*aca3beaaSApple OSS Distributions pfr_sin6.sin6_family = AF_INET6;
225*aca3beaaSApple OSS Distributions
226*aca3beaaSApple OSS Distributions memset(&pfr_ffaddr, 0xff, sizeof(pfr_ffaddr));
227*aca3beaaSApple OSS Distributions }
228*aca3beaaSApple OSS Distributions
229*aca3beaaSApple OSS Distributions #if 0
230*aca3beaaSApple OSS Distributions void
231*aca3beaaSApple OSS Distributions pfr_destroy(void)
232*aca3beaaSApple OSS Distributions {
233*aca3beaaSApple OSS Distributions pool_destroy(&pfr_ktable_pl);
234*aca3beaaSApple OSS Distributions pool_destroy(&pfr_kentry_pl);
235*aca3beaaSApple OSS Distributions pool_destroy(&pfr_kentry_pl2);
236*aca3beaaSApple OSS Distributions }
237*aca3beaaSApple OSS Distributions #endif
238*aca3beaaSApple OSS Distributions
239*aca3beaaSApple OSS Distributions int
pfr_clr_addrs(struct pfr_table * tbl,int * ndel,int flags)240*aca3beaaSApple OSS Distributions pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
241*aca3beaaSApple OSS Distributions {
242*aca3beaaSApple OSS Distributions struct pfr_ktable *kt;
243*aca3beaaSApple OSS Distributions struct pfr_kentryworkq workq;
244*aca3beaaSApple OSS Distributions
245*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
246*aca3beaaSApple OSS Distributions if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) {
247*aca3beaaSApple OSS Distributions return EINVAL;
248*aca3beaaSApple OSS Distributions }
249*aca3beaaSApple OSS Distributions kt = pfr_lookup_table(tbl);
250*aca3beaaSApple OSS Distributions if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
251*aca3beaaSApple OSS Distributions return ESRCH;
252*aca3beaaSApple OSS Distributions }
253*aca3beaaSApple OSS Distributions if (kt->pfrkt_flags & PFR_TFLAG_CONST) {
254*aca3beaaSApple OSS Distributions return EPERM;
255*aca3beaaSApple OSS Distributions }
256*aca3beaaSApple OSS Distributions pfr_enqueue_addrs(kt, &workq, ndel, 0);
257*aca3beaaSApple OSS Distributions
258*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
259*aca3beaaSApple OSS Distributions pfr_remove_kentries(kt, &workq);
260*aca3beaaSApple OSS Distributions if (kt->pfrkt_cnt) {
261*aca3beaaSApple OSS Distributions printf("pfr_clr_addrs: corruption detected (%d).\n",
262*aca3beaaSApple OSS Distributions kt->pfrkt_cnt);
263*aca3beaaSApple OSS Distributions kt->pfrkt_cnt = 0;
264*aca3beaaSApple OSS Distributions }
265*aca3beaaSApple OSS Distributions }
266*aca3beaaSApple OSS Distributions return 0;
267*aca3beaaSApple OSS Distributions }
268*aca3beaaSApple OSS Distributions
269*aca3beaaSApple OSS Distributions int
pfr_add_addrs(struct pfr_table * tbl,user_addr_t _addr,int size,int * nadd,int flags)270*aca3beaaSApple OSS Distributions pfr_add_addrs(struct pfr_table *tbl, user_addr_t _addr, int size,
271*aca3beaaSApple OSS Distributions int *nadd, int flags)
272*aca3beaaSApple OSS Distributions {
273*aca3beaaSApple OSS Distributions struct pfr_ktable *kt, *tmpkt;
274*aca3beaaSApple OSS Distributions struct pfr_kentryworkq workq;
275*aca3beaaSApple OSS Distributions struct pfr_kentry *p, *q;
276*aca3beaaSApple OSS Distributions struct pfr_addr ad;
277*aca3beaaSApple OSS Distributions int i, rv, xadd = 0;
278*aca3beaaSApple OSS Distributions user_addr_t addr = _addr;
279*aca3beaaSApple OSS Distributions u_int64_t tzero = pf_calendar_time_second();
280*aca3beaaSApple OSS Distributions
281*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
282*aca3beaaSApple OSS Distributions PFR_FLAG_FEEDBACK);
283*aca3beaaSApple OSS Distributions if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) {
284*aca3beaaSApple OSS Distributions return EINVAL;
285*aca3beaaSApple OSS Distributions }
286*aca3beaaSApple OSS Distributions kt = pfr_lookup_table(tbl);
287*aca3beaaSApple OSS Distributions if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
288*aca3beaaSApple OSS Distributions return ESRCH;
289*aca3beaaSApple OSS Distributions }
290*aca3beaaSApple OSS Distributions if (kt->pfrkt_flags & PFR_TFLAG_CONST) {
291*aca3beaaSApple OSS Distributions return EPERM;
292*aca3beaaSApple OSS Distributions }
293*aca3beaaSApple OSS Distributions tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
294*aca3beaaSApple OSS Distributions if (tmpkt == NULL) {
295*aca3beaaSApple OSS Distributions return ENOMEM;
296*aca3beaaSApple OSS Distributions }
297*aca3beaaSApple OSS Distributions SLIST_INIT(&workq);
298*aca3beaaSApple OSS Distributions for (i = 0; i < size; i++, addr += sizeof(ad)) {
299*aca3beaaSApple OSS Distributions if (COPYIN(addr, &ad, sizeof(ad), flags)) {
300*aca3beaaSApple OSS Distributions senderr(EFAULT);
301*aca3beaaSApple OSS Distributions }
302*aca3beaaSApple OSS Distributions if (pfr_validate_addr(&ad)) {
303*aca3beaaSApple OSS Distributions senderr(EINVAL);
304*aca3beaaSApple OSS Distributions }
305*aca3beaaSApple OSS Distributions p = pfr_lookup_addr(kt, &ad, 1);
306*aca3beaaSApple OSS Distributions q = pfr_lookup_addr(tmpkt, &ad, 1);
307*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_FEEDBACK) {
308*aca3beaaSApple OSS Distributions if (q != NULL) {
309*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_DUPLICATE;
310*aca3beaaSApple OSS Distributions } else if (p == NULL) {
311*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_ADDED;
312*aca3beaaSApple OSS Distributions } else if (p->pfrke_not != ad.pfra_not) {
313*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_CONFLICT;
314*aca3beaaSApple OSS Distributions } else {
315*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_NONE;
316*aca3beaaSApple OSS Distributions }
317*aca3beaaSApple OSS Distributions }
318*aca3beaaSApple OSS Distributions if (p == NULL && q == NULL) {
319*aca3beaaSApple OSS Distributions p = pfr_create_kentry(&ad,
320*aca3beaaSApple OSS Distributions !(flags & PFR_FLAG_USERIOCTL));
321*aca3beaaSApple OSS Distributions if (p == NULL) {
322*aca3beaaSApple OSS Distributions senderr(ENOMEM);
323*aca3beaaSApple OSS Distributions }
324*aca3beaaSApple OSS Distributions if (pfr_route_kentry(tmpkt, p)) {
325*aca3beaaSApple OSS Distributions pfr_destroy_kentry(p);
326*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_NONE;
327*aca3beaaSApple OSS Distributions } else {
328*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
329*aca3beaaSApple OSS Distributions xadd++;
330*aca3beaaSApple OSS Distributions }
331*aca3beaaSApple OSS Distributions }
332*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_FEEDBACK) {
333*aca3beaaSApple OSS Distributions if (COPYOUT(&ad, addr, sizeof(ad), flags)) {
334*aca3beaaSApple OSS Distributions senderr(EFAULT);
335*aca3beaaSApple OSS Distributions }
336*aca3beaaSApple OSS Distributions }
337*aca3beaaSApple OSS Distributions }
338*aca3beaaSApple OSS Distributions pfr_clean_node_mask(tmpkt, &workq);
339*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
340*aca3beaaSApple OSS Distributions pfr_insert_kentries(kt, &workq, tzero);
341*aca3beaaSApple OSS Distributions } else {
342*aca3beaaSApple OSS Distributions pfr_destroy_kentries(&workq);
343*aca3beaaSApple OSS Distributions }
344*aca3beaaSApple OSS Distributions if (nadd != NULL) {
345*aca3beaaSApple OSS Distributions *nadd = xadd;
346*aca3beaaSApple OSS Distributions }
347*aca3beaaSApple OSS Distributions pfr_destroy_ktable(tmpkt, 0);
348*aca3beaaSApple OSS Distributions return 0;
349*aca3beaaSApple OSS Distributions _bad:
350*aca3beaaSApple OSS Distributions pfr_clean_node_mask(tmpkt, &workq);
351*aca3beaaSApple OSS Distributions pfr_destroy_kentries(&workq);
352*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_FEEDBACK) {
353*aca3beaaSApple OSS Distributions pfr_reset_feedback(_addr, size, flags);
354*aca3beaaSApple OSS Distributions }
355*aca3beaaSApple OSS Distributions pfr_destroy_ktable(tmpkt, 0);
356*aca3beaaSApple OSS Distributions return rv;
357*aca3beaaSApple OSS Distributions }
358*aca3beaaSApple OSS Distributions
359*aca3beaaSApple OSS Distributions int
pfr_del_addrs(struct pfr_table * tbl,user_addr_t _addr,int size,int * ndel,int flags)360*aca3beaaSApple OSS Distributions pfr_del_addrs(struct pfr_table *tbl, user_addr_t _addr, int size,
361*aca3beaaSApple OSS Distributions int *ndel, int flags)
362*aca3beaaSApple OSS Distributions {
363*aca3beaaSApple OSS Distributions struct pfr_ktable *kt;
364*aca3beaaSApple OSS Distributions struct pfr_kentryworkq workq;
365*aca3beaaSApple OSS Distributions struct pfr_kentry *p;
366*aca3beaaSApple OSS Distributions struct pfr_addr ad;
367*aca3beaaSApple OSS Distributions user_addr_t addr = _addr;
368*aca3beaaSApple OSS Distributions int i, rv, xdel = 0, log = 1;
369*aca3beaaSApple OSS Distributions
370*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
371*aca3beaaSApple OSS Distributions PFR_FLAG_FEEDBACK);
372*aca3beaaSApple OSS Distributions if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) {
373*aca3beaaSApple OSS Distributions return EINVAL;
374*aca3beaaSApple OSS Distributions }
375*aca3beaaSApple OSS Distributions kt = pfr_lookup_table(tbl);
376*aca3beaaSApple OSS Distributions if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
377*aca3beaaSApple OSS Distributions return ESRCH;
378*aca3beaaSApple OSS Distributions }
379*aca3beaaSApple OSS Distributions if (kt->pfrkt_flags & PFR_TFLAG_CONST) {
380*aca3beaaSApple OSS Distributions return EPERM;
381*aca3beaaSApple OSS Distributions }
382*aca3beaaSApple OSS Distributions /*
383*aca3beaaSApple OSS Distributions * there are two algorithms to choose from here.
384*aca3beaaSApple OSS Distributions * with:
385*aca3beaaSApple OSS Distributions * n: number of addresses to delete
386*aca3beaaSApple OSS Distributions * N: number of addresses in the table
387*aca3beaaSApple OSS Distributions *
388*aca3beaaSApple OSS Distributions * one is O(N) and is better for large 'n'
389*aca3beaaSApple OSS Distributions * one is O(n*LOG(N)) and is better for small 'n'
390*aca3beaaSApple OSS Distributions *
391*aca3beaaSApple OSS Distributions * following code try to decide which one is best.
392*aca3beaaSApple OSS Distributions */
393*aca3beaaSApple OSS Distributions for (i = kt->pfrkt_cnt; i > 0; i >>= 1) {
394*aca3beaaSApple OSS Distributions log++;
395*aca3beaaSApple OSS Distributions }
396*aca3beaaSApple OSS Distributions if (size > kt->pfrkt_cnt / log) {
397*aca3beaaSApple OSS Distributions /* full table scan */
398*aca3beaaSApple OSS Distributions pfr_mark_addrs(kt);
399*aca3beaaSApple OSS Distributions } else {
400*aca3beaaSApple OSS Distributions /* iterate over addresses to delete */
401*aca3beaaSApple OSS Distributions for (i = 0; i < size; i++, addr += sizeof(ad)) {
402*aca3beaaSApple OSS Distributions if (COPYIN(addr, &ad, sizeof(ad), flags)) {
403*aca3beaaSApple OSS Distributions return EFAULT;
404*aca3beaaSApple OSS Distributions }
405*aca3beaaSApple OSS Distributions if (pfr_validate_addr(&ad)) {
406*aca3beaaSApple OSS Distributions return EINVAL;
407*aca3beaaSApple OSS Distributions }
408*aca3beaaSApple OSS Distributions p = pfr_lookup_addr(kt, &ad, 1);
409*aca3beaaSApple OSS Distributions if (p != NULL) {
410*aca3beaaSApple OSS Distributions p->pfrke_mark = 0;
411*aca3beaaSApple OSS Distributions }
412*aca3beaaSApple OSS Distributions }
413*aca3beaaSApple OSS Distributions }
414*aca3beaaSApple OSS Distributions SLIST_INIT(&workq);
415*aca3beaaSApple OSS Distributions for (addr = _addr, i = 0; i < size; i++, addr += sizeof(ad)) {
416*aca3beaaSApple OSS Distributions if (COPYIN(addr, &ad, sizeof(ad), flags)) {
417*aca3beaaSApple OSS Distributions senderr(EFAULT);
418*aca3beaaSApple OSS Distributions }
419*aca3beaaSApple OSS Distributions if (pfr_validate_addr(&ad)) {
420*aca3beaaSApple OSS Distributions senderr(EINVAL);
421*aca3beaaSApple OSS Distributions }
422*aca3beaaSApple OSS Distributions p = pfr_lookup_addr(kt, &ad, 1);
423*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_FEEDBACK) {
424*aca3beaaSApple OSS Distributions if (p == NULL) {
425*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_NONE;
426*aca3beaaSApple OSS Distributions } else if (p->pfrke_not != ad.pfra_not) {
427*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_CONFLICT;
428*aca3beaaSApple OSS Distributions } else if (p->pfrke_mark) {
429*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_DUPLICATE;
430*aca3beaaSApple OSS Distributions } else {
431*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_DELETED;
432*aca3beaaSApple OSS Distributions }
433*aca3beaaSApple OSS Distributions }
434*aca3beaaSApple OSS Distributions if (p != NULL && p->pfrke_not == ad.pfra_not &&
435*aca3beaaSApple OSS Distributions !p->pfrke_mark) {
436*aca3beaaSApple OSS Distributions p->pfrke_mark = 1;
437*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
438*aca3beaaSApple OSS Distributions xdel++;
439*aca3beaaSApple OSS Distributions }
440*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_FEEDBACK) {
441*aca3beaaSApple OSS Distributions if (COPYOUT(&ad, addr, sizeof(ad), flags)) {
442*aca3beaaSApple OSS Distributions senderr(EFAULT);
443*aca3beaaSApple OSS Distributions }
444*aca3beaaSApple OSS Distributions }
445*aca3beaaSApple OSS Distributions }
446*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
447*aca3beaaSApple OSS Distributions pfr_remove_kentries(kt, &workq);
448*aca3beaaSApple OSS Distributions }
449*aca3beaaSApple OSS Distributions if (ndel != NULL) {
450*aca3beaaSApple OSS Distributions *ndel = xdel;
451*aca3beaaSApple OSS Distributions }
452*aca3beaaSApple OSS Distributions return 0;
453*aca3beaaSApple OSS Distributions _bad:
454*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_FEEDBACK) {
455*aca3beaaSApple OSS Distributions pfr_reset_feedback(_addr, size, flags);
456*aca3beaaSApple OSS Distributions }
457*aca3beaaSApple OSS Distributions return rv;
458*aca3beaaSApple OSS Distributions }
459*aca3beaaSApple OSS Distributions
460*aca3beaaSApple OSS Distributions int
pfr_set_addrs(struct pfr_table * tbl,user_addr_t _addr,int size,int * size2,int * nadd,int * ndel,int * nchange,int flags,u_int32_t ignore_pfrt_flags)461*aca3beaaSApple OSS Distributions pfr_set_addrs(struct pfr_table *tbl, user_addr_t _addr, int size,
462*aca3beaaSApple OSS Distributions int *size2, int *nadd, int *ndel, int *nchange, int flags,
463*aca3beaaSApple OSS Distributions u_int32_t ignore_pfrt_flags)
464*aca3beaaSApple OSS Distributions {
465*aca3beaaSApple OSS Distributions struct pfr_ktable *kt, *tmpkt;
466*aca3beaaSApple OSS Distributions struct pfr_kentryworkq addq, delq, changeq;
467*aca3beaaSApple OSS Distributions struct pfr_kentry *p, *q;
468*aca3beaaSApple OSS Distributions struct pfr_addr ad;
469*aca3beaaSApple OSS Distributions user_addr_t addr = _addr;
470*aca3beaaSApple OSS Distributions int i, rv, xadd = 0, xdel = 0, xchange = 0;
471*aca3beaaSApple OSS Distributions u_int64_t tzero = pf_calendar_time_second();
472*aca3beaaSApple OSS Distributions
473*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
474*aca3beaaSApple OSS Distributions PFR_FLAG_FEEDBACK);
475*aca3beaaSApple OSS Distributions if (pfr_validate_table(tbl, ignore_pfrt_flags, flags &
476*aca3beaaSApple OSS Distributions PFR_FLAG_USERIOCTL)) {
477*aca3beaaSApple OSS Distributions return EINVAL;
478*aca3beaaSApple OSS Distributions }
479*aca3beaaSApple OSS Distributions kt = pfr_lookup_table(tbl);
480*aca3beaaSApple OSS Distributions if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
481*aca3beaaSApple OSS Distributions return ESRCH;
482*aca3beaaSApple OSS Distributions }
483*aca3beaaSApple OSS Distributions if (kt->pfrkt_flags & PFR_TFLAG_CONST) {
484*aca3beaaSApple OSS Distributions return EPERM;
485*aca3beaaSApple OSS Distributions }
486*aca3beaaSApple OSS Distributions tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
487*aca3beaaSApple OSS Distributions if (tmpkt == NULL) {
488*aca3beaaSApple OSS Distributions return ENOMEM;
489*aca3beaaSApple OSS Distributions }
490*aca3beaaSApple OSS Distributions pfr_mark_addrs(kt);
491*aca3beaaSApple OSS Distributions SLIST_INIT(&addq);
492*aca3beaaSApple OSS Distributions SLIST_INIT(&delq);
493*aca3beaaSApple OSS Distributions SLIST_INIT(&changeq);
494*aca3beaaSApple OSS Distributions for (i = 0; i < size; i++, addr += sizeof(ad)) {
495*aca3beaaSApple OSS Distributions if (COPYIN(addr, &ad, sizeof(ad), flags)) {
496*aca3beaaSApple OSS Distributions senderr(EFAULT);
497*aca3beaaSApple OSS Distributions }
498*aca3beaaSApple OSS Distributions if (pfr_validate_addr(&ad)) {
499*aca3beaaSApple OSS Distributions senderr(EINVAL);
500*aca3beaaSApple OSS Distributions }
501*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_NONE;
502*aca3beaaSApple OSS Distributions p = pfr_lookup_addr(kt, &ad, 1);
503*aca3beaaSApple OSS Distributions if (p != NULL) {
504*aca3beaaSApple OSS Distributions if (p->pfrke_mark) {
505*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_DUPLICATE;
506*aca3beaaSApple OSS Distributions goto _skip;
507*aca3beaaSApple OSS Distributions }
508*aca3beaaSApple OSS Distributions p->pfrke_mark = 1;
509*aca3beaaSApple OSS Distributions if (p->pfrke_not != ad.pfra_not) {
510*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&changeq, p, pfrke_workq);
511*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_CHANGED;
512*aca3beaaSApple OSS Distributions xchange++;
513*aca3beaaSApple OSS Distributions }
514*aca3beaaSApple OSS Distributions } else {
515*aca3beaaSApple OSS Distributions q = pfr_lookup_addr(tmpkt, &ad, 1);
516*aca3beaaSApple OSS Distributions if (q != NULL) {
517*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_DUPLICATE;
518*aca3beaaSApple OSS Distributions goto _skip;
519*aca3beaaSApple OSS Distributions }
520*aca3beaaSApple OSS Distributions p = pfr_create_kentry(&ad,
521*aca3beaaSApple OSS Distributions !(flags & PFR_FLAG_USERIOCTL));
522*aca3beaaSApple OSS Distributions if (p == NULL) {
523*aca3beaaSApple OSS Distributions senderr(ENOMEM);
524*aca3beaaSApple OSS Distributions }
525*aca3beaaSApple OSS Distributions if (pfr_route_kentry(tmpkt, p)) {
526*aca3beaaSApple OSS Distributions pfr_destroy_kentry(p);
527*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_NONE;
528*aca3beaaSApple OSS Distributions } else {
529*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&addq, p, pfrke_workq);
530*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_ADDED;
531*aca3beaaSApple OSS Distributions xadd++;
532*aca3beaaSApple OSS Distributions }
533*aca3beaaSApple OSS Distributions }
534*aca3beaaSApple OSS Distributions _skip:
535*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_FEEDBACK) {
536*aca3beaaSApple OSS Distributions if (COPYOUT(&ad, addr, sizeof(ad), flags)) {
537*aca3beaaSApple OSS Distributions senderr(EFAULT);
538*aca3beaaSApple OSS Distributions }
539*aca3beaaSApple OSS Distributions }
540*aca3beaaSApple OSS Distributions }
541*aca3beaaSApple OSS Distributions pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY);
542*aca3beaaSApple OSS Distributions if ((flags & PFR_FLAG_FEEDBACK) && *size2) {
543*aca3beaaSApple OSS Distributions if (*size2 < size + xdel) {
544*aca3beaaSApple OSS Distributions *size2 = size + xdel;
545*aca3beaaSApple OSS Distributions senderr(0);
546*aca3beaaSApple OSS Distributions }
547*aca3beaaSApple OSS Distributions i = 0;
548*aca3beaaSApple OSS Distributions addr = _addr + size;
549*aca3beaaSApple OSS Distributions SLIST_FOREACH(p, &delq, pfrke_workq) {
550*aca3beaaSApple OSS Distributions pfr_copyout_addr(&ad, p);
551*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_DELETED;
552*aca3beaaSApple OSS Distributions if (COPYOUT(&ad, addr, sizeof(ad), flags)) {
553*aca3beaaSApple OSS Distributions senderr(EFAULT);
554*aca3beaaSApple OSS Distributions }
555*aca3beaaSApple OSS Distributions addr += sizeof(ad);
556*aca3beaaSApple OSS Distributions i++;
557*aca3beaaSApple OSS Distributions }
558*aca3beaaSApple OSS Distributions }
559*aca3beaaSApple OSS Distributions pfr_clean_node_mask(tmpkt, &addq);
560*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
561*aca3beaaSApple OSS Distributions pfr_insert_kentries(kt, &addq, tzero);
562*aca3beaaSApple OSS Distributions pfr_remove_kentries(kt, &delq);
563*aca3beaaSApple OSS Distributions pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG);
564*aca3beaaSApple OSS Distributions } else {
565*aca3beaaSApple OSS Distributions pfr_destroy_kentries(&addq);
566*aca3beaaSApple OSS Distributions }
567*aca3beaaSApple OSS Distributions if (nadd != NULL) {
568*aca3beaaSApple OSS Distributions *nadd = xadd;
569*aca3beaaSApple OSS Distributions }
570*aca3beaaSApple OSS Distributions if (ndel != NULL) {
571*aca3beaaSApple OSS Distributions *ndel = xdel;
572*aca3beaaSApple OSS Distributions }
573*aca3beaaSApple OSS Distributions if (nchange != NULL) {
574*aca3beaaSApple OSS Distributions *nchange = xchange;
575*aca3beaaSApple OSS Distributions }
576*aca3beaaSApple OSS Distributions if ((flags & PFR_FLAG_FEEDBACK) && size2) {
577*aca3beaaSApple OSS Distributions *size2 = size + xdel;
578*aca3beaaSApple OSS Distributions }
579*aca3beaaSApple OSS Distributions pfr_destroy_ktable(tmpkt, 0);
580*aca3beaaSApple OSS Distributions return 0;
581*aca3beaaSApple OSS Distributions _bad:
582*aca3beaaSApple OSS Distributions pfr_clean_node_mask(tmpkt, &addq);
583*aca3beaaSApple OSS Distributions pfr_destroy_kentries(&addq);
584*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_FEEDBACK) {
585*aca3beaaSApple OSS Distributions pfr_reset_feedback(_addr, size, flags);
586*aca3beaaSApple OSS Distributions }
587*aca3beaaSApple OSS Distributions pfr_destroy_ktable(tmpkt, 0);
588*aca3beaaSApple OSS Distributions return rv;
589*aca3beaaSApple OSS Distributions }
590*aca3beaaSApple OSS Distributions
591*aca3beaaSApple OSS Distributions int
pfr_tst_addrs(struct pfr_table * tbl,user_addr_t addr,int size,int * nmatch,int flags)592*aca3beaaSApple OSS Distributions pfr_tst_addrs(struct pfr_table *tbl, user_addr_t addr, int size,
593*aca3beaaSApple OSS Distributions int *nmatch, int flags)
594*aca3beaaSApple OSS Distributions {
595*aca3beaaSApple OSS Distributions struct pfr_ktable *kt;
596*aca3beaaSApple OSS Distributions struct pfr_kentry *p;
597*aca3beaaSApple OSS Distributions struct pfr_addr ad;
598*aca3beaaSApple OSS Distributions int i, xmatch = 0;
599*aca3beaaSApple OSS Distributions
600*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_REPLACE);
601*aca3beaaSApple OSS Distributions if (pfr_validate_table(tbl, 0, 0)) {
602*aca3beaaSApple OSS Distributions return EINVAL;
603*aca3beaaSApple OSS Distributions }
604*aca3beaaSApple OSS Distributions kt = pfr_lookup_table(tbl);
605*aca3beaaSApple OSS Distributions if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
606*aca3beaaSApple OSS Distributions return ESRCH;
607*aca3beaaSApple OSS Distributions }
608*aca3beaaSApple OSS Distributions
609*aca3beaaSApple OSS Distributions for (i = 0; i < size; i++, addr += sizeof(ad)) {
610*aca3beaaSApple OSS Distributions if (COPYIN(addr, &ad, sizeof(ad), flags)) {
611*aca3beaaSApple OSS Distributions return EFAULT;
612*aca3beaaSApple OSS Distributions }
613*aca3beaaSApple OSS Distributions if (pfr_validate_addr(&ad)) {
614*aca3beaaSApple OSS Distributions return EINVAL;
615*aca3beaaSApple OSS Distributions }
616*aca3beaaSApple OSS Distributions if (ADDR_NETWORK(&ad)) {
617*aca3beaaSApple OSS Distributions return EINVAL;
618*aca3beaaSApple OSS Distributions }
619*aca3beaaSApple OSS Distributions p = pfr_lookup_addr(kt, &ad, 0);
620*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_REPLACE) {
621*aca3beaaSApple OSS Distributions pfr_copyout_addr(&ad, p);
622*aca3beaaSApple OSS Distributions }
623*aca3beaaSApple OSS Distributions ad.pfra_fback = (p == NULL) ? PFR_FB_NONE :
624*aca3beaaSApple OSS Distributions (p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH);
625*aca3beaaSApple OSS Distributions if (p != NULL && !p->pfrke_not) {
626*aca3beaaSApple OSS Distributions xmatch++;
627*aca3beaaSApple OSS Distributions }
628*aca3beaaSApple OSS Distributions if (COPYOUT(&ad, addr, sizeof(ad), flags)) {
629*aca3beaaSApple OSS Distributions return EFAULT;
630*aca3beaaSApple OSS Distributions }
631*aca3beaaSApple OSS Distributions }
632*aca3beaaSApple OSS Distributions if (nmatch != NULL) {
633*aca3beaaSApple OSS Distributions *nmatch = xmatch;
634*aca3beaaSApple OSS Distributions }
635*aca3beaaSApple OSS Distributions return 0;
636*aca3beaaSApple OSS Distributions }
637*aca3beaaSApple OSS Distributions
638*aca3beaaSApple OSS Distributions int
pfr_get_addrs(struct pfr_table * tbl,user_addr_t addr,int * size,int flags)639*aca3beaaSApple OSS Distributions pfr_get_addrs(struct pfr_table *tbl, user_addr_t addr, int *size,
640*aca3beaaSApple OSS Distributions int flags)
641*aca3beaaSApple OSS Distributions {
642*aca3beaaSApple OSS Distributions struct pfr_ktable *kt;
643*aca3beaaSApple OSS Distributions struct pfr_walktree w;
644*aca3beaaSApple OSS Distributions int rv;
645*aca3beaaSApple OSS Distributions
646*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, 0);
647*aca3beaaSApple OSS Distributions if (pfr_validate_table(tbl, 0, 0)) {
648*aca3beaaSApple OSS Distributions return EINVAL;
649*aca3beaaSApple OSS Distributions }
650*aca3beaaSApple OSS Distributions kt = pfr_lookup_table(tbl);
651*aca3beaaSApple OSS Distributions if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
652*aca3beaaSApple OSS Distributions return ESRCH;
653*aca3beaaSApple OSS Distributions }
654*aca3beaaSApple OSS Distributions if (kt->pfrkt_cnt > *size) {
655*aca3beaaSApple OSS Distributions *size = kt->pfrkt_cnt;
656*aca3beaaSApple OSS Distributions return 0;
657*aca3beaaSApple OSS Distributions }
658*aca3beaaSApple OSS Distributions
659*aca3beaaSApple OSS Distributions bzero(&w, sizeof(w));
660*aca3beaaSApple OSS Distributions w.pfrw_op = PFRW_GET_ADDRS;
661*aca3beaaSApple OSS Distributions w.pfrw_addr = addr;
662*aca3beaaSApple OSS Distributions w.pfrw_free = kt->pfrkt_cnt;
663*aca3beaaSApple OSS Distributions w.pfrw_flags = flags;
664*aca3beaaSApple OSS Distributions rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
665*aca3beaaSApple OSS Distributions if (!rv) {
666*aca3beaaSApple OSS Distributions rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6,
667*aca3beaaSApple OSS Distributions pfr_walktree, &w);
668*aca3beaaSApple OSS Distributions }
669*aca3beaaSApple OSS Distributions if (rv) {
670*aca3beaaSApple OSS Distributions return rv;
671*aca3beaaSApple OSS Distributions }
672*aca3beaaSApple OSS Distributions
673*aca3beaaSApple OSS Distributions if (w.pfrw_free) {
674*aca3beaaSApple OSS Distributions printf("pfr_get_addrs: corruption detected (%d).\n",
675*aca3beaaSApple OSS Distributions w.pfrw_free);
676*aca3beaaSApple OSS Distributions return ENOTTY;
677*aca3beaaSApple OSS Distributions }
678*aca3beaaSApple OSS Distributions *size = kt->pfrkt_cnt;
679*aca3beaaSApple OSS Distributions return 0;
680*aca3beaaSApple OSS Distributions }
681*aca3beaaSApple OSS Distributions
682*aca3beaaSApple OSS Distributions int
pfr_get_astats(struct pfr_table * tbl,user_addr_t addr,int * size,int flags)683*aca3beaaSApple OSS Distributions pfr_get_astats(struct pfr_table *tbl, user_addr_t addr, int *size,
684*aca3beaaSApple OSS Distributions int flags)
685*aca3beaaSApple OSS Distributions {
686*aca3beaaSApple OSS Distributions struct pfr_ktable *kt;
687*aca3beaaSApple OSS Distributions struct pfr_walktree w;
688*aca3beaaSApple OSS Distributions struct pfr_kentryworkq workq;
689*aca3beaaSApple OSS Distributions int rv;
690*aca3beaaSApple OSS Distributions u_int64_t tzero = pf_calendar_time_second();
691*aca3beaaSApple OSS Distributions
692*aca3beaaSApple OSS Distributions /* XXX PFR_FLAG_CLSTATS disabled */
693*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC);
694*aca3beaaSApple OSS Distributions if (pfr_validate_table(tbl, 0, 0)) {
695*aca3beaaSApple OSS Distributions return EINVAL;
696*aca3beaaSApple OSS Distributions }
697*aca3beaaSApple OSS Distributions kt = pfr_lookup_table(tbl);
698*aca3beaaSApple OSS Distributions if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
699*aca3beaaSApple OSS Distributions return ESRCH;
700*aca3beaaSApple OSS Distributions }
701*aca3beaaSApple OSS Distributions if (kt->pfrkt_cnt > *size) {
702*aca3beaaSApple OSS Distributions *size = kt->pfrkt_cnt;
703*aca3beaaSApple OSS Distributions return 0;
704*aca3beaaSApple OSS Distributions }
705*aca3beaaSApple OSS Distributions
706*aca3beaaSApple OSS Distributions bzero(&w, sizeof(w));
707*aca3beaaSApple OSS Distributions w.pfrw_op = PFRW_GET_ASTATS;
708*aca3beaaSApple OSS Distributions w.pfrw_astats = addr;
709*aca3beaaSApple OSS Distributions w.pfrw_free = kt->pfrkt_cnt;
710*aca3beaaSApple OSS Distributions w.pfrw_flags = flags;
711*aca3beaaSApple OSS Distributions rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
712*aca3beaaSApple OSS Distributions if (!rv) {
713*aca3beaaSApple OSS Distributions rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6,
714*aca3beaaSApple OSS Distributions pfr_walktree, &w);
715*aca3beaaSApple OSS Distributions }
716*aca3beaaSApple OSS Distributions if (!rv && (flags & PFR_FLAG_CLSTATS)) {
717*aca3beaaSApple OSS Distributions pfr_enqueue_addrs(kt, &workq, NULL, 0);
718*aca3beaaSApple OSS Distributions pfr_clstats_kentries(&workq, tzero, 0);
719*aca3beaaSApple OSS Distributions }
720*aca3beaaSApple OSS Distributions if (rv) {
721*aca3beaaSApple OSS Distributions return rv;
722*aca3beaaSApple OSS Distributions }
723*aca3beaaSApple OSS Distributions
724*aca3beaaSApple OSS Distributions if (w.pfrw_free) {
725*aca3beaaSApple OSS Distributions printf("pfr_get_astats: corruption detected (%d).\n",
726*aca3beaaSApple OSS Distributions w.pfrw_free);
727*aca3beaaSApple OSS Distributions return ENOTTY;
728*aca3beaaSApple OSS Distributions }
729*aca3beaaSApple OSS Distributions *size = kt->pfrkt_cnt;
730*aca3beaaSApple OSS Distributions return 0;
731*aca3beaaSApple OSS Distributions }
732*aca3beaaSApple OSS Distributions
733*aca3beaaSApple OSS Distributions int
pfr_clr_astats(struct pfr_table * tbl,user_addr_t _addr,int size,int * nzero,int flags)734*aca3beaaSApple OSS Distributions pfr_clr_astats(struct pfr_table *tbl, user_addr_t _addr, int size,
735*aca3beaaSApple OSS Distributions int *nzero, int flags)
736*aca3beaaSApple OSS Distributions {
737*aca3beaaSApple OSS Distributions struct pfr_ktable *kt;
738*aca3beaaSApple OSS Distributions struct pfr_kentryworkq workq;
739*aca3beaaSApple OSS Distributions struct pfr_kentry *p;
740*aca3beaaSApple OSS Distributions struct pfr_addr ad;
741*aca3beaaSApple OSS Distributions user_addr_t addr = _addr;
742*aca3beaaSApple OSS Distributions int i, rv, xzero = 0;
743*aca3beaaSApple OSS Distributions
744*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
745*aca3beaaSApple OSS Distributions PFR_FLAG_FEEDBACK);
746*aca3beaaSApple OSS Distributions if (pfr_validate_table(tbl, 0, 0)) {
747*aca3beaaSApple OSS Distributions return EINVAL;
748*aca3beaaSApple OSS Distributions }
749*aca3beaaSApple OSS Distributions kt = pfr_lookup_table(tbl);
750*aca3beaaSApple OSS Distributions if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
751*aca3beaaSApple OSS Distributions return ESRCH;
752*aca3beaaSApple OSS Distributions }
753*aca3beaaSApple OSS Distributions SLIST_INIT(&workq);
754*aca3beaaSApple OSS Distributions for (i = 0; i < size; i++, addr += sizeof(ad)) {
755*aca3beaaSApple OSS Distributions if (COPYIN(addr, &ad, sizeof(ad), flags)) {
756*aca3beaaSApple OSS Distributions senderr(EFAULT);
757*aca3beaaSApple OSS Distributions }
758*aca3beaaSApple OSS Distributions if (pfr_validate_addr(&ad)) {
759*aca3beaaSApple OSS Distributions senderr(EINVAL);
760*aca3beaaSApple OSS Distributions }
761*aca3beaaSApple OSS Distributions p = pfr_lookup_addr(kt, &ad, 1);
762*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_FEEDBACK) {
763*aca3beaaSApple OSS Distributions ad.pfra_fback = (p != NULL) ?
764*aca3beaaSApple OSS Distributions PFR_FB_CLEARED : PFR_FB_NONE;
765*aca3beaaSApple OSS Distributions if (COPYOUT(&ad, addr, sizeof(ad), flags)) {
766*aca3beaaSApple OSS Distributions senderr(EFAULT);
767*aca3beaaSApple OSS Distributions }
768*aca3beaaSApple OSS Distributions }
769*aca3beaaSApple OSS Distributions if (p != NULL) {
770*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
771*aca3beaaSApple OSS Distributions xzero++;
772*aca3beaaSApple OSS Distributions }
773*aca3beaaSApple OSS Distributions }
774*aca3beaaSApple OSS Distributions
775*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
776*aca3beaaSApple OSS Distributions pfr_clstats_kentries(&workq, 0, 0);
777*aca3beaaSApple OSS Distributions }
778*aca3beaaSApple OSS Distributions if (nzero != NULL) {
779*aca3beaaSApple OSS Distributions *nzero = xzero;
780*aca3beaaSApple OSS Distributions }
781*aca3beaaSApple OSS Distributions return 0;
782*aca3beaaSApple OSS Distributions _bad:
783*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_FEEDBACK) {
784*aca3beaaSApple OSS Distributions pfr_reset_feedback(_addr, size, flags);
785*aca3beaaSApple OSS Distributions }
786*aca3beaaSApple OSS Distributions return rv;
787*aca3beaaSApple OSS Distributions }
788*aca3beaaSApple OSS Distributions
789*aca3beaaSApple OSS Distributions static int
pfr_validate_addr(struct pfr_addr * ad)790*aca3beaaSApple OSS Distributions pfr_validate_addr(struct pfr_addr *ad)
791*aca3beaaSApple OSS Distributions {
792*aca3beaaSApple OSS Distributions int i;
793*aca3beaaSApple OSS Distributions
794*aca3beaaSApple OSS Distributions switch (ad->pfra_af) {
795*aca3beaaSApple OSS Distributions #if INET
796*aca3beaaSApple OSS Distributions case AF_INET:
797*aca3beaaSApple OSS Distributions if (ad->pfra_net > 32) {
798*aca3beaaSApple OSS Distributions return -1;
799*aca3beaaSApple OSS Distributions }
800*aca3beaaSApple OSS Distributions break;
801*aca3beaaSApple OSS Distributions #endif /* INET */
802*aca3beaaSApple OSS Distributions case AF_INET6:
803*aca3beaaSApple OSS Distributions if (ad->pfra_net > 128) {
804*aca3beaaSApple OSS Distributions return -1;
805*aca3beaaSApple OSS Distributions }
806*aca3beaaSApple OSS Distributions break;
807*aca3beaaSApple OSS Distributions default:
808*aca3beaaSApple OSS Distributions return -1;
809*aca3beaaSApple OSS Distributions }
810*aca3beaaSApple OSS Distributions if (ad->pfra_net < 128 &&
811*aca3beaaSApple OSS Distributions (((caddr_t)ad)[ad->pfra_net / 8] & (0xFF >> (ad->pfra_net % 8)))) {
812*aca3beaaSApple OSS Distributions return -1;
813*aca3beaaSApple OSS Distributions }
814*aca3beaaSApple OSS Distributions for (i = (ad->pfra_net + 7) / 8; i < (int)sizeof(ad->pfra_u); i++) {
815*aca3beaaSApple OSS Distributions if (((caddr_t)ad)[i]) {
816*aca3beaaSApple OSS Distributions return -1;
817*aca3beaaSApple OSS Distributions }
818*aca3beaaSApple OSS Distributions }
819*aca3beaaSApple OSS Distributions if (ad->pfra_not && ad->pfra_not != 1) {
820*aca3beaaSApple OSS Distributions return -1;
821*aca3beaaSApple OSS Distributions }
822*aca3beaaSApple OSS Distributions if (ad->pfra_fback) {
823*aca3beaaSApple OSS Distributions return -1;
824*aca3beaaSApple OSS Distributions }
825*aca3beaaSApple OSS Distributions return 0;
826*aca3beaaSApple OSS Distributions }
827*aca3beaaSApple OSS Distributions
828*aca3beaaSApple OSS Distributions static void
pfr_enqueue_addrs(struct pfr_ktable * kt,struct pfr_kentryworkq * workq,int * naddr,int sweep)829*aca3beaaSApple OSS Distributions pfr_enqueue_addrs(struct pfr_ktable *kt, struct pfr_kentryworkq *workq,
830*aca3beaaSApple OSS Distributions int *naddr, int sweep)
831*aca3beaaSApple OSS Distributions {
832*aca3beaaSApple OSS Distributions struct pfr_walktree w;
833*aca3beaaSApple OSS Distributions
834*aca3beaaSApple OSS Distributions SLIST_INIT(workq);
835*aca3beaaSApple OSS Distributions bzero(&w, sizeof(w));
836*aca3beaaSApple OSS Distributions w.pfrw_op = sweep ? PFRW_SWEEP : PFRW_ENQUEUE;
837*aca3beaaSApple OSS Distributions w.pfrw_workq = workq;
838*aca3beaaSApple OSS Distributions if (kt->pfrkt_ip4 != NULL) {
839*aca3beaaSApple OSS Distributions if (kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4,
840*aca3beaaSApple OSS Distributions pfr_walktree, &w)) {
841*aca3beaaSApple OSS Distributions printf("pfr_enqueue_addrs: IPv4 walktree failed.\n");
842*aca3beaaSApple OSS Distributions }
843*aca3beaaSApple OSS Distributions }
844*aca3beaaSApple OSS Distributions if (kt->pfrkt_ip6 != NULL) {
845*aca3beaaSApple OSS Distributions if (kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6,
846*aca3beaaSApple OSS Distributions pfr_walktree, &w)) {
847*aca3beaaSApple OSS Distributions printf("pfr_enqueue_addrs: IPv6 walktree failed.\n");
848*aca3beaaSApple OSS Distributions }
849*aca3beaaSApple OSS Distributions }
850*aca3beaaSApple OSS Distributions if (naddr != NULL) {
851*aca3beaaSApple OSS Distributions *naddr = w.pfrw_cnt;
852*aca3beaaSApple OSS Distributions }
853*aca3beaaSApple OSS Distributions }
854*aca3beaaSApple OSS Distributions
855*aca3beaaSApple OSS Distributions static void
pfr_mark_addrs(struct pfr_ktable * kt)856*aca3beaaSApple OSS Distributions pfr_mark_addrs(struct pfr_ktable *kt)
857*aca3beaaSApple OSS Distributions {
858*aca3beaaSApple OSS Distributions struct pfr_walktree w;
859*aca3beaaSApple OSS Distributions
860*aca3beaaSApple OSS Distributions bzero(&w, sizeof(w));
861*aca3beaaSApple OSS Distributions w.pfrw_op = PFRW_MARK;
862*aca3beaaSApple OSS Distributions if (kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w)) {
863*aca3beaaSApple OSS Distributions printf("pfr_mark_addrs: IPv4 walktree failed.\n");
864*aca3beaaSApple OSS Distributions }
865*aca3beaaSApple OSS Distributions if (kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w)) {
866*aca3beaaSApple OSS Distributions printf("pfr_mark_addrs: IPv6 walktree failed.\n");
867*aca3beaaSApple OSS Distributions }
868*aca3beaaSApple OSS Distributions }
869*aca3beaaSApple OSS Distributions
870*aca3beaaSApple OSS Distributions
871*aca3beaaSApple OSS Distributions static struct pfr_kentry *
pfr_lookup_addr(struct pfr_ktable * kt,struct pfr_addr * ad,int exact)872*aca3beaaSApple OSS Distributions pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
873*aca3beaaSApple OSS Distributions {
874*aca3beaaSApple OSS Distributions union sockaddr_union sa, mask;
875*aca3beaaSApple OSS Distributions struct radix_node_head *head;
876*aca3beaaSApple OSS Distributions struct pfr_kentry *ke;
877*aca3beaaSApple OSS Distributions
878*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
879*aca3beaaSApple OSS Distributions
880*aca3beaaSApple OSS Distributions bzero(&sa, sizeof(sa));
881*aca3beaaSApple OSS Distributions if (ad->pfra_af == AF_INET) {
882*aca3beaaSApple OSS Distributions FILLIN_SIN(sa.sin, ad->pfra_ip4addr);
883*aca3beaaSApple OSS Distributions head = kt->pfrkt_ip4;
884*aca3beaaSApple OSS Distributions } else if (ad->pfra_af == AF_INET6) {
885*aca3beaaSApple OSS Distributions FILLIN_SIN6(sa.sin6, ad->pfra_ip6addr);
886*aca3beaaSApple OSS Distributions head = kt->pfrkt_ip6;
887*aca3beaaSApple OSS Distributions } else {
888*aca3beaaSApple OSS Distributions return NULL;
889*aca3beaaSApple OSS Distributions }
890*aca3beaaSApple OSS Distributions if (ADDR_NETWORK(ad)) {
891*aca3beaaSApple OSS Distributions pfr_prepare_network(&mask, ad->pfra_af, ad->pfra_net);
892*aca3beaaSApple OSS Distributions ke = (struct pfr_kentry *)rn_lookup(&sa, &mask, head);
893*aca3beaaSApple OSS Distributions if (ke && KENTRY_RNF_ROOT(ke)) {
894*aca3beaaSApple OSS Distributions ke = NULL;
895*aca3beaaSApple OSS Distributions }
896*aca3beaaSApple OSS Distributions } else {
897*aca3beaaSApple OSS Distributions ke = (struct pfr_kentry *)rn_match(&sa, head);
898*aca3beaaSApple OSS Distributions if (ke && KENTRY_RNF_ROOT(ke)) {
899*aca3beaaSApple OSS Distributions ke = NULL;
900*aca3beaaSApple OSS Distributions }
901*aca3beaaSApple OSS Distributions if (exact && ke && KENTRY_NETWORK(ke)) {
902*aca3beaaSApple OSS Distributions ke = NULL;
903*aca3beaaSApple OSS Distributions }
904*aca3beaaSApple OSS Distributions }
905*aca3beaaSApple OSS Distributions return ke;
906*aca3beaaSApple OSS Distributions }
907*aca3beaaSApple OSS Distributions
908*aca3beaaSApple OSS Distributions static struct pfr_kentry *
pfr_create_kentry(struct pfr_addr * ad,boolean_t intr)909*aca3beaaSApple OSS Distributions pfr_create_kentry(struct pfr_addr *ad, boolean_t intr)
910*aca3beaaSApple OSS Distributions {
911*aca3beaaSApple OSS Distributions struct pfr_kentry *ke;
912*aca3beaaSApple OSS Distributions
913*aca3beaaSApple OSS Distributions if (intr) {
914*aca3beaaSApple OSS Distributions ke = pool_get(&pfr_kentry_pl2, PR_WAITOK);
915*aca3beaaSApple OSS Distributions } else {
916*aca3beaaSApple OSS Distributions ke = pool_get(&pfr_kentry_pl, PR_WAITOK);
917*aca3beaaSApple OSS Distributions }
918*aca3beaaSApple OSS Distributions if (ke == NULL) {
919*aca3beaaSApple OSS Distributions return NULL;
920*aca3beaaSApple OSS Distributions }
921*aca3beaaSApple OSS Distributions bzero(ke, sizeof(*ke));
922*aca3beaaSApple OSS Distributions
923*aca3beaaSApple OSS Distributions if (ad->pfra_af == AF_INET) {
924*aca3beaaSApple OSS Distributions FILLIN_SIN(ke->pfrke_sa.sin, ad->pfra_ip4addr);
925*aca3beaaSApple OSS Distributions } else if (ad->pfra_af == AF_INET6) {
926*aca3beaaSApple OSS Distributions FILLIN_SIN6(ke->pfrke_sa.sin6, ad->pfra_ip6addr);
927*aca3beaaSApple OSS Distributions }
928*aca3beaaSApple OSS Distributions ke->pfrke_af = ad->pfra_af;
929*aca3beaaSApple OSS Distributions ke->pfrke_net = ad->pfra_net;
930*aca3beaaSApple OSS Distributions ke->pfrke_not = ad->pfra_not;
931*aca3beaaSApple OSS Distributions ke->pfrke_intrpool = (u_int8_t)intr;
932*aca3beaaSApple OSS Distributions return ke;
933*aca3beaaSApple OSS Distributions }
934*aca3beaaSApple OSS Distributions
935*aca3beaaSApple OSS Distributions static void
pfr_destroy_kentries(struct pfr_kentryworkq * workq)936*aca3beaaSApple OSS Distributions pfr_destroy_kentries(struct pfr_kentryworkq *workq)
937*aca3beaaSApple OSS Distributions {
938*aca3beaaSApple OSS Distributions struct pfr_kentry *p, *q;
939*aca3beaaSApple OSS Distributions
940*aca3beaaSApple OSS Distributions for (p = SLIST_FIRST(workq); p != NULL; p = q) {
941*aca3beaaSApple OSS Distributions q = SLIST_NEXT(p, pfrke_workq);
942*aca3beaaSApple OSS Distributions pfr_destroy_kentry(p);
943*aca3beaaSApple OSS Distributions }
944*aca3beaaSApple OSS Distributions }
945*aca3beaaSApple OSS Distributions
946*aca3beaaSApple OSS Distributions static void
pfr_destroy_kentry(struct pfr_kentry * ke)947*aca3beaaSApple OSS Distributions pfr_destroy_kentry(struct pfr_kentry *ke)
948*aca3beaaSApple OSS Distributions {
949*aca3beaaSApple OSS Distributions if (ke->pfrke_intrpool) {
950*aca3beaaSApple OSS Distributions pool_put(&pfr_kentry_pl2, ke);
951*aca3beaaSApple OSS Distributions } else {
952*aca3beaaSApple OSS Distributions pool_put(&pfr_kentry_pl, ke);
953*aca3beaaSApple OSS Distributions }
954*aca3beaaSApple OSS Distributions }
955*aca3beaaSApple OSS Distributions
956*aca3beaaSApple OSS Distributions static void
pfr_insert_kentries(struct pfr_ktable * kt,struct pfr_kentryworkq * workq,u_int64_t tzero)957*aca3beaaSApple OSS Distributions pfr_insert_kentries(struct pfr_ktable *kt,
958*aca3beaaSApple OSS Distributions struct pfr_kentryworkq *workq, u_int64_t tzero)
959*aca3beaaSApple OSS Distributions {
960*aca3beaaSApple OSS Distributions struct pfr_kentry *p;
961*aca3beaaSApple OSS Distributions int rv, n = 0;
962*aca3beaaSApple OSS Distributions
963*aca3beaaSApple OSS Distributions SLIST_FOREACH(p, workq, pfrke_workq) {
964*aca3beaaSApple OSS Distributions rv = pfr_route_kentry(kt, p);
965*aca3beaaSApple OSS Distributions if (rv) {
966*aca3beaaSApple OSS Distributions printf("pfr_insert_kentries: cannot route entry "
967*aca3beaaSApple OSS Distributions "(code=%d).\n", rv);
968*aca3beaaSApple OSS Distributions break;
969*aca3beaaSApple OSS Distributions }
970*aca3beaaSApple OSS Distributions p->pfrke_tzero = tzero;
971*aca3beaaSApple OSS Distributions n++;
972*aca3beaaSApple OSS Distributions }
973*aca3beaaSApple OSS Distributions kt->pfrkt_cnt += n;
974*aca3beaaSApple OSS Distributions }
975*aca3beaaSApple OSS Distributions
976*aca3beaaSApple OSS Distributions int
pfr_insert_kentry(struct pfr_ktable * kt,struct pfr_addr * ad,u_int64_t tzero)977*aca3beaaSApple OSS Distributions pfr_insert_kentry(struct pfr_ktable *kt, struct pfr_addr *ad, u_int64_t tzero)
978*aca3beaaSApple OSS Distributions {
979*aca3beaaSApple OSS Distributions struct pfr_kentry *p;
980*aca3beaaSApple OSS Distributions int rv;
981*aca3beaaSApple OSS Distributions
982*aca3beaaSApple OSS Distributions p = pfr_lookup_addr(kt, ad, 1);
983*aca3beaaSApple OSS Distributions if (p != NULL) {
984*aca3beaaSApple OSS Distributions return 0;
985*aca3beaaSApple OSS Distributions }
986*aca3beaaSApple OSS Distributions p = pfr_create_kentry(ad, TRUE);
987*aca3beaaSApple OSS Distributions if (p == NULL) {
988*aca3beaaSApple OSS Distributions return EINVAL;
989*aca3beaaSApple OSS Distributions }
990*aca3beaaSApple OSS Distributions
991*aca3beaaSApple OSS Distributions rv = pfr_route_kentry(kt, p);
992*aca3beaaSApple OSS Distributions if (rv) {
993*aca3beaaSApple OSS Distributions return rv;
994*aca3beaaSApple OSS Distributions }
995*aca3beaaSApple OSS Distributions
996*aca3beaaSApple OSS Distributions p->pfrke_tzero = tzero;
997*aca3beaaSApple OSS Distributions kt->pfrkt_cnt++;
998*aca3beaaSApple OSS Distributions
999*aca3beaaSApple OSS Distributions return 0;
1000*aca3beaaSApple OSS Distributions }
1001*aca3beaaSApple OSS Distributions
1002*aca3beaaSApple OSS Distributions static void
pfr_remove_kentries(struct pfr_ktable * kt,struct pfr_kentryworkq * workq)1003*aca3beaaSApple OSS Distributions pfr_remove_kentries(struct pfr_ktable *kt,
1004*aca3beaaSApple OSS Distributions struct pfr_kentryworkq *workq)
1005*aca3beaaSApple OSS Distributions {
1006*aca3beaaSApple OSS Distributions struct pfr_kentry *p;
1007*aca3beaaSApple OSS Distributions int n = 0;
1008*aca3beaaSApple OSS Distributions
1009*aca3beaaSApple OSS Distributions SLIST_FOREACH(p, workq, pfrke_workq) {
1010*aca3beaaSApple OSS Distributions pfr_unroute_kentry(kt, p);
1011*aca3beaaSApple OSS Distributions n++;
1012*aca3beaaSApple OSS Distributions }
1013*aca3beaaSApple OSS Distributions kt->pfrkt_cnt -= n;
1014*aca3beaaSApple OSS Distributions pfr_destroy_kentries(workq);
1015*aca3beaaSApple OSS Distributions }
1016*aca3beaaSApple OSS Distributions
1017*aca3beaaSApple OSS Distributions static void
pfr_clean_node_mask(struct pfr_ktable * kt,struct pfr_kentryworkq * workq)1018*aca3beaaSApple OSS Distributions pfr_clean_node_mask(struct pfr_ktable *kt,
1019*aca3beaaSApple OSS Distributions struct pfr_kentryworkq *workq)
1020*aca3beaaSApple OSS Distributions {
1021*aca3beaaSApple OSS Distributions struct pfr_kentry *p;
1022*aca3beaaSApple OSS Distributions
1023*aca3beaaSApple OSS Distributions SLIST_FOREACH(p, workq, pfrke_workq)
1024*aca3beaaSApple OSS Distributions pfr_unroute_kentry(kt, p);
1025*aca3beaaSApple OSS Distributions }
1026*aca3beaaSApple OSS Distributions
1027*aca3beaaSApple OSS Distributions static void
pfr_clstats_kentries(struct pfr_kentryworkq * workq,u_int64_t tzero,int negchange)1028*aca3beaaSApple OSS Distributions pfr_clstats_kentries(struct pfr_kentryworkq *workq, u_int64_t tzero,
1029*aca3beaaSApple OSS Distributions int negchange)
1030*aca3beaaSApple OSS Distributions {
1031*aca3beaaSApple OSS Distributions struct pfr_kentry *p;
1032*aca3beaaSApple OSS Distributions
1033*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1034*aca3beaaSApple OSS Distributions
1035*aca3beaaSApple OSS Distributions SLIST_FOREACH(p, workq, pfrke_workq) {
1036*aca3beaaSApple OSS Distributions if (negchange) {
1037*aca3beaaSApple OSS Distributions p->pfrke_not = !p->pfrke_not;
1038*aca3beaaSApple OSS Distributions }
1039*aca3beaaSApple OSS Distributions bzero(p->pfrke_packets, sizeof(p->pfrke_packets));
1040*aca3beaaSApple OSS Distributions bzero(p->pfrke_bytes, sizeof(p->pfrke_bytes));
1041*aca3beaaSApple OSS Distributions p->pfrke_tzero = tzero;
1042*aca3beaaSApple OSS Distributions }
1043*aca3beaaSApple OSS Distributions }
1044*aca3beaaSApple OSS Distributions
1045*aca3beaaSApple OSS Distributions static void
pfr_reset_feedback(user_addr_t addr,int size,int flags)1046*aca3beaaSApple OSS Distributions pfr_reset_feedback(user_addr_t addr, int size, int flags)
1047*aca3beaaSApple OSS Distributions {
1048*aca3beaaSApple OSS Distributions struct pfr_addr ad;
1049*aca3beaaSApple OSS Distributions int i;
1050*aca3beaaSApple OSS Distributions
1051*aca3beaaSApple OSS Distributions for (i = 0; i < size; i++, addr += sizeof(ad)) {
1052*aca3beaaSApple OSS Distributions if (COPYIN(addr, &ad, sizeof(ad), flags)) {
1053*aca3beaaSApple OSS Distributions break;
1054*aca3beaaSApple OSS Distributions }
1055*aca3beaaSApple OSS Distributions ad.pfra_fback = PFR_FB_NONE;
1056*aca3beaaSApple OSS Distributions if (COPYOUT(&ad, addr, sizeof(ad), flags)) {
1057*aca3beaaSApple OSS Distributions break;
1058*aca3beaaSApple OSS Distributions }
1059*aca3beaaSApple OSS Distributions }
1060*aca3beaaSApple OSS Distributions }
1061*aca3beaaSApple OSS Distributions
1062*aca3beaaSApple OSS Distributions static void
pfr_prepare_network(union sockaddr_union * sa,int af,int net)1063*aca3beaaSApple OSS Distributions pfr_prepare_network(union sockaddr_union *sa, int af, int net)
1064*aca3beaaSApple OSS Distributions {
1065*aca3beaaSApple OSS Distributions int i;
1066*aca3beaaSApple OSS Distributions
1067*aca3beaaSApple OSS Distributions bzero(sa, sizeof(*sa));
1068*aca3beaaSApple OSS Distributions if (af == AF_INET) {
1069*aca3beaaSApple OSS Distributions sa->sin.sin_len = sizeof(sa->sin);
1070*aca3beaaSApple OSS Distributions sa->sin.sin_family = AF_INET;
1071*aca3beaaSApple OSS Distributions sa->sin.sin_addr.s_addr = net ? htonl(-1 << (32 - net)) : 0;
1072*aca3beaaSApple OSS Distributions } else if (af == AF_INET6) {
1073*aca3beaaSApple OSS Distributions sa->sin6.sin6_len = sizeof(sa->sin6);
1074*aca3beaaSApple OSS Distributions sa->sin6.sin6_family = AF_INET6;
1075*aca3beaaSApple OSS Distributions for (i = 0; i < 4; i++) {
1076*aca3beaaSApple OSS Distributions if (net <= 32) {
1077*aca3beaaSApple OSS Distributions sa->sin6.sin6_addr.s6_addr32[i] =
1078*aca3beaaSApple OSS Distributions net ? htonl(-1 << (32 - net)) : 0;
1079*aca3beaaSApple OSS Distributions break;
1080*aca3beaaSApple OSS Distributions }
1081*aca3beaaSApple OSS Distributions sa->sin6.sin6_addr.s6_addr32[i] = 0xFFFFFFFF;
1082*aca3beaaSApple OSS Distributions net -= 32;
1083*aca3beaaSApple OSS Distributions }
1084*aca3beaaSApple OSS Distributions }
1085*aca3beaaSApple OSS Distributions }
1086*aca3beaaSApple OSS Distributions
1087*aca3beaaSApple OSS Distributions static int
pfr_route_kentry(struct pfr_ktable * kt,struct pfr_kentry * ke)1088*aca3beaaSApple OSS Distributions pfr_route_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
1089*aca3beaaSApple OSS Distributions {
1090*aca3beaaSApple OSS Distributions union sockaddr_union mask;
1091*aca3beaaSApple OSS Distributions struct radix_node *rn;
1092*aca3beaaSApple OSS Distributions struct radix_node_head *head;
1093*aca3beaaSApple OSS Distributions
1094*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1095*aca3beaaSApple OSS Distributions
1096*aca3beaaSApple OSS Distributions bzero(ke->pfrke_node, sizeof(ke->pfrke_node));
1097*aca3beaaSApple OSS Distributions if (ke->pfrke_af == AF_INET) {
1098*aca3beaaSApple OSS Distributions head = kt->pfrkt_ip4;
1099*aca3beaaSApple OSS Distributions } else if (ke->pfrke_af == AF_INET6) {
1100*aca3beaaSApple OSS Distributions head = kt->pfrkt_ip6;
1101*aca3beaaSApple OSS Distributions } else {
1102*aca3beaaSApple OSS Distributions return -1;
1103*aca3beaaSApple OSS Distributions }
1104*aca3beaaSApple OSS Distributions
1105*aca3beaaSApple OSS Distributions if (KENTRY_NETWORK(ke)) {
1106*aca3beaaSApple OSS Distributions pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
1107*aca3beaaSApple OSS Distributions rn = rn_addroute(&ke->pfrke_sa, &mask, head, ke->pfrke_node);
1108*aca3beaaSApple OSS Distributions } else {
1109*aca3beaaSApple OSS Distributions rn = rn_addroute(&ke->pfrke_sa, NULL, head, ke->pfrke_node);
1110*aca3beaaSApple OSS Distributions }
1111*aca3beaaSApple OSS Distributions
1112*aca3beaaSApple OSS Distributions return rn == NULL ? -1 : 0;
1113*aca3beaaSApple OSS Distributions }
1114*aca3beaaSApple OSS Distributions
1115*aca3beaaSApple OSS Distributions static int
pfr_unroute_kentry(struct pfr_ktable * kt,struct pfr_kentry * ke)1116*aca3beaaSApple OSS Distributions pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
1117*aca3beaaSApple OSS Distributions {
1118*aca3beaaSApple OSS Distributions union sockaddr_union mask;
1119*aca3beaaSApple OSS Distributions struct radix_node *rn;
1120*aca3beaaSApple OSS Distributions struct radix_node_head *head;
1121*aca3beaaSApple OSS Distributions
1122*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1123*aca3beaaSApple OSS Distributions
1124*aca3beaaSApple OSS Distributions if (ke->pfrke_af == AF_INET) {
1125*aca3beaaSApple OSS Distributions head = kt->pfrkt_ip4;
1126*aca3beaaSApple OSS Distributions } else if (ke->pfrke_af == AF_INET6) {
1127*aca3beaaSApple OSS Distributions head = kt->pfrkt_ip6;
1128*aca3beaaSApple OSS Distributions } else {
1129*aca3beaaSApple OSS Distributions return -1;
1130*aca3beaaSApple OSS Distributions }
1131*aca3beaaSApple OSS Distributions
1132*aca3beaaSApple OSS Distributions if (KENTRY_NETWORK(ke)) {
1133*aca3beaaSApple OSS Distributions pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
1134*aca3beaaSApple OSS Distributions rn = rn_delete(&ke->pfrke_sa, &mask, head);
1135*aca3beaaSApple OSS Distributions } else {
1136*aca3beaaSApple OSS Distributions rn = rn_delete(&ke->pfrke_sa, NULL, head);
1137*aca3beaaSApple OSS Distributions }
1138*aca3beaaSApple OSS Distributions
1139*aca3beaaSApple OSS Distributions if (rn == NULL) {
1140*aca3beaaSApple OSS Distributions printf("pfr_unroute_kentry: delete failed.\n");
1141*aca3beaaSApple OSS Distributions return -1;
1142*aca3beaaSApple OSS Distributions }
1143*aca3beaaSApple OSS Distributions return 0;
1144*aca3beaaSApple OSS Distributions }
1145*aca3beaaSApple OSS Distributions
1146*aca3beaaSApple OSS Distributions static void
pfr_copyout_addr(struct pfr_addr * ad,struct pfr_kentry * ke)1147*aca3beaaSApple OSS Distributions pfr_copyout_addr(struct pfr_addr *ad, struct pfr_kentry *ke)
1148*aca3beaaSApple OSS Distributions {
1149*aca3beaaSApple OSS Distributions bzero(ad, sizeof(*ad));
1150*aca3beaaSApple OSS Distributions if (ke == NULL) {
1151*aca3beaaSApple OSS Distributions return;
1152*aca3beaaSApple OSS Distributions }
1153*aca3beaaSApple OSS Distributions ad->pfra_af = ke->pfrke_af;
1154*aca3beaaSApple OSS Distributions ad->pfra_net = ke->pfrke_net;
1155*aca3beaaSApple OSS Distributions ad->pfra_not = ke->pfrke_not;
1156*aca3beaaSApple OSS Distributions if (ad->pfra_af == AF_INET) {
1157*aca3beaaSApple OSS Distributions ad->pfra_ip4addr = ke->pfrke_sa.sin.sin_addr;
1158*aca3beaaSApple OSS Distributions } else if (ad->pfra_af == AF_INET6) {
1159*aca3beaaSApple OSS Distributions ad->pfra_ip6addr = ke->pfrke_sa.sin6.sin6_addr;
1160*aca3beaaSApple OSS Distributions }
1161*aca3beaaSApple OSS Distributions }
1162*aca3beaaSApple OSS Distributions
1163*aca3beaaSApple OSS Distributions static int
pfr_walktree(struct radix_node * rn,void * arg)1164*aca3beaaSApple OSS Distributions pfr_walktree(struct radix_node *rn, void *arg)
1165*aca3beaaSApple OSS Distributions {
1166*aca3beaaSApple OSS Distributions struct pfr_kentry *ke = (struct pfr_kentry *)rn;
1167*aca3beaaSApple OSS Distributions struct pfr_walktree *w = arg;
1168*aca3beaaSApple OSS Distributions int flags = w->pfrw_flags;
1169*aca3beaaSApple OSS Distributions
1170*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1171*aca3beaaSApple OSS Distributions
1172*aca3beaaSApple OSS Distributions VERIFY(ke != NULL);
1173*aca3beaaSApple OSS Distributions switch (w->pfrw_op) {
1174*aca3beaaSApple OSS Distributions case PFRW_MARK:
1175*aca3beaaSApple OSS Distributions ke->pfrke_mark = 0;
1176*aca3beaaSApple OSS Distributions break;
1177*aca3beaaSApple OSS Distributions case PFRW_SWEEP:
1178*aca3beaaSApple OSS Distributions if (ke->pfrke_mark) {
1179*aca3beaaSApple OSS Distributions break;
1180*aca3beaaSApple OSS Distributions }
1181*aca3beaaSApple OSS Distributions OS_FALLTHROUGH;
1182*aca3beaaSApple OSS Distributions case PFRW_ENQUEUE:
1183*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(w->pfrw_workq, ke, pfrke_workq);
1184*aca3beaaSApple OSS Distributions w->pfrw_cnt++;
1185*aca3beaaSApple OSS Distributions break;
1186*aca3beaaSApple OSS Distributions case PFRW_GET_ADDRS:
1187*aca3beaaSApple OSS Distributions if (w->pfrw_free-- > 0) {
1188*aca3beaaSApple OSS Distributions struct pfr_addr ad;
1189*aca3beaaSApple OSS Distributions
1190*aca3beaaSApple OSS Distributions pfr_copyout_addr(&ad, ke);
1191*aca3beaaSApple OSS Distributions if (copyout(&ad, w->pfrw_addr, sizeof(ad))) {
1192*aca3beaaSApple OSS Distributions return EFAULT;
1193*aca3beaaSApple OSS Distributions }
1194*aca3beaaSApple OSS Distributions w->pfrw_addr += sizeof(ad);
1195*aca3beaaSApple OSS Distributions }
1196*aca3beaaSApple OSS Distributions break;
1197*aca3beaaSApple OSS Distributions case PFRW_GET_ASTATS:
1198*aca3beaaSApple OSS Distributions if (w->pfrw_free-- > 0) {
1199*aca3beaaSApple OSS Distributions struct pfr_astats as;
1200*aca3beaaSApple OSS Distributions
1201*aca3beaaSApple OSS Distributions bzero(&as, sizeof(as));
1202*aca3beaaSApple OSS Distributions
1203*aca3beaaSApple OSS Distributions pfr_copyout_addr(&as.pfras_a, ke);
1204*aca3beaaSApple OSS Distributions
1205*aca3beaaSApple OSS Distributions bcopy(ke->pfrke_packets, as.pfras_packets,
1206*aca3beaaSApple OSS Distributions sizeof(as.pfras_packets));
1207*aca3beaaSApple OSS Distributions bcopy(ke->pfrke_bytes, as.pfras_bytes,
1208*aca3beaaSApple OSS Distributions sizeof(as.pfras_bytes));
1209*aca3beaaSApple OSS Distributions as.pfras_tzero = ke->pfrke_tzero;
1210*aca3beaaSApple OSS Distributions
1211*aca3beaaSApple OSS Distributions if (COPYOUT(&as, w->pfrw_astats, sizeof(as), flags)) {
1212*aca3beaaSApple OSS Distributions return EFAULT;
1213*aca3beaaSApple OSS Distributions }
1214*aca3beaaSApple OSS Distributions w->pfrw_astats += sizeof(as);
1215*aca3beaaSApple OSS Distributions }
1216*aca3beaaSApple OSS Distributions break;
1217*aca3beaaSApple OSS Distributions case PFRW_POOL_GET:
1218*aca3beaaSApple OSS Distributions if (ke->pfrke_not) {
1219*aca3beaaSApple OSS Distributions break; /* negative entries are ignored */
1220*aca3beaaSApple OSS Distributions }
1221*aca3beaaSApple OSS Distributions if (!w->pfrw_cnt--) {
1222*aca3beaaSApple OSS Distributions w->pfrw_kentry = ke;
1223*aca3beaaSApple OSS Distributions return 1; /* finish search */
1224*aca3beaaSApple OSS Distributions }
1225*aca3beaaSApple OSS Distributions break;
1226*aca3beaaSApple OSS Distributions case PFRW_DYNADDR_UPDATE:
1227*aca3beaaSApple OSS Distributions if (ke->pfrke_af == AF_INET) {
1228*aca3beaaSApple OSS Distributions if (w->pfrw_dyn->pfid_acnt4++ > 0) {
1229*aca3beaaSApple OSS Distributions break;
1230*aca3beaaSApple OSS Distributions }
1231*aca3beaaSApple OSS Distributions pfr_prepare_network(&pfr_mask, AF_INET, ke->pfrke_net);
1232*aca3beaaSApple OSS Distributions w->pfrw_dyn->pfid_addr4 = *SUNION2PF(
1233*aca3beaaSApple OSS Distributions &ke->pfrke_sa, AF_INET);
1234*aca3beaaSApple OSS Distributions w->pfrw_dyn->pfid_mask4 = *SUNION2PF(
1235*aca3beaaSApple OSS Distributions &pfr_mask, AF_INET);
1236*aca3beaaSApple OSS Distributions } else if (ke->pfrke_af == AF_INET6) {
1237*aca3beaaSApple OSS Distributions if (w->pfrw_dyn->pfid_acnt6++ > 0) {
1238*aca3beaaSApple OSS Distributions break;
1239*aca3beaaSApple OSS Distributions }
1240*aca3beaaSApple OSS Distributions pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net);
1241*aca3beaaSApple OSS Distributions w->pfrw_dyn->pfid_addr6 = *SUNION2PF(
1242*aca3beaaSApple OSS Distributions &ke->pfrke_sa, AF_INET6);
1243*aca3beaaSApple OSS Distributions w->pfrw_dyn->pfid_mask6 = *SUNION2PF(
1244*aca3beaaSApple OSS Distributions &pfr_mask, AF_INET6);
1245*aca3beaaSApple OSS Distributions }
1246*aca3beaaSApple OSS Distributions break;
1247*aca3beaaSApple OSS Distributions }
1248*aca3beaaSApple OSS Distributions return 0;
1249*aca3beaaSApple OSS Distributions }
1250*aca3beaaSApple OSS Distributions
1251*aca3beaaSApple OSS Distributions int
pfr_clr_tables(struct pfr_table * filter,int * ndel,int flags)1252*aca3beaaSApple OSS Distributions pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
1253*aca3beaaSApple OSS Distributions {
1254*aca3beaaSApple OSS Distributions struct pfr_ktableworkq workq;
1255*aca3beaaSApple OSS Distributions struct pfr_ktable *p;
1256*aca3beaaSApple OSS Distributions int xdel = 0;
1257*aca3beaaSApple OSS Distributions
1258*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1259*aca3beaaSApple OSS Distributions
1260*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
1261*aca3beaaSApple OSS Distributions PFR_FLAG_ALLRSETS);
1262*aca3beaaSApple OSS Distributions if (pfr_fix_anchor(filter->pfrt_anchor)) {
1263*aca3beaaSApple OSS Distributions return EINVAL;
1264*aca3beaaSApple OSS Distributions }
1265*aca3beaaSApple OSS Distributions if (pfr_table_count(filter, flags) < 0) {
1266*aca3beaaSApple OSS Distributions return ENOENT;
1267*aca3beaaSApple OSS Distributions }
1268*aca3beaaSApple OSS Distributions
1269*aca3beaaSApple OSS Distributions SLIST_INIT(&workq);
1270*aca3beaaSApple OSS Distributions RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1271*aca3beaaSApple OSS Distributions if (pfr_skip_table(filter, p, flags)) {
1272*aca3beaaSApple OSS Distributions continue;
1273*aca3beaaSApple OSS Distributions }
1274*aca3beaaSApple OSS Distributions if (strcmp(p->pfrkt_anchor, PF_RESERVED_ANCHOR) == 0) {
1275*aca3beaaSApple OSS Distributions continue;
1276*aca3beaaSApple OSS Distributions }
1277*aca3beaaSApple OSS Distributions if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1278*aca3beaaSApple OSS Distributions continue;
1279*aca3beaaSApple OSS Distributions }
1280*aca3beaaSApple OSS Distributions p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
1281*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1282*aca3beaaSApple OSS Distributions xdel++;
1283*aca3beaaSApple OSS Distributions }
1284*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
1285*aca3beaaSApple OSS Distributions pfr_setflags_ktables(&workq);
1286*aca3beaaSApple OSS Distributions }
1287*aca3beaaSApple OSS Distributions if (ndel != NULL) {
1288*aca3beaaSApple OSS Distributions *ndel = xdel;
1289*aca3beaaSApple OSS Distributions }
1290*aca3beaaSApple OSS Distributions return 0;
1291*aca3beaaSApple OSS Distributions }
1292*aca3beaaSApple OSS Distributions
1293*aca3beaaSApple OSS Distributions int
pfr_add_tables(user_addr_t tbl,int size,int * nadd,int flags)1294*aca3beaaSApple OSS Distributions pfr_add_tables(user_addr_t tbl, int size, int *nadd, int flags)
1295*aca3beaaSApple OSS Distributions {
1296*aca3beaaSApple OSS Distributions struct pfr_ktableworkq addq, changeq;
1297*aca3beaaSApple OSS Distributions struct pfr_ktable *p, *q, *r, key;
1298*aca3beaaSApple OSS Distributions int i, rv, xadd = 0;
1299*aca3beaaSApple OSS Distributions u_int64_t tzero = pf_calendar_time_second();
1300*aca3beaaSApple OSS Distributions
1301*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1302*aca3beaaSApple OSS Distributions
1303*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
1304*aca3beaaSApple OSS Distributions SLIST_INIT(&addq);
1305*aca3beaaSApple OSS Distributions SLIST_INIT(&changeq);
1306*aca3beaaSApple OSS Distributions for (i = 0; i < size; i++, tbl += sizeof(key.pfrkt_t)) {
1307*aca3beaaSApple OSS Distributions if (COPYIN(tbl, &key.pfrkt_t, sizeof(key.pfrkt_t), flags)) {
1308*aca3beaaSApple OSS Distributions senderr(EFAULT);
1309*aca3beaaSApple OSS Distributions }
1310*aca3beaaSApple OSS Distributions pfr_table_copyin_cleanup(&key.pfrkt_t);
1311*aca3beaaSApple OSS Distributions if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK,
1312*aca3beaaSApple OSS Distributions flags & PFR_FLAG_USERIOCTL)) {
1313*aca3beaaSApple OSS Distributions senderr(EINVAL);
1314*aca3beaaSApple OSS Distributions }
1315*aca3beaaSApple OSS Distributions key.pfrkt_flags |= PFR_TFLAG_ACTIVE;
1316*aca3beaaSApple OSS Distributions p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1317*aca3beaaSApple OSS Distributions if (p == NULL) {
1318*aca3beaaSApple OSS Distributions p = pfr_create_ktable(&key.pfrkt_t, tzero, 1);
1319*aca3beaaSApple OSS Distributions if (p == NULL) {
1320*aca3beaaSApple OSS Distributions senderr(ENOMEM);
1321*aca3beaaSApple OSS Distributions }
1322*aca3beaaSApple OSS Distributions SLIST_FOREACH(q, &addq, pfrkt_workq) {
1323*aca3beaaSApple OSS Distributions if (!pfr_ktable_compare(p, q)) {
1324*aca3beaaSApple OSS Distributions pfr_destroy_ktable(p, 0);
1325*aca3beaaSApple OSS Distributions goto _skip;
1326*aca3beaaSApple OSS Distributions }
1327*aca3beaaSApple OSS Distributions }
1328*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&addq, p, pfrkt_workq);
1329*aca3beaaSApple OSS Distributions xadd++;
1330*aca3beaaSApple OSS Distributions if (!key.pfrkt_anchor[0]) {
1331*aca3beaaSApple OSS Distributions goto _skip;
1332*aca3beaaSApple OSS Distributions }
1333*aca3beaaSApple OSS Distributions
1334*aca3beaaSApple OSS Distributions /* find or create root table */
1335*aca3beaaSApple OSS Distributions bzero(key.pfrkt_anchor, sizeof(key.pfrkt_anchor));
1336*aca3beaaSApple OSS Distributions r = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1337*aca3beaaSApple OSS Distributions if (r != NULL) {
1338*aca3beaaSApple OSS Distributions p->pfrkt_root = r;
1339*aca3beaaSApple OSS Distributions goto _skip;
1340*aca3beaaSApple OSS Distributions }
1341*aca3beaaSApple OSS Distributions SLIST_FOREACH(q, &addq, pfrkt_workq) {
1342*aca3beaaSApple OSS Distributions if (!pfr_ktable_compare(&key, q)) {
1343*aca3beaaSApple OSS Distributions p->pfrkt_root = q;
1344*aca3beaaSApple OSS Distributions goto _skip;
1345*aca3beaaSApple OSS Distributions }
1346*aca3beaaSApple OSS Distributions }
1347*aca3beaaSApple OSS Distributions key.pfrkt_flags = 0;
1348*aca3beaaSApple OSS Distributions r = pfr_create_ktable(&key.pfrkt_t, 0, 1);
1349*aca3beaaSApple OSS Distributions if (r == NULL) {
1350*aca3beaaSApple OSS Distributions senderr(ENOMEM);
1351*aca3beaaSApple OSS Distributions }
1352*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&addq, r, pfrkt_workq);
1353*aca3beaaSApple OSS Distributions p->pfrkt_root = r;
1354*aca3beaaSApple OSS Distributions } else if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1355*aca3beaaSApple OSS Distributions SLIST_FOREACH(q, &changeq, pfrkt_workq)
1356*aca3beaaSApple OSS Distributions if (!pfr_ktable_compare(&key, q)) {
1357*aca3beaaSApple OSS Distributions goto _skip;
1358*aca3beaaSApple OSS Distributions }
1359*aca3beaaSApple OSS Distributions p->pfrkt_nflags = (p->pfrkt_flags &
1360*aca3beaaSApple OSS Distributions ~PFR_TFLAG_USRMASK) | key.pfrkt_flags;
1361*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&changeq, p, pfrkt_workq);
1362*aca3beaaSApple OSS Distributions xadd++;
1363*aca3beaaSApple OSS Distributions }
1364*aca3beaaSApple OSS Distributions _skip:
1365*aca3beaaSApple OSS Distributions ;
1366*aca3beaaSApple OSS Distributions }
1367*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
1368*aca3beaaSApple OSS Distributions pfr_insert_ktables(&addq);
1369*aca3beaaSApple OSS Distributions pfr_setflags_ktables(&changeq);
1370*aca3beaaSApple OSS Distributions } else {
1371*aca3beaaSApple OSS Distributions pfr_destroy_ktables(&addq, 0);
1372*aca3beaaSApple OSS Distributions }
1373*aca3beaaSApple OSS Distributions if (nadd != NULL) {
1374*aca3beaaSApple OSS Distributions *nadd = xadd;
1375*aca3beaaSApple OSS Distributions }
1376*aca3beaaSApple OSS Distributions return 0;
1377*aca3beaaSApple OSS Distributions _bad:
1378*aca3beaaSApple OSS Distributions pfr_destroy_ktables(&addq, 0);
1379*aca3beaaSApple OSS Distributions return rv;
1380*aca3beaaSApple OSS Distributions }
1381*aca3beaaSApple OSS Distributions
1382*aca3beaaSApple OSS Distributions int
pfr_del_tables(user_addr_t tbl,int size,int * ndel,int flags)1383*aca3beaaSApple OSS Distributions pfr_del_tables(user_addr_t tbl, int size, int *ndel, int flags)
1384*aca3beaaSApple OSS Distributions {
1385*aca3beaaSApple OSS Distributions struct pfr_ktableworkq workq;
1386*aca3beaaSApple OSS Distributions struct pfr_ktable *p, *q, key;
1387*aca3beaaSApple OSS Distributions int i, xdel = 0;
1388*aca3beaaSApple OSS Distributions
1389*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1390*aca3beaaSApple OSS Distributions
1391*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
1392*aca3beaaSApple OSS Distributions SLIST_INIT(&workq);
1393*aca3beaaSApple OSS Distributions for (i = 0; i < size; i++, tbl += sizeof(key.pfrkt_t)) {
1394*aca3beaaSApple OSS Distributions if (COPYIN(tbl, &key.pfrkt_t, sizeof(key.pfrkt_t), flags)) {
1395*aca3beaaSApple OSS Distributions return EFAULT;
1396*aca3beaaSApple OSS Distributions }
1397*aca3beaaSApple OSS Distributions pfr_table_copyin_cleanup(&key.pfrkt_t);
1398*aca3beaaSApple OSS Distributions if (pfr_validate_table(&key.pfrkt_t, 0,
1399*aca3beaaSApple OSS Distributions flags & PFR_FLAG_USERIOCTL)) {
1400*aca3beaaSApple OSS Distributions return EINVAL;
1401*aca3beaaSApple OSS Distributions }
1402*aca3beaaSApple OSS Distributions p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1403*aca3beaaSApple OSS Distributions if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1404*aca3beaaSApple OSS Distributions SLIST_FOREACH(q, &workq, pfrkt_workq)
1405*aca3beaaSApple OSS Distributions if (!pfr_ktable_compare(p, q)) {
1406*aca3beaaSApple OSS Distributions goto _skip;
1407*aca3beaaSApple OSS Distributions }
1408*aca3beaaSApple OSS Distributions p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
1409*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1410*aca3beaaSApple OSS Distributions xdel++;
1411*aca3beaaSApple OSS Distributions }
1412*aca3beaaSApple OSS Distributions _skip:
1413*aca3beaaSApple OSS Distributions ;
1414*aca3beaaSApple OSS Distributions }
1415*aca3beaaSApple OSS Distributions
1416*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
1417*aca3beaaSApple OSS Distributions pfr_setflags_ktables(&workq);
1418*aca3beaaSApple OSS Distributions }
1419*aca3beaaSApple OSS Distributions if (ndel != NULL) {
1420*aca3beaaSApple OSS Distributions *ndel = xdel;
1421*aca3beaaSApple OSS Distributions }
1422*aca3beaaSApple OSS Distributions return 0;
1423*aca3beaaSApple OSS Distributions }
1424*aca3beaaSApple OSS Distributions
1425*aca3beaaSApple OSS Distributions int
pfr_get_tables(struct pfr_table * filter,user_addr_t tbl,int * size,int flags)1426*aca3beaaSApple OSS Distributions pfr_get_tables(struct pfr_table *filter, user_addr_t tbl, int *size,
1427*aca3beaaSApple OSS Distributions int flags)
1428*aca3beaaSApple OSS Distributions {
1429*aca3beaaSApple OSS Distributions struct pfr_ktable *p;
1430*aca3beaaSApple OSS Distributions int n, nn;
1431*aca3beaaSApple OSS Distributions
1432*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS);
1433*aca3beaaSApple OSS Distributions if (pfr_fix_anchor(filter->pfrt_anchor)) {
1434*aca3beaaSApple OSS Distributions return EINVAL;
1435*aca3beaaSApple OSS Distributions }
1436*aca3beaaSApple OSS Distributions n = nn = pfr_table_count(filter, flags);
1437*aca3beaaSApple OSS Distributions if (n < 0) {
1438*aca3beaaSApple OSS Distributions return ENOENT;
1439*aca3beaaSApple OSS Distributions }
1440*aca3beaaSApple OSS Distributions if (n > *size) {
1441*aca3beaaSApple OSS Distributions *size = n;
1442*aca3beaaSApple OSS Distributions return 0;
1443*aca3beaaSApple OSS Distributions }
1444*aca3beaaSApple OSS Distributions RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1445*aca3beaaSApple OSS Distributions if (pfr_skip_table(filter, p, flags)) {
1446*aca3beaaSApple OSS Distributions continue;
1447*aca3beaaSApple OSS Distributions }
1448*aca3beaaSApple OSS Distributions if (n-- <= 0) {
1449*aca3beaaSApple OSS Distributions continue;
1450*aca3beaaSApple OSS Distributions }
1451*aca3beaaSApple OSS Distributions if (COPYOUT(&p->pfrkt_t, tbl, sizeof(p->pfrkt_t), flags)) {
1452*aca3beaaSApple OSS Distributions return EFAULT;
1453*aca3beaaSApple OSS Distributions }
1454*aca3beaaSApple OSS Distributions tbl += sizeof(p->pfrkt_t);
1455*aca3beaaSApple OSS Distributions }
1456*aca3beaaSApple OSS Distributions if (n) {
1457*aca3beaaSApple OSS Distributions printf("pfr_get_tables: corruption detected (%d).\n", n);
1458*aca3beaaSApple OSS Distributions return ENOTTY;
1459*aca3beaaSApple OSS Distributions }
1460*aca3beaaSApple OSS Distributions *size = nn;
1461*aca3beaaSApple OSS Distributions return 0;
1462*aca3beaaSApple OSS Distributions }
1463*aca3beaaSApple OSS Distributions
1464*aca3beaaSApple OSS Distributions int
pfr_get_tstats(struct pfr_table * filter,user_addr_t tbl,int * size,int flags)1465*aca3beaaSApple OSS Distributions pfr_get_tstats(struct pfr_table *filter, user_addr_t tbl, int *size,
1466*aca3beaaSApple OSS Distributions int flags)
1467*aca3beaaSApple OSS Distributions {
1468*aca3beaaSApple OSS Distributions struct pfr_ktable *p;
1469*aca3beaaSApple OSS Distributions struct pfr_ktableworkq workq;
1470*aca3beaaSApple OSS Distributions int n, nn;
1471*aca3beaaSApple OSS Distributions u_int64_t tzero = pf_calendar_time_second();
1472*aca3beaaSApple OSS Distributions
1473*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1474*aca3beaaSApple OSS Distributions
1475*aca3beaaSApple OSS Distributions /* XXX PFR_FLAG_CLSTATS disabled */
1476*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_ALLRSETS);
1477*aca3beaaSApple OSS Distributions if (pfr_fix_anchor(filter->pfrt_anchor)) {
1478*aca3beaaSApple OSS Distributions return EINVAL;
1479*aca3beaaSApple OSS Distributions }
1480*aca3beaaSApple OSS Distributions n = nn = pfr_table_count(filter, flags);
1481*aca3beaaSApple OSS Distributions if (n < 0) {
1482*aca3beaaSApple OSS Distributions return ENOENT;
1483*aca3beaaSApple OSS Distributions }
1484*aca3beaaSApple OSS Distributions if (n > *size) {
1485*aca3beaaSApple OSS Distributions *size = n;
1486*aca3beaaSApple OSS Distributions return 0;
1487*aca3beaaSApple OSS Distributions }
1488*aca3beaaSApple OSS Distributions SLIST_INIT(&workq);
1489*aca3beaaSApple OSS Distributions RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1490*aca3beaaSApple OSS Distributions if (pfr_skip_table(filter, p, flags)) {
1491*aca3beaaSApple OSS Distributions continue;
1492*aca3beaaSApple OSS Distributions }
1493*aca3beaaSApple OSS Distributions if (n-- <= 0) {
1494*aca3beaaSApple OSS Distributions continue;
1495*aca3beaaSApple OSS Distributions }
1496*aca3beaaSApple OSS Distributions if (COPYOUT(&p->pfrkt_ts, tbl, sizeof(p->pfrkt_ts), flags)) {
1497*aca3beaaSApple OSS Distributions return EFAULT;
1498*aca3beaaSApple OSS Distributions }
1499*aca3beaaSApple OSS Distributions tbl += sizeof(p->pfrkt_ts);
1500*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1501*aca3beaaSApple OSS Distributions }
1502*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_CLSTATS) {
1503*aca3beaaSApple OSS Distributions pfr_clstats_ktables(&workq, tzero,
1504*aca3beaaSApple OSS Distributions flags & PFR_FLAG_ADDRSTOO);
1505*aca3beaaSApple OSS Distributions }
1506*aca3beaaSApple OSS Distributions if (n) {
1507*aca3beaaSApple OSS Distributions printf("pfr_get_tstats: corruption detected (%d).\n", n);
1508*aca3beaaSApple OSS Distributions return ENOTTY;
1509*aca3beaaSApple OSS Distributions }
1510*aca3beaaSApple OSS Distributions *size = nn;
1511*aca3beaaSApple OSS Distributions return 0;
1512*aca3beaaSApple OSS Distributions }
1513*aca3beaaSApple OSS Distributions
1514*aca3beaaSApple OSS Distributions int
pfr_clr_tstats(user_addr_t tbl,int size,int * nzero,int flags)1515*aca3beaaSApple OSS Distributions pfr_clr_tstats(user_addr_t tbl, int size, int *nzero, int flags)
1516*aca3beaaSApple OSS Distributions {
1517*aca3beaaSApple OSS Distributions struct pfr_ktableworkq workq;
1518*aca3beaaSApple OSS Distributions struct pfr_ktable *p, key;
1519*aca3beaaSApple OSS Distributions int i, xzero = 0;
1520*aca3beaaSApple OSS Distributions u_int64_t tzero = pf_calendar_time_second();
1521*aca3beaaSApple OSS Distributions
1522*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1523*aca3beaaSApple OSS Distributions
1524*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY |
1525*aca3beaaSApple OSS Distributions PFR_FLAG_ADDRSTOO);
1526*aca3beaaSApple OSS Distributions SLIST_INIT(&workq);
1527*aca3beaaSApple OSS Distributions for (i = 0; i < size; i++, tbl += sizeof(key.pfrkt_t)) {
1528*aca3beaaSApple OSS Distributions if (COPYIN(tbl, &key.pfrkt_t, sizeof(key.pfrkt_t), flags)) {
1529*aca3beaaSApple OSS Distributions return EFAULT;
1530*aca3beaaSApple OSS Distributions }
1531*aca3beaaSApple OSS Distributions pfr_table_copyin_cleanup(&key.pfrkt_t);
1532*aca3beaaSApple OSS Distributions if (pfr_validate_table(&key.pfrkt_t, 0, 0)) {
1533*aca3beaaSApple OSS Distributions return EINVAL;
1534*aca3beaaSApple OSS Distributions }
1535*aca3beaaSApple OSS Distributions p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1536*aca3beaaSApple OSS Distributions if (p != NULL) {
1537*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1538*aca3beaaSApple OSS Distributions xzero++;
1539*aca3beaaSApple OSS Distributions }
1540*aca3beaaSApple OSS Distributions }
1541*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
1542*aca3beaaSApple OSS Distributions pfr_clstats_ktables(&workq, tzero, flags & PFR_FLAG_ADDRSTOO);
1543*aca3beaaSApple OSS Distributions }
1544*aca3beaaSApple OSS Distributions if (nzero != NULL) {
1545*aca3beaaSApple OSS Distributions *nzero = xzero;
1546*aca3beaaSApple OSS Distributions }
1547*aca3beaaSApple OSS Distributions return 0;
1548*aca3beaaSApple OSS Distributions }
1549*aca3beaaSApple OSS Distributions
1550*aca3beaaSApple OSS Distributions int
pfr_set_tflags(user_addr_t tbl,int size,int setflag,int clrflag,int * nchange,int * ndel,int flags)1551*aca3beaaSApple OSS Distributions pfr_set_tflags(user_addr_t tbl, int size, int setflag, int clrflag,
1552*aca3beaaSApple OSS Distributions int *nchange, int *ndel, int flags)
1553*aca3beaaSApple OSS Distributions {
1554*aca3beaaSApple OSS Distributions struct pfr_ktableworkq workq;
1555*aca3beaaSApple OSS Distributions struct pfr_ktable *p, *q, key;
1556*aca3beaaSApple OSS Distributions int i, xchange = 0, xdel = 0;
1557*aca3beaaSApple OSS Distributions
1558*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1559*aca3beaaSApple OSS Distributions
1560*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
1561*aca3beaaSApple OSS Distributions if ((setflag & ~PFR_TFLAG_USRMASK) ||
1562*aca3beaaSApple OSS Distributions (clrflag & ~PFR_TFLAG_USRMASK) ||
1563*aca3beaaSApple OSS Distributions (setflag & clrflag)) {
1564*aca3beaaSApple OSS Distributions return EINVAL;
1565*aca3beaaSApple OSS Distributions }
1566*aca3beaaSApple OSS Distributions SLIST_INIT(&workq);
1567*aca3beaaSApple OSS Distributions for (i = 0; i < size; i++, tbl += sizeof(key.pfrkt_t)) {
1568*aca3beaaSApple OSS Distributions if (COPYIN(tbl, &key.pfrkt_t, sizeof(key.pfrkt_t), flags)) {
1569*aca3beaaSApple OSS Distributions return EFAULT;
1570*aca3beaaSApple OSS Distributions }
1571*aca3beaaSApple OSS Distributions pfr_table_copyin_cleanup(&key.pfrkt_t);
1572*aca3beaaSApple OSS Distributions if (pfr_validate_table(&key.pfrkt_t, 0,
1573*aca3beaaSApple OSS Distributions flags & PFR_FLAG_USERIOCTL)) {
1574*aca3beaaSApple OSS Distributions return EINVAL;
1575*aca3beaaSApple OSS Distributions }
1576*aca3beaaSApple OSS Distributions p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1577*aca3beaaSApple OSS Distributions if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1578*aca3beaaSApple OSS Distributions p->pfrkt_nflags = (p->pfrkt_flags | setflag) &
1579*aca3beaaSApple OSS Distributions ~clrflag;
1580*aca3beaaSApple OSS Distributions if (p->pfrkt_nflags == p->pfrkt_flags) {
1581*aca3beaaSApple OSS Distributions goto _skip;
1582*aca3beaaSApple OSS Distributions }
1583*aca3beaaSApple OSS Distributions SLIST_FOREACH(q, &workq, pfrkt_workq)
1584*aca3beaaSApple OSS Distributions if (!pfr_ktable_compare(p, q)) {
1585*aca3beaaSApple OSS Distributions goto _skip;
1586*aca3beaaSApple OSS Distributions }
1587*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1588*aca3beaaSApple OSS Distributions if ((p->pfrkt_flags & PFR_TFLAG_PERSIST) &&
1589*aca3beaaSApple OSS Distributions (clrflag & PFR_TFLAG_PERSIST) &&
1590*aca3beaaSApple OSS Distributions !(p->pfrkt_flags & PFR_TFLAG_REFERENCED)) {
1591*aca3beaaSApple OSS Distributions xdel++;
1592*aca3beaaSApple OSS Distributions } else {
1593*aca3beaaSApple OSS Distributions xchange++;
1594*aca3beaaSApple OSS Distributions }
1595*aca3beaaSApple OSS Distributions }
1596*aca3beaaSApple OSS Distributions _skip:
1597*aca3beaaSApple OSS Distributions ;
1598*aca3beaaSApple OSS Distributions }
1599*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
1600*aca3beaaSApple OSS Distributions pfr_setflags_ktables(&workq);
1601*aca3beaaSApple OSS Distributions }
1602*aca3beaaSApple OSS Distributions if (nchange != NULL) {
1603*aca3beaaSApple OSS Distributions *nchange = xchange;
1604*aca3beaaSApple OSS Distributions }
1605*aca3beaaSApple OSS Distributions if (ndel != NULL) {
1606*aca3beaaSApple OSS Distributions *ndel = xdel;
1607*aca3beaaSApple OSS Distributions }
1608*aca3beaaSApple OSS Distributions return 0;
1609*aca3beaaSApple OSS Distributions }
1610*aca3beaaSApple OSS Distributions
1611*aca3beaaSApple OSS Distributions int
pfr_ina_begin(struct pfr_table * trs,u_int32_t * ticket,int * ndel,int flags)1612*aca3beaaSApple OSS Distributions pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags)
1613*aca3beaaSApple OSS Distributions {
1614*aca3beaaSApple OSS Distributions struct pfr_ktableworkq workq;
1615*aca3beaaSApple OSS Distributions struct pfr_ktable *p;
1616*aca3beaaSApple OSS Distributions struct pf_ruleset *rs;
1617*aca3beaaSApple OSS Distributions int xdel = 0;
1618*aca3beaaSApple OSS Distributions
1619*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1620*aca3beaaSApple OSS Distributions
1621*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1622*aca3beaaSApple OSS Distributions rs = pf_find_or_create_ruleset(trs->pfrt_anchor);
1623*aca3beaaSApple OSS Distributions if (rs == NULL) {
1624*aca3beaaSApple OSS Distributions return ENOMEM;
1625*aca3beaaSApple OSS Distributions }
1626*aca3beaaSApple OSS Distributions SLIST_INIT(&workq);
1627*aca3beaaSApple OSS Distributions RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1628*aca3beaaSApple OSS Distributions if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
1629*aca3beaaSApple OSS Distributions pfr_skip_table(trs, p, 0)) {
1630*aca3beaaSApple OSS Distributions continue;
1631*aca3beaaSApple OSS Distributions }
1632*aca3beaaSApple OSS Distributions p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
1633*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1634*aca3beaaSApple OSS Distributions xdel++;
1635*aca3beaaSApple OSS Distributions }
1636*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
1637*aca3beaaSApple OSS Distributions pfr_setflags_ktables(&workq);
1638*aca3beaaSApple OSS Distributions if (ticket != NULL) {
1639*aca3beaaSApple OSS Distributions *ticket = ++rs->tticket;
1640*aca3beaaSApple OSS Distributions }
1641*aca3beaaSApple OSS Distributions rs->topen = 1;
1642*aca3beaaSApple OSS Distributions } else {
1643*aca3beaaSApple OSS Distributions pf_release_ruleset(rs);
1644*aca3beaaSApple OSS Distributions }
1645*aca3beaaSApple OSS Distributions if (ndel != NULL) {
1646*aca3beaaSApple OSS Distributions *ndel = xdel;
1647*aca3beaaSApple OSS Distributions }
1648*aca3beaaSApple OSS Distributions return 0;
1649*aca3beaaSApple OSS Distributions }
1650*aca3beaaSApple OSS Distributions
1651*aca3beaaSApple OSS Distributions int
pfr_ina_define(struct pfr_table * tbl,user_addr_t addr,int size,int * nadd,int * naddr,u_int32_t ticket,int flags)1652*aca3beaaSApple OSS Distributions pfr_ina_define(struct pfr_table *tbl, user_addr_t addr, int size,
1653*aca3beaaSApple OSS Distributions int *nadd, int *naddr, u_int32_t ticket, int flags)
1654*aca3beaaSApple OSS Distributions {
1655*aca3beaaSApple OSS Distributions struct pfr_ktableworkq tableq;
1656*aca3beaaSApple OSS Distributions struct pfr_kentryworkq addrq;
1657*aca3beaaSApple OSS Distributions struct pfr_ktable *kt, *rt, *shadow, key;
1658*aca3beaaSApple OSS Distributions struct pfr_kentry *p;
1659*aca3beaaSApple OSS Distributions struct pfr_addr ad;
1660*aca3beaaSApple OSS Distributions struct pf_ruleset *rs;
1661*aca3beaaSApple OSS Distributions int i, rv, xadd = 0, xaddr = 0;
1662*aca3beaaSApple OSS Distributions
1663*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1664*aca3beaaSApple OSS Distributions
1665*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO);
1666*aca3beaaSApple OSS Distributions if (size && !(flags & PFR_FLAG_ADDRSTOO)) {
1667*aca3beaaSApple OSS Distributions return EINVAL;
1668*aca3beaaSApple OSS Distributions }
1669*aca3beaaSApple OSS Distributions if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
1670*aca3beaaSApple OSS Distributions flags & PFR_FLAG_USERIOCTL)) {
1671*aca3beaaSApple OSS Distributions return EINVAL;
1672*aca3beaaSApple OSS Distributions }
1673*aca3beaaSApple OSS Distributions rs = pf_find_ruleset(tbl->pfrt_anchor);
1674*aca3beaaSApple OSS Distributions if (rs == NULL || !rs->topen || ticket != rs->tticket) {
1675*aca3beaaSApple OSS Distributions return EBUSY;
1676*aca3beaaSApple OSS Distributions }
1677*aca3beaaSApple OSS Distributions pf_release_ruleset(rs);
1678*aca3beaaSApple OSS Distributions rs = NULL;
1679*aca3beaaSApple OSS Distributions tbl->pfrt_flags |= PFR_TFLAG_INACTIVE;
1680*aca3beaaSApple OSS Distributions SLIST_INIT(&tableq);
1681*aca3beaaSApple OSS Distributions kt = RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)(void *)tbl);
1682*aca3beaaSApple OSS Distributions if (kt == NULL) {
1683*aca3beaaSApple OSS Distributions kt = pfr_create_ktable(tbl, 0, 1);
1684*aca3beaaSApple OSS Distributions if (kt == NULL) {
1685*aca3beaaSApple OSS Distributions return ENOMEM;
1686*aca3beaaSApple OSS Distributions }
1687*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&tableq, kt, pfrkt_workq);
1688*aca3beaaSApple OSS Distributions xadd++;
1689*aca3beaaSApple OSS Distributions if (!tbl->pfrt_anchor[0]) {
1690*aca3beaaSApple OSS Distributions goto _skip;
1691*aca3beaaSApple OSS Distributions }
1692*aca3beaaSApple OSS Distributions
1693*aca3beaaSApple OSS Distributions /* find or create root table */
1694*aca3beaaSApple OSS Distributions bzero(&key, sizeof(key));
1695*aca3beaaSApple OSS Distributions strlcpy(key.pfrkt_name, tbl->pfrt_name,
1696*aca3beaaSApple OSS Distributions sizeof(key.pfrkt_name));
1697*aca3beaaSApple OSS Distributions rt = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1698*aca3beaaSApple OSS Distributions if (rt != NULL) {
1699*aca3beaaSApple OSS Distributions kt->pfrkt_root = rt;
1700*aca3beaaSApple OSS Distributions goto _skip;
1701*aca3beaaSApple OSS Distributions }
1702*aca3beaaSApple OSS Distributions rt = pfr_create_ktable(&key.pfrkt_t, 0, 1);
1703*aca3beaaSApple OSS Distributions if (rt == NULL) {
1704*aca3beaaSApple OSS Distributions pfr_destroy_ktables(&tableq, 0);
1705*aca3beaaSApple OSS Distributions return ENOMEM;
1706*aca3beaaSApple OSS Distributions }
1707*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&tableq, rt, pfrkt_workq);
1708*aca3beaaSApple OSS Distributions kt->pfrkt_root = rt;
1709*aca3beaaSApple OSS Distributions } else if (!(kt->pfrkt_flags & PFR_TFLAG_INACTIVE)) {
1710*aca3beaaSApple OSS Distributions xadd++;
1711*aca3beaaSApple OSS Distributions }
1712*aca3beaaSApple OSS Distributions _skip:
1713*aca3beaaSApple OSS Distributions shadow = pfr_create_ktable(tbl, 0, 0);
1714*aca3beaaSApple OSS Distributions if (shadow == NULL) {
1715*aca3beaaSApple OSS Distributions pfr_destroy_ktables(&tableq, 0);
1716*aca3beaaSApple OSS Distributions return ENOMEM;
1717*aca3beaaSApple OSS Distributions }
1718*aca3beaaSApple OSS Distributions SLIST_INIT(&addrq);
1719*aca3beaaSApple OSS Distributions for (i = 0; i < size; i++, addr += sizeof(ad)) {
1720*aca3beaaSApple OSS Distributions if (COPYIN(addr, &ad, sizeof(ad), flags)) {
1721*aca3beaaSApple OSS Distributions senderr(EFAULT);
1722*aca3beaaSApple OSS Distributions }
1723*aca3beaaSApple OSS Distributions if (pfr_validate_addr(&ad)) {
1724*aca3beaaSApple OSS Distributions senderr(EINVAL);
1725*aca3beaaSApple OSS Distributions }
1726*aca3beaaSApple OSS Distributions if (pfr_lookup_addr(shadow, &ad, 1) != NULL) {
1727*aca3beaaSApple OSS Distributions continue;
1728*aca3beaaSApple OSS Distributions }
1729*aca3beaaSApple OSS Distributions p = pfr_create_kentry(&ad, FALSE);
1730*aca3beaaSApple OSS Distributions if (p == NULL) {
1731*aca3beaaSApple OSS Distributions senderr(ENOMEM);
1732*aca3beaaSApple OSS Distributions }
1733*aca3beaaSApple OSS Distributions if (pfr_route_kentry(shadow, p)) {
1734*aca3beaaSApple OSS Distributions pfr_destroy_kentry(p);
1735*aca3beaaSApple OSS Distributions continue;
1736*aca3beaaSApple OSS Distributions }
1737*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&addrq, p, pfrke_workq);
1738*aca3beaaSApple OSS Distributions xaddr++;
1739*aca3beaaSApple OSS Distributions }
1740*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
1741*aca3beaaSApple OSS Distributions if (kt->pfrkt_shadow != NULL) {
1742*aca3beaaSApple OSS Distributions pfr_destroy_ktable(kt->pfrkt_shadow, 1);
1743*aca3beaaSApple OSS Distributions }
1744*aca3beaaSApple OSS Distributions kt->pfrkt_flags |= PFR_TFLAG_INACTIVE;
1745*aca3beaaSApple OSS Distributions pfr_insert_ktables(&tableq);
1746*aca3beaaSApple OSS Distributions shadow->pfrkt_cnt = (flags & PFR_FLAG_ADDRSTOO) ?
1747*aca3beaaSApple OSS Distributions xaddr : NO_ADDRESSES;
1748*aca3beaaSApple OSS Distributions kt->pfrkt_shadow = shadow;
1749*aca3beaaSApple OSS Distributions } else {
1750*aca3beaaSApple OSS Distributions pfr_clean_node_mask(shadow, &addrq);
1751*aca3beaaSApple OSS Distributions pfr_destroy_ktable(shadow, 0);
1752*aca3beaaSApple OSS Distributions pfr_destroy_ktables(&tableq, 0);
1753*aca3beaaSApple OSS Distributions pfr_destroy_kentries(&addrq);
1754*aca3beaaSApple OSS Distributions }
1755*aca3beaaSApple OSS Distributions if (nadd != NULL) {
1756*aca3beaaSApple OSS Distributions *nadd = xadd;
1757*aca3beaaSApple OSS Distributions }
1758*aca3beaaSApple OSS Distributions if (naddr != NULL) {
1759*aca3beaaSApple OSS Distributions *naddr = xaddr;
1760*aca3beaaSApple OSS Distributions }
1761*aca3beaaSApple OSS Distributions return 0;
1762*aca3beaaSApple OSS Distributions _bad:
1763*aca3beaaSApple OSS Distributions pfr_destroy_ktable(shadow, 0);
1764*aca3beaaSApple OSS Distributions pfr_destroy_ktables(&tableq, 0);
1765*aca3beaaSApple OSS Distributions pfr_destroy_kentries(&addrq);
1766*aca3beaaSApple OSS Distributions return rv;
1767*aca3beaaSApple OSS Distributions }
1768*aca3beaaSApple OSS Distributions
1769*aca3beaaSApple OSS Distributions int
pfr_ina_rollback(struct pfr_table * trs,u_int32_t ticket,int * ndel,int flags)1770*aca3beaaSApple OSS Distributions pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
1771*aca3beaaSApple OSS Distributions {
1772*aca3beaaSApple OSS Distributions struct pfr_ktableworkq workq;
1773*aca3beaaSApple OSS Distributions struct pfr_ktable *p;
1774*aca3beaaSApple OSS Distributions struct pf_ruleset *rs;
1775*aca3beaaSApple OSS Distributions int xdel = 0;
1776*aca3beaaSApple OSS Distributions
1777*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1778*aca3beaaSApple OSS Distributions
1779*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1780*aca3beaaSApple OSS Distributions rs = pf_find_ruleset(trs->pfrt_anchor);
1781*aca3beaaSApple OSS Distributions if (rs == NULL || !rs->topen || ticket != rs->tticket) {
1782*aca3beaaSApple OSS Distributions goto done;
1783*aca3beaaSApple OSS Distributions }
1784*aca3beaaSApple OSS Distributions SLIST_INIT(&workq);
1785*aca3beaaSApple OSS Distributions RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1786*aca3beaaSApple OSS Distributions if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
1787*aca3beaaSApple OSS Distributions pfr_skip_table(trs, p, 0)) {
1788*aca3beaaSApple OSS Distributions continue;
1789*aca3beaaSApple OSS Distributions }
1790*aca3beaaSApple OSS Distributions p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
1791*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1792*aca3beaaSApple OSS Distributions xdel++;
1793*aca3beaaSApple OSS Distributions }
1794*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
1795*aca3beaaSApple OSS Distributions pfr_setflags_ktables(&workq);
1796*aca3beaaSApple OSS Distributions rs->topen = 0;
1797*aca3beaaSApple OSS Distributions }
1798*aca3beaaSApple OSS Distributions if (ndel != NULL) {
1799*aca3beaaSApple OSS Distributions *ndel = xdel;
1800*aca3beaaSApple OSS Distributions }
1801*aca3beaaSApple OSS Distributions done:
1802*aca3beaaSApple OSS Distributions if (rs) {
1803*aca3beaaSApple OSS Distributions pf_release_ruleset(rs);
1804*aca3beaaSApple OSS Distributions rs = NULL;
1805*aca3beaaSApple OSS Distributions }
1806*aca3beaaSApple OSS Distributions return 0;
1807*aca3beaaSApple OSS Distributions }
1808*aca3beaaSApple OSS Distributions
1809*aca3beaaSApple OSS Distributions int
pfr_ina_commit(struct pfr_table * trs,u_int32_t ticket,int * nadd,int * nchange,int flags)1810*aca3beaaSApple OSS Distributions pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
1811*aca3beaaSApple OSS Distributions int *nchange, int flags)
1812*aca3beaaSApple OSS Distributions {
1813*aca3beaaSApple OSS Distributions struct pfr_ktable *p, *q;
1814*aca3beaaSApple OSS Distributions struct pfr_ktableworkq workq;
1815*aca3beaaSApple OSS Distributions struct pf_ruleset *rs;
1816*aca3beaaSApple OSS Distributions int xadd = 0, xchange = 0;
1817*aca3beaaSApple OSS Distributions u_int64_t tzero = pf_calendar_time_second();
1818*aca3beaaSApple OSS Distributions int err = 0;
1819*aca3beaaSApple OSS Distributions
1820*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1821*aca3beaaSApple OSS Distributions
1822*aca3beaaSApple OSS Distributions ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY);
1823*aca3beaaSApple OSS Distributions rs = pf_find_ruleset(trs->pfrt_anchor);
1824*aca3beaaSApple OSS Distributions if (rs == NULL || !rs->topen || ticket != rs->tticket) {
1825*aca3beaaSApple OSS Distributions err = EBUSY;
1826*aca3beaaSApple OSS Distributions goto done;
1827*aca3beaaSApple OSS Distributions }
1828*aca3beaaSApple OSS Distributions
1829*aca3beaaSApple OSS Distributions SLIST_INIT(&workq);
1830*aca3beaaSApple OSS Distributions RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1831*aca3beaaSApple OSS Distributions if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
1832*aca3beaaSApple OSS Distributions pfr_skip_table(trs, p, 0)) {
1833*aca3beaaSApple OSS Distributions continue;
1834*aca3beaaSApple OSS Distributions }
1835*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1836*aca3beaaSApple OSS Distributions if (p->pfrkt_flags & PFR_TFLAG_ACTIVE) {
1837*aca3beaaSApple OSS Distributions xchange++;
1838*aca3beaaSApple OSS Distributions } else {
1839*aca3beaaSApple OSS Distributions xadd++;
1840*aca3beaaSApple OSS Distributions }
1841*aca3beaaSApple OSS Distributions }
1842*aca3beaaSApple OSS Distributions
1843*aca3beaaSApple OSS Distributions if (!(flags & PFR_FLAG_DUMMY)) {
1844*aca3beaaSApple OSS Distributions for (p = SLIST_FIRST(&workq); p != NULL; p = q) {
1845*aca3beaaSApple OSS Distributions q = SLIST_NEXT(p, pfrkt_workq);
1846*aca3beaaSApple OSS Distributions pfr_commit_ktable(p, tzero);
1847*aca3beaaSApple OSS Distributions }
1848*aca3beaaSApple OSS Distributions rs->topen = 0;
1849*aca3beaaSApple OSS Distributions }
1850*aca3beaaSApple OSS Distributions if (nadd != NULL) {
1851*aca3beaaSApple OSS Distributions *nadd = xadd;
1852*aca3beaaSApple OSS Distributions }
1853*aca3beaaSApple OSS Distributions if (nchange != NULL) {
1854*aca3beaaSApple OSS Distributions *nchange = xchange;
1855*aca3beaaSApple OSS Distributions }
1856*aca3beaaSApple OSS Distributions
1857*aca3beaaSApple OSS Distributions done:
1858*aca3beaaSApple OSS Distributions if (rs != NULL) {
1859*aca3beaaSApple OSS Distributions pf_release_ruleset(rs);
1860*aca3beaaSApple OSS Distributions rs = NULL;
1861*aca3beaaSApple OSS Distributions }
1862*aca3beaaSApple OSS Distributions return err;
1863*aca3beaaSApple OSS Distributions }
1864*aca3beaaSApple OSS Distributions
1865*aca3beaaSApple OSS Distributions static void
pfr_commit_ktable(struct pfr_ktable * kt,u_int64_t tzero)1866*aca3beaaSApple OSS Distributions pfr_commit_ktable(struct pfr_ktable *kt, u_int64_t tzero)
1867*aca3beaaSApple OSS Distributions {
1868*aca3beaaSApple OSS Distributions struct pfr_ktable *shadow = kt->pfrkt_shadow;
1869*aca3beaaSApple OSS Distributions int nflags;
1870*aca3beaaSApple OSS Distributions
1871*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
1872*aca3beaaSApple OSS Distributions
1873*aca3beaaSApple OSS Distributions if (shadow->pfrkt_cnt == NO_ADDRESSES) {
1874*aca3beaaSApple OSS Distributions if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1875*aca3beaaSApple OSS Distributions pfr_clstats_ktable(kt, tzero, 1);
1876*aca3beaaSApple OSS Distributions }
1877*aca3beaaSApple OSS Distributions } else if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) {
1878*aca3beaaSApple OSS Distributions /* kt might contain addresses */
1879*aca3beaaSApple OSS Distributions struct pfr_kentryworkq addrq, addq, changeq, delq, garbageq;
1880*aca3beaaSApple OSS Distributions struct pfr_kentry *p, *q, *next;
1881*aca3beaaSApple OSS Distributions struct pfr_addr ad;
1882*aca3beaaSApple OSS Distributions
1883*aca3beaaSApple OSS Distributions pfr_enqueue_addrs(shadow, &addrq, NULL, 0);
1884*aca3beaaSApple OSS Distributions pfr_mark_addrs(kt);
1885*aca3beaaSApple OSS Distributions SLIST_INIT(&addq);
1886*aca3beaaSApple OSS Distributions SLIST_INIT(&changeq);
1887*aca3beaaSApple OSS Distributions SLIST_INIT(&delq);
1888*aca3beaaSApple OSS Distributions SLIST_INIT(&garbageq);
1889*aca3beaaSApple OSS Distributions pfr_clean_node_mask(shadow, &addrq);
1890*aca3beaaSApple OSS Distributions for (p = SLIST_FIRST(&addrq); p != NULL; p = next) {
1891*aca3beaaSApple OSS Distributions next = SLIST_NEXT(p, pfrke_workq); /* XXX */
1892*aca3beaaSApple OSS Distributions pfr_copyout_addr(&ad, p);
1893*aca3beaaSApple OSS Distributions q = pfr_lookup_addr(kt, &ad, 1);
1894*aca3beaaSApple OSS Distributions if (q != NULL) {
1895*aca3beaaSApple OSS Distributions if (q->pfrke_not != p->pfrke_not) {
1896*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&changeq, q,
1897*aca3beaaSApple OSS Distributions pfrke_workq);
1898*aca3beaaSApple OSS Distributions }
1899*aca3beaaSApple OSS Distributions q->pfrke_mark = 1;
1900*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&garbageq, p, pfrke_workq);
1901*aca3beaaSApple OSS Distributions } else {
1902*aca3beaaSApple OSS Distributions p->pfrke_tzero = tzero;
1903*aca3beaaSApple OSS Distributions SLIST_INSERT_HEAD(&addq, p, pfrke_workq);
1904*aca3beaaSApple OSS Distributions }
1905*aca3beaaSApple OSS Distributions }
1906*aca3beaaSApple OSS Distributions pfr_enqueue_addrs(kt, &delq, NULL, ENQUEUE_UNMARKED_ONLY);
1907*aca3beaaSApple OSS Distributions pfr_insert_kentries(kt, &addq, tzero);
1908*aca3beaaSApple OSS Distributions pfr_remove_kentries(kt, &delq);
1909*aca3beaaSApple OSS Distributions pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG);
1910*aca3beaaSApple OSS Distributions pfr_destroy_kentries(&garbageq);
1911*aca3beaaSApple OSS Distributions } else {
1912*aca3beaaSApple OSS Distributions /* kt cannot contain addresses */
1913*aca3beaaSApple OSS Distributions SWAP(struct radix_node_head *, kt->pfrkt_ip4,
1914*aca3beaaSApple OSS Distributions shadow->pfrkt_ip4);
1915*aca3beaaSApple OSS Distributions SWAP(struct radix_node_head *, kt->pfrkt_ip6,
1916*aca3beaaSApple OSS Distributions shadow->pfrkt_ip6);
1917*aca3beaaSApple OSS Distributions SWAP(int, kt->pfrkt_cnt, shadow->pfrkt_cnt);
1918*aca3beaaSApple OSS Distributions pfr_clstats_ktable(kt, tzero, 1);
1919*aca3beaaSApple OSS Distributions }
1920*aca3beaaSApple OSS Distributions nflags = ((shadow->pfrkt_flags & PFR_TFLAG_USRMASK) |
1921*aca3beaaSApple OSS Distributions (kt->pfrkt_flags & PFR_TFLAG_SETMASK) | PFR_TFLAG_ACTIVE) &
1922*aca3beaaSApple OSS Distributions ~PFR_TFLAG_INACTIVE;
1923*aca3beaaSApple OSS Distributions pfr_destroy_ktable(shadow, 0);
1924*aca3beaaSApple OSS Distributions kt->pfrkt_shadow = NULL;
1925*aca3beaaSApple OSS Distributions pfr_setflags_ktable(kt, nflags);
1926*aca3beaaSApple OSS Distributions }
1927*aca3beaaSApple OSS Distributions
1928*aca3beaaSApple OSS Distributions void
pfr_table_copyin_cleanup(struct pfr_table * tbl)1929*aca3beaaSApple OSS Distributions pfr_table_copyin_cleanup(struct pfr_table *tbl)
1930*aca3beaaSApple OSS Distributions {
1931*aca3beaaSApple OSS Distributions tbl->pfrt_anchor[sizeof(tbl->pfrt_anchor) - 1] = '\0';
1932*aca3beaaSApple OSS Distributions tbl->pfrt_name[sizeof(tbl->pfrt_name) - 1] = '\0';
1933*aca3beaaSApple OSS Distributions }
1934*aca3beaaSApple OSS Distributions
1935*aca3beaaSApple OSS Distributions static int
pfr_validate_table(struct pfr_table * tbl,int allowedflags,int no_reserved)1936*aca3beaaSApple OSS Distributions pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved)
1937*aca3beaaSApple OSS Distributions {
1938*aca3beaaSApple OSS Distributions size_t i;
1939*aca3beaaSApple OSS Distributions
1940*aca3beaaSApple OSS Distributions if (!tbl->pfrt_name[0]) {
1941*aca3beaaSApple OSS Distributions return -1;
1942*aca3beaaSApple OSS Distributions }
1943*aca3beaaSApple OSS Distributions if (no_reserved && strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR) == 0) {
1944*aca3beaaSApple OSS Distributions return -1;
1945*aca3beaaSApple OSS Distributions }
1946*aca3beaaSApple OSS Distributions if (tbl->pfrt_name[PF_TABLE_NAME_SIZE - 1]) {
1947*aca3beaaSApple OSS Distributions return -1;
1948*aca3beaaSApple OSS Distributions }
1949*aca3beaaSApple OSS Distributions for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++) {
1950*aca3beaaSApple OSS Distributions if (tbl->pfrt_name[i]) {
1951*aca3beaaSApple OSS Distributions return -1;
1952*aca3beaaSApple OSS Distributions }
1953*aca3beaaSApple OSS Distributions }
1954*aca3beaaSApple OSS Distributions if (pfr_fix_anchor(tbl->pfrt_anchor)) {
1955*aca3beaaSApple OSS Distributions return -1;
1956*aca3beaaSApple OSS Distributions }
1957*aca3beaaSApple OSS Distributions if (tbl->pfrt_flags & ~allowedflags) {
1958*aca3beaaSApple OSS Distributions return -1;
1959*aca3beaaSApple OSS Distributions }
1960*aca3beaaSApple OSS Distributions return 0;
1961*aca3beaaSApple OSS Distributions }
1962*aca3beaaSApple OSS Distributions
1963*aca3beaaSApple OSS Distributions /*
1964*aca3beaaSApple OSS Distributions * Rewrite anchors referenced by tables to remove slashes
1965*aca3beaaSApple OSS Distributions * and check for validity.
1966*aca3beaaSApple OSS Distributions */
1967*aca3beaaSApple OSS Distributions static int
pfr_fix_anchor(char * anchor)1968*aca3beaaSApple OSS Distributions pfr_fix_anchor(char *anchor)
1969*aca3beaaSApple OSS Distributions {
1970*aca3beaaSApple OSS Distributions size_t siz = MAXPATHLEN;
1971*aca3beaaSApple OSS Distributions size_t i;
1972*aca3beaaSApple OSS Distributions
1973*aca3beaaSApple OSS Distributions if (anchor[0] == '/') {
1974*aca3beaaSApple OSS Distributions char *path;
1975*aca3beaaSApple OSS Distributions int off;
1976*aca3beaaSApple OSS Distributions
1977*aca3beaaSApple OSS Distributions path = anchor;
1978*aca3beaaSApple OSS Distributions off = 1;
1979*aca3beaaSApple OSS Distributions while (*++path == '/') {
1980*aca3beaaSApple OSS Distributions off++;
1981*aca3beaaSApple OSS Distributions }
1982*aca3beaaSApple OSS Distributions bcopy(path, anchor, siz - off);
1983*aca3beaaSApple OSS Distributions memset(anchor + siz - off, 0, off);
1984*aca3beaaSApple OSS Distributions }
1985*aca3beaaSApple OSS Distributions if (anchor[siz - 1]) {
1986*aca3beaaSApple OSS Distributions return -1;
1987*aca3beaaSApple OSS Distributions }
1988*aca3beaaSApple OSS Distributions for (i = strlen(anchor); i < siz; i++) {
1989*aca3beaaSApple OSS Distributions if (anchor[i]) {
1990*aca3beaaSApple OSS Distributions return -1;
1991*aca3beaaSApple OSS Distributions }
1992*aca3beaaSApple OSS Distributions }
1993*aca3beaaSApple OSS Distributions return 0;
1994*aca3beaaSApple OSS Distributions }
1995*aca3beaaSApple OSS Distributions
1996*aca3beaaSApple OSS Distributions static int
pfr_table_count(struct pfr_table * filter,int flags)1997*aca3beaaSApple OSS Distributions pfr_table_count(struct pfr_table *filter, int flags)
1998*aca3beaaSApple OSS Distributions {
1999*aca3beaaSApple OSS Distributions struct pf_ruleset *rs;
2000*aca3beaaSApple OSS Distributions
2001*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_ALLRSETS) {
2002*aca3beaaSApple OSS Distributions return pfr_ktable_cnt;
2003*aca3beaaSApple OSS Distributions }
2004*aca3beaaSApple OSS Distributions if (filter->pfrt_anchor[0]) {
2005*aca3beaaSApple OSS Distributions int r = -1;
2006*aca3beaaSApple OSS Distributions rs = pf_find_ruleset(filter->pfrt_anchor);
2007*aca3beaaSApple OSS Distributions r = (rs != NULL) ? rs->tables : -1;
2008*aca3beaaSApple OSS Distributions if (rs) {
2009*aca3beaaSApple OSS Distributions pf_release_ruleset(rs);
2010*aca3beaaSApple OSS Distributions rs = NULL;
2011*aca3beaaSApple OSS Distributions }
2012*aca3beaaSApple OSS Distributions return r;
2013*aca3beaaSApple OSS Distributions }
2014*aca3beaaSApple OSS Distributions return pf_main_ruleset.tables;
2015*aca3beaaSApple OSS Distributions }
2016*aca3beaaSApple OSS Distributions
2017*aca3beaaSApple OSS Distributions static int
pfr_skip_table(struct pfr_table * filter,struct pfr_ktable * kt,int flags)2018*aca3beaaSApple OSS Distributions pfr_skip_table(struct pfr_table *filter, struct pfr_ktable *kt, int flags)
2019*aca3beaaSApple OSS Distributions {
2020*aca3beaaSApple OSS Distributions if (flags & PFR_FLAG_ALLRSETS) {
2021*aca3beaaSApple OSS Distributions return 0;
2022*aca3beaaSApple OSS Distributions }
2023*aca3beaaSApple OSS Distributions if (strcmp(filter->pfrt_anchor, kt->pfrkt_anchor)) {
2024*aca3beaaSApple OSS Distributions return 1;
2025*aca3beaaSApple OSS Distributions }
2026*aca3beaaSApple OSS Distributions return 0;
2027*aca3beaaSApple OSS Distributions }
2028*aca3beaaSApple OSS Distributions
2029*aca3beaaSApple OSS Distributions static void
pfr_insert_ktables(struct pfr_ktableworkq * workq)2030*aca3beaaSApple OSS Distributions pfr_insert_ktables(struct pfr_ktableworkq *workq)
2031*aca3beaaSApple OSS Distributions {
2032*aca3beaaSApple OSS Distributions struct pfr_ktable *p;
2033*aca3beaaSApple OSS Distributions
2034*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2035*aca3beaaSApple OSS Distributions
2036*aca3beaaSApple OSS Distributions SLIST_FOREACH(p, workq, pfrkt_workq)
2037*aca3beaaSApple OSS Distributions pfr_insert_ktable(p);
2038*aca3beaaSApple OSS Distributions }
2039*aca3beaaSApple OSS Distributions
2040*aca3beaaSApple OSS Distributions static void
pfr_insert_ktable(struct pfr_ktable * kt)2041*aca3beaaSApple OSS Distributions pfr_insert_ktable(struct pfr_ktable *kt)
2042*aca3beaaSApple OSS Distributions {
2043*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2044*aca3beaaSApple OSS Distributions
2045*aca3beaaSApple OSS Distributions RB_INSERT(pfr_ktablehead, &pfr_ktables, kt);
2046*aca3beaaSApple OSS Distributions pfr_ktable_cnt++;
2047*aca3beaaSApple OSS Distributions if (kt->pfrkt_root != NULL) {
2048*aca3beaaSApple OSS Distributions if (!kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR]++) {
2049*aca3beaaSApple OSS Distributions pfr_setflags_ktable(kt->pfrkt_root,
2050*aca3beaaSApple OSS Distributions kt->pfrkt_root->pfrkt_flags | PFR_TFLAG_REFDANCHOR);
2051*aca3beaaSApple OSS Distributions }
2052*aca3beaaSApple OSS Distributions }
2053*aca3beaaSApple OSS Distributions }
2054*aca3beaaSApple OSS Distributions
2055*aca3beaaSApple OSS Distributions static void
pfr_setflags_ktables(struct pfr_ktableworkq * workq)2056*aca3beaaSApple OSS Distributions pfr_setflags_ktables(struct pfr_ktableworkq *workq)
2057*aca3beaaSApple OSS Distributions {
2058*aca3beaaSApple OSS Distributions struct pfr_ktable *p, *q;
2059*aca3beaaSApple OSS Distributions
2060*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2061*aca3beaaSApple OSS Distributions
2062*aca3beaaSApple OSS Distributions for (p = SLIST_FIRST(workq); p; p = q) {
2063*aca3beaaSApple OSS Distributions q = SLIST_NEXT(p, pfrkt_workq);
2064*aca3beaaSApple OSS Distributions pfr_setflags_ktable(p, p->pfrkt_nflags);
2065*aca3beaaSApple OSS Distributions }
2066*aca3beaaSApple OSS Distributions }
2067*aca3beaaSApple OSS Distributions
2068*aca3beaaSApple OSS Distributions static void
pfr_setflags_ktable(struct pfr_ktable * kt,int newf)2069*aca3beaaSApple OSS Distributions pfr_setflags_ktable(struct pfr_ktable *kt, int newf)
2070*aca3beaaSApple OSS Distributions {
2071*aca3beaaSApple OSS Distributions struct pfr_kentryworkq addrq;
2072*aca3beaaSApple OSS Distributions
2073*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2074*aca3beaaSApple OSS Distributions
2075*aca3beaaSApple OSS Distributions if (!(newf & PFR_TFLAG_REFERENCED) &&
2076*aca3beaaSApple OSS Distributions !(newf & PFR_TFLAG_REFDANCHOR) &&
2077*aca3beaaSApple OSS Distributions !(newf & PFR_TFLAG_PERSIST)) {
2078*aca3beaaSApple OSS Distributions newf &= ~PFR_TFLAG_ACTIVE;
2079*aca3beaaSApple OSS Distributions }
2080*aca3beaaSApple OSS Distributions if (!(newf & PFR_TFLAG_ACTIVE)) {
2081*aca3beaaSApple OSS Distributions newf &= ~PFR_TFLAG_USRMASK;
2082*aca3beaaSApple OSS Distributions }
2083*aca3beaaSApple OSS Distributions if (!(newf & PFR_TFLAG_SETMASK)) {
2084*aca3beaaSApple OSS Distributions RB_REMOVE(pfr_ktablehead, &pfr_ktables, kt);
2085*aca3beaaSApple OSS Distributions if (kt->pfrkt_root != NULL) {
2086*aca3beaaSApple OSS Distributions if (!--kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR]) {
2087*aca3beaaSApple OSS Distributions pfr_setflags_ktable(kt->pfrkt_root,
2088*aca3beaaSApple OSS Distributions kt->pfrkt_root->pfrkt_flags &
2089*aca3beaaSApple OSS Distributions ~PFR_TFLAG_REFDANCHOR);
2090*aca3beaaSApple OSS Distributions }
2091*aca3beaaSApple OSS Distributions }
2092*aca3beaaSApple OSS Distributions pfr_destroy_ktable(kt, 1);
2093*aca3beaaSApple OSS Distributions pfr_ktable_cnt--;
2094*aca3beaaSApple OSS Distributions return;
2095*aca3beaaSApple OSS Distributions }
2096*aca3beaaSApple OSS Distributions if (!(newf & PFR_TFLAG_ACTIVE) && kt->pfrkt_cnt) {
2097*aca3beaaSApple OSS Distributions pfr_enqueue_addrs(kt, &addrq, NULL, 0);
2098*aca3beaaSApple OSS Distributions pfr_remove_kentries(kt, &addrq);
2099*aca3beaaSApple OSS Distributions }
2100*aca3beaaSApple OSS Distributions if (!(newf & PFR_TFLAG_INACTIVE) && kt->pfrkt_shadow != NULL) {
2101*aca3beaaSApple OSS Distributions pfr_destroy_ktable(kt->pfrkt_shadow, 1);
2102*aca3beaaSApple OSS Distributions kt->pfrkt_shadow = NULL;
2103*aca3beaaSApple OSS Distributions }
2104*aca3beaaSApple OSS Distributions kt->pfrkt_flags = newf;
2105*aca3beaaSApple OSS Distributions }
2106*aca3beaaSApple OSS Distributions
2107*aca3beaaSApple OSS Distributions static void
pfr_clstats_ktables(struct pfr_ktableworkq * workq,u_int64_t tzero,int recurse)2108*aca3beaaSApple OSS Distributions pfr_clstats_ktables(struct pfr_ktableworkq *workq, u_int64_t tzero, int recurse)
2109*aca3beaaSApple OSS Distributions {
2110*aca3beaaSApple OSS Distributions struct pfr_ktable *p;
2111*aca3beaaSApple OSS Distributions
2112*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2113*aca3beaaSApple OSS Distributions
2114*aca3beaaSApple OSS Distributions SLIST_FOREACH(p, workq, pfrkt_workq)
2115*aca3beaaSApple OSS Distributions pfr_clstats_ktable(p, tzero, recurse);
2116*aca3beaaSApple OSS Distributions }
2117*aca3beaaSApple OSS Distributions
2118*aca3beaaSApple OSS Distributions static void
pfr_clstats_ktable(struct pfr_ktable * kt,u_int64_t tzero,int recurse)2119*aca3beaaSApple OSS Distributions pfr_clstats_ktable(struct pfr_ktable *kt, u_int64_t tzero, int recurse)
2120*aca3beaaSApple OSS Distributions {
2121*aca3beaaSApple OSS Distributions struct pfr_kentryworkq addrq;
2122*aca3beaaSApple OSS Distributions
2123*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2124*aca3beaaSApple OSS Distributions
2125*aca3beaaSApple OSS Distributions if (recurse) {
2126*aca3beaaSApple OSS Distributions pfr_enqueue_addrs(kt, &addrq, NULL, 0);
2127*aca3beaaSApple OSS Distributions pfr_clstats_kentries(&addrq, tzero, 0);
2128*aca3beaaSApple OSS Distributions }
2129*aca3beaaSApple OSS Distributions bzero(kt->pfrkt_packets, sizeof(kt->pfrkt_packets));
2130*aca3beaaSApple OSS Distributions bzero(kt->pfrkt_bytes, sizeof(kt->pfrkt_bytes));
2131*aca3beaaSApple OSS Distributions kt->pfrkt_match = kt->pfrkt_nomatch = 0;
2132*aca3beaaSApple OSS Distributions kt->pfrkt_tzero = tzero;
2133*aca3beaaSApple OSS Distributions }
2134*aca3beaaSApple OSS Distributions
2135*aca3beaaSApple OSS Distributions static struct pfr_ktable *
pfr_create_ktable(struct pfr_table * tbl,u_int64_t tzero,int attachruleset)2136*aca3beaaSApple OSS Distributions pfr_create_ktable(struct pfr_table *tbl, u_int64_t tzero, int attachruleset)
2137*aca3beaaSApple OSS Distributions {
2138*aca3beaaSApple OSS Distributions struct pfr_ktable *kt;
2139*aca3beaaSApple OSS Distributions struct pf_ruleset *rs;
2140*aca3beaaSApple OSS Distributions
2141*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2142*aca3beaaSApple OSS Distributions
2143*aca3beaaSApple OSS Distributions kt = pool_get(&pfr_ktable_pl, PR_WAITOK);
2144*aca3beaaSApple OSS Distributions if (kt == NULL) {
2145*aca3beaaSApple OSS Distributions return NULL;
2146*aca3beaaSApple OSS Distributions }
2147*aca3beaaSApple OSS Distributions bzero(kt, sizeof(*kt));
2148*aca3beaaSApple OSS Distributions kt->pfrkt_t = *tbl;
2149*aca3beaaSApple OSS Distributions
2150*aca3beaaSApple OSS Distributions if (attachruleset) {
2151*aca3beaaSApple OSS Distributions rs = pf_find_or_create_ruleset(tbl->pfrt_anchor);
2152*aca3beaaSApple OSS Distributions if (!rs) {
2153*aca3beaaSApple OSS Distributions pfr_destroy_ktable(kt, 0);
2154*aca3beaaSApple OSS Distributions return NULL;
2155*aca3beaaSApple OSS Distributions }
2156*aca3beaaSApple OSS Distributions kt->pfrkt_rs = rs;
2157*aca3beaaSApple OSS Distributions rs->tables++;
2158*aca3beaaSApple OSS Distributions }
2159*aca3beaaSApple OSS Distributions
2160*aca3beaaSApple OSS Distributions if (!rn_inithead((void **)&kt->pfrkt_ip4,
2161*aca3beaaSApple OSS Distributions offsetof(struct sockaddr_in, sin_addr) * 8) ||
2162*aca3beaaSApple OSS Distributions !rn_inithead((void **)&kt->pfrkt_ip6,
2163*aca3beaaSApple OSS Distributions offsetof(struct sockaddr_in6, sin6_addr) * 8)) {
2164*aca3beaaSApple OSS Distributions pfr_destroy_ktable(kt, 0);
2165*aca3beaaSApple OSS Distributions return NULL;
2166*aca3beaaSApple OSS Distributions }
2167*aca3beaaSApple OSS Distributions kt->pfrkt_tzero = tzero;
2168*aca3beaaSApple OSS Distributions
2169*aca3beaaSApple OSS Distributions return kt;
2170*aca3beaaSApple OSS Distributions }
2171*aca3beaaSApple OSS Distributions
2172*aca3beaaSApple OSS Distributions static void
pfr_destroy_ktables(struct pfr_ktableworkq * workq,int flushaddr)2173*aca3beaaSApple OSS Distributions pfr_destroy_ktables(struct pfr_ktableworkq *workq, int flushaddr)
2174*aca3beaaSApple OSS Distributions {
2175*aca3beaaSApple OSS Distributions struct pfr_ktable *p, *q;
2176*aca3beaaSApple OSS Distributions
2177*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2178*aca3beaaSApple OSS Distributions
2179*aca3beaaSApple OSS Distributions for (p = SLIST_FIRST(workq); p; p = q) {
2180*aca3beaaSApple OSS Distributions q = SLIST_NEXT(p, pfrkt_workq);
2181*aca3beaaSApple OSS Distributions pfr_destroy_ktable(p, flushaddr);
2182*aca3beaaSApple OSS Distributions }
2183*aca3beaaSApple OSS Distributions }
2184*aca3beaaSApple OSS Distributions
2185*aca3beaaSApple OSS Distributions static void
pfr_destroy_ktable(struct pfr_ktable * kt,int flushaddr)2186*aca3beaaSApple OSS Distributions pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
2187*aca3beaaSApple OSS Distributions {
2188*aca3beaaSApple OSS Distributions struct pfr_kentryworkq addrq;
2189*aca3beaaSApple OSS Distributions
2190*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2191*aca3beaaSApple OSS Distributions
2192*aca3beaaSApple OSS Distributions if (flushaddr) {
2193*aca3beaaSApple OSS Distributions pfr_enqueue_addrs(kt, &addrq, NULL, 0);
2194*aca3beaaSApple OSS Distributions pfr_clean_node_mask(kt, &addrq);
2195*aca3beaaSApple OSS Distributions pfr_destroy_kentries(&addrq);
2196*aca3beaaSApple OSS Distributions }
2197*aca3beaaSApple OSS Distributions if (kt->pfrkt_ip4 != NULL) {
2198*aca3beaaSApple OSS Distributions zfree(radix_node_head_zone, kt->pfrkt_ip4);
2199*aca3beaaSApple OSS Distributions }
2200*aca3beaaSApple OSS Distributions if (kt->pfrkt_ip6 != NULL) {
2201*aca3beaaSApple OSS Distributions zfree(radix_node_head_zone, kt->pfrkt_ip6);
2202*aca3beaaSApple OSS Distributions }
2203*aca3beaaSApple OSS Distributions if (kt->pfrkt_shadow != NULL) {
2204*aca3beaaSApple OSS Distributions pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr);
2205*aca3beaaSApple OSS Distributions }
2206*aca3beaaSApple OSS Distributions if (kt->pfrkt_rs != NULL) {
2207*aca3beaaSApple OSS Distributions kt->pfrkt_rs->tables--;
2208*aca3beaaSApple OSS Distributions pf_release_ruleset(kt->pfrkt_rs);
2209*aca3beaaSApple OSS Distributions }
2210*aca3beaaSApple OSS Distributions pool_put(&pfr_ktable_pl, kt);
2211*aca3beaaSApple OSS Distributions }
2212*aca3beaaSApple OSS Distributions
2213*aca3beaaSApple OSS Distributions static int
pfr_ktable_compare(struct pfr_ktable * p,struct pfr_ktable * q)2214*aca3beaaSApple OSS Distributions pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q)
2215*aca3beaaSApple OSS Distributions {
2216*aca3beaaSApple OSS Distributions int d;
2217*aca3beaaSApple OSS Distributions
2218*aca3beaaSApple OSS Distributions if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE))) {
2219*aca3beaaSApple OSS Distributions return d;
2220*aca3beaaSApple OSS Distributions }
2221*aca3beaaSApple OSS Distributions return strcmp(p->pfrkt_anchor, q->pfrkt_anchor);
2222*aca3beaaSApple OSS Distributions }
2223*aca3beaaSApple OSS Distributions
2224*aca3beaaSApple OSS Distributions static struct pfr_ktable *
pfr_lookup_table(struct pfr_table * tbl)2225*aca3beaaSApple OSS Distributions pfr_lookup_table(struct pfr_table *tbl)
2226*aca3beaaSApple OSS Distributions {
2227*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2228*aca3beaaSApple OSS Distributions
2229*aca3beaaSApple OSS Distributions /* struct pfr_ktable start like a struct pfr_table */
2230*aca3beaaSApple OSS Distributions return RB_FIND(pfr_ktablehead, &pfr_ktables,
2231*aca3beaaSApple OSS Distributions (struct pfr_ktable *)(void *)tbl);
2232*aca3beaaSApple OSS Distributions }
2233*aca3beaaSApple OSS Distributions
2234*aca3beaaSApple OSS Distributions int
pfr_match_addr(struct pfr_ktable * kt,struct pf_addr * a,sa_family_t af)2235*aca3beaaSApple OSS Distributions pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
2236*aca3beaaSApple OSS Distributions {
2237*aca3beaaSApple OSS Distributions struct pfr_kentry *ke = NULL;
2238*aca3beaaSApple OSS Distributions int match;
2239*aca3beaaSApple OSS Distributions
2240*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2241*aca3beaaSApple OSS Distributions
2242*aca3beaaSApple OSS Distributions if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) {
2243*aca3beaaSApple OSS Distributions kt = kt->pfrkt_root;
2244*aca3beaaSApple OSS Distributions }
2245*aca3beaaSApple OSS Distributions if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
2246*aca3beaaSApple OSS Distributions return 0;
2247*aca3beaaSApple OSS Distributions }
2248*aca3beaaSApple OSS Distributions
2249*aca3beaaSApple OSS Distributions switch (af) {
2250*aca3beaaSApple OSS Distributions #if INET
2251*aca3beaaSApple OSS Distributions case AF_INET:
2252*aca3beaaSApple OSS Distributions pfr_sin.sin_addr.s_addr = a->addr32[0];
2253*aca3beaaSApple OSS Distributions ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4);
2254*aca3beaaSApple OSS Distributions if (ke && KENTRY_RNF_ROOT(ke)) {
2255*aca3beaaSApple OSS Distributions ke = NULL;
2256*aca3beaaSApple OSS Distributions }
2257*aca3beaaSApple OSS Distributions break;
2258*aca3beaaSApple OSS Distributions #endif /* INET */
2259*aca3beaaSApple OSS Distributions case AF_INET6:
2260*aca3beaaSApple OSS Distributions bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr));
2261*aca3beaaSApple OSS Distributions ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6);
2262*aca3beaaSApple OSS Distributions if (ke && KENTRY_RNF_ROOT(ke)) {
2263*aca3beaaSApple OSS Distributions ke = NULL;
2264*aca3beaaSApple OSS Distributions }
2265*aca3beaaSApple OSS Distributions break;
2266*aca3beaaSApple OSS Distributions }
2267*aca3beaaSApple OSS Distributions match = (ke && !ke->pfrke_not);
2268*aca3beaaSApple OSS Distributions if (match) {
2269*aca3beaaSApple OSS Distributions kt->pfrkt_match++;
2270*aca3beaaSApple OSS Distributions } else {
2271*aca3beaaSApple OSS Distributions kt->pfrkt_nomatch++;
2272*aca3beaaSApple OSS Distributions }
2273*aca3beaaSApple OSS Distributions return match;
2274*aca3beaaSApple OSS Distributions }
2275*aca3beaaSApple OSS Distributions
2276*aca3beaaSApple OSS Distributions void
pfr_update_stats(struct pfr_ktable * kt,struct pf_addr * a,sa_family_t af,u_int64_t len,int dir_out,int op_pass,int notrule)2277*aca3beaaSApple OSS Distributions pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
2278*aca3beaaSApple OSS Distributions u_int64_t len, int dir_out, int op_pass, int notrule)
2279*aca3beaaSApple OSS Distributions {
2280*aca3beaaSApple OSS Distributions struct pfr_kentry *ke = NULL;
2281*aca3beaaSApple OSS Distributions
2282*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2283*aca3beaaSApple OSS Distributions
2284*aca3beaaSApple OSS Distributions if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) {
2285*aca3beaaSApple OSS Distributions kt = kt->pfrkt_root;
2286*aca3beaaSApple OSS Distributions }
2287*aca3beaaSApple OSS Distributions if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
2288*aca3beaaSApple OSS Distributions return;
2289*aca3beaaSApple OSS Distributions }
2290*aca3beaaSApple OSS Distributions
2291*aca3beaaSApple OSS Distributions switch (af) {
2292*aca3beaaSApple OSS Distributions #if INET
2293*aca3beaaSApple OSS Distributions case AF_INET:
2294*aca3beaaSApple OSS Distributions pfr_sin.sin_addr.s_addr = a->addr32[0];
2295*aca3beaaSApple OSS Distributions ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4);
2296*aca3beaaSApple OSS Distributions if (ke && KENTRY_RNF_ROOT(ke)) {
2297*aca3beaaSApple OSS Distributions ke = NULL;
2298*aca3beaaSApple OSS Distributions }
2299*aca3beaaSApple OSS Distributions break;
2300*aca3beaaSApple OSS Distributions #endif /* INET */
2301*aca3beaaSApple OSS Distributions case AF_INET6:
2302*aca3beaaSApple OSS Distributions bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr));
2303*aca3beaaSApple OSS Distributions ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6);
2304*aca3beaaSApple OSS Distributions if (ke && KENTRY_RNF_ROOT(ke)) {
2305*aca3beaaSApple OSS Distributions ke = NULL;
2306*aca3beaaSApple OSS Distributions }
2307*aca3beaaSApple OSS Distributions break;
2308*aca3beaaSApple OSS Distributions default:
2309*aca3beaaSApple OSS Distributions ;
2310*aca3beaaSApple OSS Distributions }
2311*aca3beaaSApple OSS Distributions if ((ke == NULL || ke->pfrke_not) != notrule) {
2312*aca3beaaSApple OSS Distributions if (op_pass != PFR_OP_PASS) {
2313*aca3beaaSApple OSS Distributions printf("pfr_update_stats: assertion failed.\n");
2314*aca3beaaSApple OSS Distributions }
2315*aca3beaaSApple OSS Distributions op_pass = PFR_OP_XPASS;
2316*aca3beaaSApple OSS Distributions }
2317*aca3beaaSApple OSS Distributions kt->pfrkt_packets[dir_out][op_pass]++;
2318*aca3beaaSApple OSS Distributions kt->pfrkt_bytes[dir_out][op_pass] += len;
2319*aca3beaaSApple OSS Distributions if (ke != NULL && op_pass != PFR_OP_XPASS) {
2320*aca3beaaSApple OSS Distributions ke->pfrke_packets[dir_out][op_pass]++;
2321*aca3beaaSApple OSS Distributions ke->pfrke_bytes[dir_out][op_pass] += len;
2322*aca3beaaSApple OSS Distributions }
2323*aca3beaaSApple OSS Distributions }
2324*aca3beaaSApple OSS Distributions
2325*aca3beaaSApple OSS Distributions struct pfr_ktable *
pfr_attach_table(struct pf_ruleset * rs,char * name)2326*aca3beaaSApple OSS Distributions pfr_attach_table(struct pf_ruleset *rs, char *name)
2327*aca3beaaSApple OSS Distributions {
2328*aca3beaaSApple OSS Distributions struct pfr_ktable *kt, *rt;
2329*aca3beaaSApple OSS Distributions struct pfr_table tbl;
2330*aca3beaaSApple OSS Distributions struct pf_anchor *ac = rs->anchor;
2331*aca3beaaSApple OSS Distributions
2332*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2333*aca3beaaSApple OSS Distributions
2334*aca3beaaSApple OSS Distributions bzero(&tbl, sizeof(tbl));
2335*aca3beaaSApple OSS Distributions strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name));
2336*aca3beaaSApple OSS Distributions if (ac != NULL) {
2337*aca3beaaSApple OSS Distributions strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor));
2338*aca3beaaSApple OSS Distributions }
2339*aca3beaaSApple OSS Distributions kt = pfr_lookup_table(&tbl);
2340*aca3beaaSApple OSS Distributions if (kt == NULL) {
2341*aca3beaaSApple OSS Distributions kt = pfr_create_ktable(&tbl, pf_calendar_time_second(), 1);
2342*aca3beaaSApple OSS Distributions if (kt == NULL) {
2343*aca3beaaSApple OSS Distributions return NULL;
2344*aca3beaaSApple OSS Distributions }
2345*aca3beaaSApple OSS Distributions if (ac != NULL) {
2346*aca3beaaSApple OSS Distributions bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor));
2347*aca3beaaSApple OSS Distributions rt = pfr_lookup_table(&tbl);
2348*aca3beaaSApple OSS Distributions if (rt == NULL) {
2349*aca3beaaSApple OSS Distributions rt = pfr_create_ktable(&tbl, 0, 1);
2350*aca3beaaSApple OSS Distributions if (rt == NULL) {
2351*aca3beaaSApple OSS Distributions pfr_destroy_ktable(kt, 0);
2352*aca3beaaSApple OSS Distributions return NULL;
2353*aca3beaaSApple OSS Distributions }
2354*aca3beaaSApple OSS Distributions pfr_insert_ktable(rt);
2355*aca3beaaSApple OSS Distributions }
2356*aca3beaaSApple OSS Distributions kt->pfrkt_root = rt;
2357*aca3beaaSApple OSS Distributions }
2358*aca3beaaSApple OSS Distributions pfr_insert_ktable(kt);
2359*aca3beaaSApple OSS Distributions }
2360*aca3beaaSApple OSS Distributions if (!kt->pfrkt_refcnt[PFR_REFCNT_RULE]++) {
2361*aca3beaaSApple OSS Distributions pfr_setflags_ktable(kt, kt->pfrkt_flags | PFR_TFLAG_REFERENCED);
2362*aca3beaaSApple OSS Distributions }
2363*aca3beaaSApple OSS Distributions return kt;
2364*aca3beaaSApple OSS Distributions }
2365*aca3beaaSApple OSS Distributions
2366*aca3beaaSApple OSS Distributions void
pfr_detach_table(struct pfr_ktable * kt)2367*aca3beaaSApple OSS Distributions pfr_detach_table(struct pfr_ktable *kt)
2368*aca3beaaSApple OSS Distributions {
2369*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2370*aca3beaaSApple OSS Distributions
2371*aca3beaaSApple OSS Distributions if (kt->pfrkt_refcnt[PFR_REFCNT_RULE] <= 0) {
2372*aca3beaaSApple OSS Distributions printf("pfr_detach_table: refcount = %d.\n",
2373*aca3beaaSApple OSS Distributions kt->pfrkt_refcnt[PFR_REFCNT_RULE]);
2374*aca3beaaSApple OSS Distributions } else if (!--kt->pfrkt_refcnt[PFR_REFCNT_RULE]) {
2375*aca3beaaSApple OSS Distributions pfr_setflags_ktable(kt, kt->pfrkt_flags & ~PFR_TFLAG_REFERENCED);
2376*aca3beaaSApple OSS Distributions }
2377*aca3beaaSApple OSS Distributions }
2378*aca3beaaSApple OSS Distributions
2379*aca3beaaSApple OSS Distributions int
pfr_pool_get(struct pfr_ktable * kt,int * pidx,struct pf_addr * counter,struct pf_addr ** raddr,struct pf_addr ** rmask,sa_family_t af)2380*aca3beaaSApple OSS Distributions pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
2381*aca3beaaSApple OSS Distributions struct pf_addr **raddr, struct pf_addr **rmask, sa_family_t af)
2382*aca3beaaSApple OSS Distributions {
2383*aca3beaaSApple OSS Distributions struct pfr_kentry *ke, *ke2;
2384*aca3beaaSApple OSS Distributions struct pf_addr *addr;
2385*aca3beaaSApple OSS Distributions union sockaddr_union mask;
2386*aca3beaaSApple OSS Distributions int idx = -1, use_counter = 0;
2387*aca3beaaSApple OSS Distributions
2388*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2389*aca3beaaSApple OSS Distributions
2390*aca3beaaSApple OSS Distributions if (af == AF_INET) {
2391*aca3beaaSApple OSS Distributions addr = (struct pf_addr *)&pfr_sin.sin_addr;
2392*aca3beaaSApple OSS Distributions } else if (af == AF_INET6) {
2393*aca3beaaSApple OSS Distributions addr = (struct pf_addr *)&pfr_sin6.sin6_addr;
2394*aca3beaaSApple OSS Distributions } else {
2395*aca3beaaSApple OSS Distributions return -1;
2396*aca3beaaSApple OSS Distributions }
2397*aca3beaaSApple OSS Distributions
2398*aca3beaaSApple OSS Distributions if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) {
2399*aca3beaaSApple OSS Distributions kt = kt->pfrkt_root;
2400*aca3beaaSApple OSS Distributions }
2401*aca3beaaSApple OSS Distributions if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
2402*aca3beaaSApple OSS Distributions return -1;
2403*aca3beaaSApple OSS Distributions }
2404*aca3beaaSApple OSS Distributions
2405*aca3beaaSApple OSS Distributions if (pidx != NULL) {
2406*aca3beaaSApple OSS Distributions idx = *pidx;
2407*aca3beaaSApple OSS Distributions }
2408*aca3beaaSApple OSS Distributions if (counter != NULL && idx >= 0) {
2409*aca3beaaSApple OSS Distributions use_counter = 1;
2410*aca3beaaSApple OSS Distributions }
2411*aca3beaaSApple OSS Distributions if (idx < 0) {
2412*aca3beaaSApple OSS Distributions idx = 0;
2413*aca3beaaSApple OSS Distributions }
2414*aca3beaaSApple OSS Distributions
2415*aca3beaaSApple OSS Distributions _next_block:
2416*aca3beaaSApple OSS Distributions ke = pfr_kentry_byidx(kt, idx, af);
2417*aca3beaaSApple OSS Distributions if (ke == NULL) {
2418*aca3beaaSApple OSS Distributions kt->pfrkt_nomatch++;
2419*aca3beaaSApple OSS Distributions return 1;
2420*aca3beaaSApple OSS Distributions }
2421*aca3beaaSApple OSS Distributions pfr_prepare_network(&pfr_mask, af, ke->pfrke_net);
2422*aca3beaaSApple OSS Distributions *raddr = SUNION2PF(&ke->pfrke_sa, af);
2423*aca3beaaSApple OSS Distributions *rmask = SUNION2PF(&pfr_mask, af);
2424*aca3beaaSApple OSS Distributions
2425*aca3beaaSApple OSS Distributions if (use_counter) {
2426*aca3beaaSApple OSS Distributions /* is supplied address within block? */
2427*aca3beaaSApple OSS Distributions if (!PF_MATCHA(0, *raddr, *rmask, counter, af)) {
2428*aca3beaaSApple OSS Distributions /* no, go to next block in table */
2429*aca3beaaSApple OSS Distributions idx++;
2430*aca3beaaSApple OSS Distributions use_counter = 0;
2431*aca3beaaSApple OSS Distributions goto _next_block;
2432*aca3beaaSApple OSS Distributions }
2433*aca3beaaSApple OSS Distributions PF_ACPY(addr, counter, af);
2434*aca3beaaSApple OSS Distributions } else {
2435*aca3beaaSApple OSS Distributions /* use first address of block */
2436*aca3beaaSApple OSS Distributions PF_ACPY(addr, *raddr, af);
2437*aca3beaaSApple OSS Distributions }
2438*aca3beaaSApple OSS Distributions
2439*aca3beaaSApple OSS Distributions if (!KENTRY_NETWORK(ke)) {
2440*aca3beaaSApple OSS Distributions /* this is a single IP address - no possible nested block */
2441*aca3beaaSApple OSS Distributions PF_ACPY(counter, addr, af);
2442*aca3beaaSApple OSS Distributions *pidx = idx;
2443*aca3beaaSApple OSS Distributions kt->pfrkt_match++;
2444*aca3beaaSApple OSS Distributions return 0;
2445*aca3beaaSApple OSS Distributions }
2446*aca3beaaSApple OSS Distributions for (;;) {
2447*aca3beaaSApple OSS Distributions /* we don't want to use a nested block */
2448*aca3beaaSApple OSS Distributions if (af == AF_INET) {
2449*aca3beaaSApple OSS Distributions ke2 = (struct pfr_kentry *)rn_match(&pfr_sin,
2450*aca3beaaSApple OSS Distributions kt->pfrkt_ip4);
2451*aca3beaaSApple OSS Distributions } else if (af == AF_INET6) {
2452*aca3beaaSApple OSS Distributions ke2 = (struct pfr_kentry *)rn_match(&pfr_sin6,
2453*aca3beaaSApple OSS Distributions kt->pfrkt_ip6);
2454*aca3beaaSApple OSS Distributions } else {
2455*aca3beaaSApple OSS Distributions return -1; /* never happens */
2456*aca3beaaSApple OSS Distributions }
2457*aca3beaaSApple OSS Distributions /* no need to check KENTRY_RNF_ROOT() here */
2458*aca3beaaSApple OSS Distributions if (ke2 == ke) {
2459*aca3beaaSApple OSS Distributions /* lookup return the same block - perfect */
2460*aca3beaaSApple OSS Distributions PF_ACPY(counter, addr, af);
2461*aca3beaaSApple OSS Distributions *pidx = idx;
2462*aca3beaaSApple OSS Distributions kt->pfrkt_match++;
2463*aca3beaaSApple OSS Distributions return 0;
2464*aca3beaaSApple OSS Distributions }
2465*aca3beaaSApple OSS Distributions
2466*aca3beaaSApple OSS Distributions /* we need to increase the counter past the nested block */
2467*aca3beaaSApple OSS Distributions pfr_prepare_network(&mask, AF_INET, ke2->pfrke_net);
2468*aca3beaaSApple OSS Distributions PF_POOLMASK(addr, addr, SUNION2PF(&mask, af), &pfr_ffaddr, af);
2469*aca3beaaSApple OSS Distributions PF_AINC(addr, af);
2470*aca3beaaSApple OSS Distributions if (!PF_MATCHA(0, *raddr, *rmask, addr, af)) {
2471*aca3beaaSApple OSS Distributions /* ok, we reached the end of our main block */
2472*aca3beaaSApple OSS Distributions /* go to next block in table */
2473*aca3beaaSApple OSS Distributions idx++;
2474*aca3beaaSApple OSS Distributions use_counter = 0;
2475*aca3beaaSApple OSS Distributions goto _next_block;
2476*aca3beaaSApple OSS Distributions }
2477*aca3beaaSApple OSS Distributions }
2478*aca3beaaSApple OSS Distributions }
2479*aca3beaaSApple OSS Distributions
2480*aca3beaaSApple OSS Distributions static struct pfr_kentry *
pfr_kentry_byidx(struct pfr_ktable * kt,int idx,int af)2481*aca3beaaSApple OSS Distributions pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
2482*aca3beaaSApple OSS Distributions {
2483*aca3beaaSApple OSS Distributions struct pfr_walktree w;
2484*aca3beaaSApple OSS Distributions
2485*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2486*aca3beaaSApple OSS Distributions
2487*aca3beaaSApple OSS Distributions bzero(&w, sizeof(w));
2488*aca3beaaSApple OSS Distributions w.pfrw_op = PFRW_POOL_GET;
2489*aca3beaaSApple OSS Distributions w.pfrw_cnt = idx;
2490*aca3beaaSApple OSS Distributions
2491*aca3beaaSApple OSS Distributions switch (af) {
2492*aca3beaaSApple OSS Distributions #if INET
2493*aca3beaaSApple OSS Distributions case AF_INET:
2494*aca3beaaSApple OSS Distributions (void) kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4,
2495*aca3beaaSApple OSS Distributions pfr_walktree, &w);
2496*aca3beaaSApple OSS Distributions return w.pfrw_kentry;
2497*aca3beaaSApple OSS Distributions #endif /* INET */
2498*aca3beaaSApple OSS Distributions case AF_INET6:
2499*aca3beaaSApple OSS Distributions (void) kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6,
2500*aca3beaaSApple OSS Distributions pfr_walktree, &w);
2501*aca3beaaSApple OSS Distributions return w.pfrw_kentry;
2502*aca3beaaSApple OSS Distributions default:
2503*aca3beaaSApple OSS Distributions return NULL;
2504*aca3beaaSApple OSS Distributions }
2505*aca3beaaSApple OSS Distributions }
2506*aca3beaaSApple OSS Distributions
2507*aca3beaaSApple OSS Distributions void
pfr_dynaddr_update(struct pfr_ktable * kt,struct pfi_dynaddr * dyn)2508*aca3beaaSApple OSS Distributions pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn)
2509*aca3beaaSApple OSS Distributions {
2510*aca3beaaSApple OSS Distributions struct pfr_walktree w;
2511*aca3beaaSApple OSS Distributions
2512*aca3beaaSApple OSS Distributions LCK_MTX_ASSERT(&pf_lock, LCK_MTX_ASSERT_OWNED);
2513*aca3beaaSApple OSS Distributions
2514*aca3beaaSApple OSS Distributions bzero(&w, sizeof(w));
2515*aca3beaaSApple OSS Distributions w.pfrw_op = PFRW_DYNADDR_UPDATE;
2516*aca3beaaSApple OSS Distributions w.pfrw_dyn = dyn;
2517*aca3beaaSApple OSS Distributions
2518*aca3beaaSApple OSS Distributions dyn->pfid_acnt4 = 0;
2519*aca3beaaSApple OSS Distributions dyn->pfid_acnt6 = 0;
2520*aca3beaaSApple OSS Distributions if (!dyn->pfid_af || dyn->pfid_af == AF_INET) {
2521*aca3beaaSApple OSS Distributions (void) kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4,
2522*aca3beaaSApple OSS Distributions pfr_walktree, &w);
2523*aca3beaaSApple OSS Distributions }
2524*aca3beaaSApple OSS Distributions if (!dyn->pfid_af || dyn->pfid_af == AF_INET6) {
2525*aca3beaaSApple OSS Distributions (void) kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6,
2526*aca3beaaSApple OSS Distributions pfr_walktree, &w);
2527*aca3beaaSApple OSS Distributions }
2528*aca3beaaSApple OSS Distributions }
2529