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