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