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