xref: /openbsd-src/sys/net/pf_table.c (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
1 /*	$OpenBSD: pf_table.c,v 1.134 2020/07/28 16:47:41 yasuoka 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 = gettime();
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 = gettime();
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 = gettime();
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, gettime(), 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 != PFR_FB_NONE)
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 = gettime();
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 					pfr_destroy_ktable(p, 0);
1310 					goto _skip;
1311 				}
1312 			}
1313 			SLIST_INSERT_HEAD(&addq, p, pfrkt_workq);
1314 			xadd++;
1315 			if (!key.pfrkt_anchor[0])
1316 				goto _skip;
1317 
1318 			/* find or create root table */
1319 			bzero(key.pfrkt_anchor, sizeof(key.pfrkt_anchor));
1320 			r = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1321 			if (r != NULL) {
1322 				p->pfrkt_root = r;
1323 				goto _skip;
1324 			}
1325 			SLIST_FOREACH(q, &addq, pfrkt_workq) {
1326 				if (!pfr_ktable_compare(&key, q)) {
1327 					p->pfrkt_root = q;
1328 					goto _skip;
1329 				}
1330 			}
1331 			key.pfrkt_flags = 0;
1332 			r = pfr_create_ktable(&key.pfrkt_t, 0, 1,
1333 			    !(flags & PFR_FLAG_USERIOCTL));
1334 			if (r == NULL)
1335 				senderr(ENOMEM);
1336 			SLIST_INSERT_HEAD(&addq, r, pfrkt_workq);
1337 			p->pfrkt_root = r;
1338 		} else if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1339 			SLIST_FOREACH(q, &changeq, pfrkt_workq)
1340 				if (!pfr_ktable_compare(&key, q))
1341 					goto _skip;
1342 			p->pfrkt_nflags = (p->pfrkt_flags &
1343 			    ~PFR_TFLAG_USRMASK) | key.pfrkt_flags;
1344 			SLIST_INSERT_HEAD(&changeq, p, pfrkt_workq);
1345 			xadd++;
1346 		}
1347 _skip:
1348 	;
1349 	}
1350 	if (!(flags & PFR_FLAG_DUMMY)) {
1351 		pfr_insert_ktables(&addq);
1352 		pfr_setflags_ktables(&changeq);
1353 	} else
1354 		 pfr_destroy_ktables(&addq, 0);
1355 	if (nadd != NULL)
1356 		*nadd = xadd;
1357 	return (0);
1358 _bad:
1359 	pfr_destroy_ktables(&addq, 0);
1360 	return (rv);
1361 }
1362 
1363 int
1364 pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
1365 {
1366 	struct pfr_ktableworkq	 workq;
1367 	struct pfr_ktable	*p, *q, key;
1368 	int			 i, xdel = 0;
1369 
1370 	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1371 	SLIST_INIT(&workq);
1372 	for (i = 0; i < size; i++) {
1373 		YIELD(i, flags & PFR_FLAG_USERIOCTL);
1374 		if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags))
1375 			return (EFAULT);
1376 		if (pfr_validate_table(&key.pfrkt_t, 0,
1377 		    flags & PFR_FLAG_USERIOCTL))
1378 			return (EINVAL);
1379 		p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1380 		if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1381 			SLIST_FOREACH(q, &workq, pfrkt_workq)
1382 				if (!pfr_ktable_compare(p, q))
1383 					goto _skip;
1384 			p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
1385 			SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1386 			xdel++;
1387 		}
1388 _skip:
1389 	;
1390 	}
1391 
1392 	if (!(flags & PFR_FLAG_DUMMY)) {
1393 		pfr_setflags_ktables(&workq);
1394 	}
1395 	if (ndel != NULL)
1396 		*ndel = xdel;
1397 	return (0);
1398 }
1399 
1400 int
1401 pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
1402 	int flags)
1403 {
1404 	struct pfr_ktable	*p;
1405 	int			 n, nn;
1406 
1407 	ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS);
1408 	if (pfr_fix_anchor(filter->pfrt_anchor))
1409 		return (EINVAL);
1410 	n = nn = pfr_table_count(filter, flags);
1411 	if (n < 0)
1412 		return (ENOENT);
1413 	if (n > *size) {
1414 		*size = n;
1415 		return (0);
1416 	}
1417 	RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1418 		if (pfr_skip_table(filter, p, flags))
1419 			continue;
1420 		if (n-- <= 0)
1421 			continue;
1422 		if (COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl), flags))
1423 			return (EFAULT);
1424 	}
1425 	if (n) {
1426 		DPFPRINTF(LOG_ERR,
1427 		    "pfr_get_tables: corruption detected (%d).", n);
1428 		return (ENOTTY);
1429 	}
1430 	*size = nn;
1431 	return (0);
1432 }
1433 
1434 int
1435 pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
1436 	int flags)
1437 {
1438 	struct pfr_ktable	*p;
1439 	struct pfr_ktableworkq	 workq;
1440 	int			 n, nn;
1441 	time_t			 tzero = gettime();
1442 
1443 	/* XXX PFR_FLAG_CLSTATS disabled */
1444 	ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS);
1445 	if (pfr_fix_anchor(filter->pfrt_anchor))
1446 		return (EINVAL);
1447 	n = nn = pfr_table_count(filter, flags);
1448 	if (n < 0)
1449 		return (ENOENT);
1450 	if (n > *size) {
1451 		*size = n;
1452 		return (0);
1453 	}
1454 	SLIST_INIT(&workq);
1455 	RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1456 		if (pfr_skip_table(filter, p, flags))
1457 			continue;
1458 		if (n-- <= 0)
1459 			continue;
1460 		if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl), flags))
1461 			return (EFAULT);
1462 		SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1463 	}
1464 	if (flags & PFR_FLAG_CLSTATS)
1465 		pfr_clstats_ktables(&workq, tzero,
1466 		    flags & PFR_FLAG_ADDRSTOO);
1467 	if (n) {
1468 		DPFPRINTF(LOG_ERR,
1469 		    "pfr_get_tstats: corruption detected (%d).", n);
1470 		return (ENOTTY);
1471 	}
1472 	*size = nn;
1473 	return (0);
1474 }
1475 
1476 int
1477 pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
1478 {
1479 	struct pfr_ktableworkq	 workq;
1480 	struct pfr_ktable	*p, key;
1481 	int			 i, xzero = 0;
1482 	time_t			 tzero = gettime();
1483 
1484 	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO);
1485 	SLIST_INIT(&workq);
1486 	for (i = 0; i < size; i++) {
1487 		YIELD(i, flags & PFR_FLAG_USERIOCTL);
1488 		if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags))
1489 			return (EFAULT);
1490 		if (pfr_validate_table(&key.pfrkt_t, 0, 0))
1491 			return (EINVAL);
1492 		p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1493 		if (p != NULL) {
1494 			SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1495 			xzero++;
1496 		}
1497 	}
1498 	if (!(flags & PFR_FLAG_DUMMY)) {
1499 		pfr_clstats_ktables(&workq, tzero, flags & PFR_FLAG_ADDRSTOO);
1500 	}
1501 	if (nzero != NULL)
1502 		*nzero = xzero;
1503 	return (0);
1504 }
1505 
1506 int
1507 pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
1508 	int *nchange, int *ndel, int flags)
1509 {
1510 	struct pfr_ktableworkq	 workq;
1511 	struct pfr_ktable	*p, *q, key;
1512 	int			 i, xchange = 0, xdel = 0;
1513 
1514 	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1515 	if ((setflag & ~PFR_TFLAG_USRMASK) ||
1516 	    (clrflag & ~PFR_TFLAG_USRMASK) ||
1517 	    (setflag & clrflag))
1518 		return (EINVAL);
1519 	SLIST_INIT(&workq);
1520 	for (i = 0; i < size; i++) {
1521 		YIELD(i, flags & PFR_FLAG_USERIOCTL);
1522 		if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags))
1523 			return (EFAULT);
1524 		if (pfr_validate_table(&key.pfrkt_t, 0,
1525 		    flags & PFR_FLAG_USERIOCTL))
1526 			return (EINVAL);
1527 		p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1528 		if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1529 			p->pfrkt_nflags = (p->pfrkt_flags | setflag) &
1530 			    ~clrflag;
1531 			if (p->pfrkt_nflags == p->pfrkt_flags)
1532 				goto _skip;
1533 			SLIST_FOREACH(q, &workq, pfrkt_workq)
1534 				if (!pfr_ktable_compare(p, q))
1535 					goto _skip;
1536 			SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1537 			if ((p->pfrkt_flags & PFR_TFLAG_PERSIST) &&
1538 			    (clrflag & PFR_TFLAG_PERSIST) &&
1539 			    !(p->pfrkt_flags & PFR_TFLAG_REFERENCED))
1540 				xdel++;
1541 			else
1542 				xchange++;
1543 		}
1544 _skip:
1545 	;
1546 	}
1547 	if (!(flags & PFR_FLAG_DUMMY)) {
1548 		pfr_setflags_ktables(&workq);
1549 	}
1550 	if (nchange != NULL)
1551 		*nchange = xchange;
1552 	if (ndel != NULL)
1553 		*ndel = xdel;
1554 	return (0);
1555 }
1556 
1557 int
1558 pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags)
1559 {
1560 	struct pfr_ktableworkq	 workq;
1561 	struct pfr_ktable	*p;
1562 	struct pf_ruleset	*rs;
1563 	int			 xdel = 0;
1564 
1565 	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1566 	rs = pf_find_or_create_ruleset(trs->pfrt_anchor);
1567 	if (rs == NULL)
1568 		return (ENOMEM);
1569 	SLIST_INIT(&workq);
1570 	RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1571 		if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
1572 		    pfr_skip_table(trs, p, 0))
1573 			continue;
1574 		p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
1575 		SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1576 		xdel++;
1577 	}
1578 	if (!(flags & PFR_FLAG_DUMMY)) {
1579 		pfr_setflags_ktables(&workq);
1580 		if (ticket != NULL)
1581 			*ticket = ++rs->tticket;
1582 		rs->topen = 1;
1583 	} else
1584 		pf_remove_if_empty_ruleset(rs);
1585 	if (ndel != NULL)
1586 		*ndel = xdel;
1587 	return (0);
1588 }
1589 
1590 int
1591 pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
1592     int *nadd, int *naddr, u_int32_t ticket, int flags)
1593 {
1594 	struct pfr_ktableworkq	 tableq;
1595 	struct pfr_kentryworkq	 addrq;
1596 	struct pfr_ktable	*kt, *rt, *shadow, key;
1597 	struct pfr_kentry	*p;
1598 	struct pfr_addr		 ad;
1599 	struct pf_ruleset	*rs;
1600 	int			 i, rv, xadd = 0, xaddr = 0;
1601 
1602 	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO);
1603 	if (size && !(flags & PFR_FLAG_ADDRSTOO))
1604 		return (EINVAL);
1605 	if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
1606 	    flags & PFR_FLAG_USERIOCTL))
1607 		return (EINVAL);
1608 	rs = pf_find_ruleset(tbl->pfrt_anchor);
1609 	if (rs == NULL || !rs->topen || ticket != rs->tticket)
1610 		return (EBUSY);
1611 	tbl->pfrt_flags |= PFR_TFLAG_INACTIVE;
1612 	SLIST_INIT(&tableq);
1613 	kt = RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)tbl);
1614 	if (kt == NULL) {
1615 		kt = pfr_create_ktable(tbl, 0, 1,
1616 		    !(flags & PFR_FLAG_USERIOCTL));
1617 		if (kt == NULL)
1618 			return (ENOMEM);
1619 		SLIST_INSERT_HEAD(&tableq, kt, pfrkt_workq);
1620 		xadd++;
1621 		if (!tbl->pfrt_anchor[0])
1622 			goto _skip;
1623 
1624 		/* find or create root table */
1625 		bzero(&key, sizeof(key));
1626 		strlcpy(key.pfrkt_name, tbl->pfrt_name, sizeof(key.pfrkt_name));
1627 		rt = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1628 		if (rt != NULL) {
1629 			kt->pfrkt_root = rt;
1630 			goto _skip;
1631 		}
1632 		rt = pfr_create_ktable(&key.pfrkt_t, 0, 1,
1633 		    !(flags & PFR_FLAG_USERIOCTL));
1634 		if (rt == NULL) {
1635 			pfr_destroy_ktables(&tableq, 0);
1636 			return (ENOMEM);
1637 		}
1638 		SLIST_INSERT_HEAD(&tableq, rt, pfrkt_workq);
1639 		kt->pfrkt_root = rt;
1640 	} else if (!(kt->pfrkt_flags & PFR_TFLAG_INACTIVE))
1641 		xadd++;
1642 _skip:
1643 	shadow = pfr_create_ktable(tbl, 0, 0, !(flags & PFR_FLAG_USERIOCTL));
1644 	if (shadow == NULL) {
1645 		pfr_destroy_ktables(&tableq, 0);
1646 		return (ENOMEM);
1647 	}
1648 	SLIST_INIT(&addrq);
1649 	for (i = 0; i < size; i++) {
1650 		YIELD(i, flags & PFR_FLAG_USERIOCTL);
1651 		if (COPYIN(addr+i, &ad, sizeof(ad), flags))
1652 			senderr(EFAULT);
1653 		if (pfr_validate_addr(&ad))
1654 			senderr(EINVAL);
1655 		if (pfr_lookup_addr(shadow, &ad, 1) != NULL)
1656 			continue;
1657 		p = pfr_create_kentry(&ad);
1658 		if (p == NULL)
1659 			senderr(ENOMEM);
1660 		if (pfr_route_kentry(shadow, p)) {
1661 			pfr_destroy_kentry(p);
1662 			continue;
1663 		}
1664 		SLIST_INSERT_HEAD(&addrq, p, pfrke_workq);
1665 		xaddr++;
1666 		if (p->pfrke_type == PFRKE_COST)
1667 			kt->pfrkt_refcntcost++;
1668 		pfr_ktable_winfo_update(kt, p);
1669 	}
1670 	if (!(flags & PFR_FLAG_DUMMY)) {
1671 		if (kt->pfrkt_shadow != NULL)
1672 			pfr_destroy_ktable(kt->pfrkt_shadow, 1);
1673 		kt->pfrkt_flags |= PFR_TFLAG_INACTIVE;
1674 		pfr_insert_ktables(&tableq);
1675 		shadow->pfrkt_cnt = (flags & PFR_FLAG_ADDRSTOO) ?
1676 		    xaddr : NO_ADDRESSES;
1677 		kt->pfrkt_shadow = shadow;
1678 	} else {
1679 		pfr_clean_node_mask(shadow, &addrq);
1680 		pfr_destroy_ktable(shadow, 0);
1681 		pfr_destroy_ktables(&tableq, 0);
1682 		pfr_destroy_kentries(&addrq);
1683 	}
1684 	if (nadd != NULL)
1685 		*nadd = xadd;
1686 	if (naddr != NULL)
1687 		*naddr = xaddr;
1688 	return (0);
1689 _bad:
1690 	pfr_destroy_ktable(shadow, 0);
1691 	pfr_destroy_ktables(&tableq, 0);
1692 	pfr_destroy_kentries(&addrq);
1693 	return (rv);
1694 }
1695 
1696 int
1697 pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
1698 {
1699 	struct pfr_ktableworkq	 workq;
1700 	struct pfr_ktable	*p;
1701 	struct pf_ruleset	*rs;
1702 	int			 xdel = 0;
1703 
1704 	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1705 	rs = pf_find_ruleset(trs->pfrt_anchor);
1706 	if (rs == NULL || !rs->topen || ticket != rs->tticket)
1707 		return (0);
1708 	SLIST_INIT(&workq);
1709 	RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1710 		if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
1711 		    pfr_skip_table(trs, p, 0))
1712 			continue;
1713 		p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
1714 		SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1715 		xdel++;
1716 	}
1717 	if (!(flags & PFR_FLAG_DUMMY)) {
1718 		pfr_setflags_ktables(&workq);
1719 		rs->topen = 0;
1720 		pf_remove_if_empty_ruleset(rs);
1721 	}
1722 	if (ndel != NULL)
1723 		*ndel = xdel;
1724 	return (0);
1725 }
1726 
1727 int
1728 pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
1729     int *nchange, int flags)
1730 {
1731 	struct pfr_ktable	*p, *q;
1732 	struct pfr_ktableworkq	 workq;
1733 	struct pf_ruleset	*rs;
1734 	int			 xadd = 0, xchange = 0;
1735 	time_t			 tzero = gettime();
1736 
1737 	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1738 	rs = pf_find_ruleset(trs->pfrt_anchor);
1739 	if (rs == NULL || !rs->topen || ticket != rs->tticket)
1740 		return (EBUSY);
1741 
1742 	SLIST_INIT(&workq);
1743 	RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1744 		if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
1745 		    pfr_skip_table(trs, p, 0))
1746 			continue;
1747 		SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1748 		if (p->pfrkt_flags & PFR_TFLAG_ACTIVE)
1749 			xchange++;
1750 		else
1751 			xadd++;
1752 	}
1753 
1754 	if (!(flags & PFR_FLAG_DUMMY)) {
1755 		for (p = SLIST_FIRST(&workq); p != NULL; p = q) {
1756 			q = SLIST_NEXT(p, pfrkt_workq);
1757 			pfr_commit_ktable(p, tzero);
1758 		}
1759 		rs->topen = 0;
1760 		pf_remove_if_empty_ruleset(rs);
1761 	}
1762 	if (nadd != NULL)
1763 		*nadd = xadd;
1764 	if (nchange != NULL)
1765 		*nchange = xchange;
1766 
1767 	return (0);
1768 }
1769 
1770 void
1771 pfr_commit_ktable(struct pfr_ktable *kt, time_t tzero)
1772 {
1773 	struct pfr_ktable	*shadow = kt->pfrkt_shadow;
1774 	int			 nflags;
1775 
1776 	if (shadow->pfrkt_cnt == NO_ADDRESSES) {
1777 		if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
1778 			pfr_clstats_ktable(kt, tzero, 1);
1779 	} else if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) {
1780 		/* kt might contain addresses */
1781 		struct pfr_kentryworkq	 addrq, addq, changeq, delq, garbageq;
1782 		struct pfr_kentry	*p, *q, *next;
1783 		struct pfr_addr		 ad;
1784 
1785 		pfr_enqueue_addrs(shadow, &addrq, NULL, 0);
1786 		pfr_mark_addrs(kt);
1787 		SLIST_INIT(&addq);
1788 		SLIST_INIT(&changeq);
1789 		SLIST_INIT(&delq);
1790 		SLIST_INIT(&garbageq);
1791 		pfr_clean_node_mask(shadow, &addrq);
1792 		for (p = SLIST_FIRST(&addrq); p != NULL; p = next) {
1793 			next = SLIST_NEXT(p, pfrke_workq);	/* XXX */
1794 			pfr_copyout_addr(&ad, p);
1795 			q = pfr_lookup_addr(kt, &ad, 1);
1796 			if (q != NULL) {
1797 				if ((q->pfrke_flags & PFRKE_FLAG_NOT) !=
1798 				    (p->pfrke_flags & PFRKE_FLAG_NOT))
1799 					SLIST_INSERT_HEAD(&changeq, q,
1800 					    pfrke_workq);
1801 				q->pfrke_flags |= PFRKE_FLAG_MARK;
1802 				SLIST_INSERT_HEAD(&garbageq, p, pfrke_workq);
1803 			} else {
1804 				p->pfrke_tzero = tzero;
1805 				SLIST_INSERT_HEAD(&addq, p, pfrke_workq);
1806 			}
1807 		}
1808 		pfr_enqueue_addrs(kt, &delq, NULL, ENQUEUE_UNMARKED_ONLY);
1809 		pfr_insert_kentries(kt, &addq, tzero);
1810 		pfr_remove_kentries(kt, &delq);
1811 		pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG);
1812 		pfr_destroy_kentries(&garbageq);
1813 	} else {
1814 		/* kt cannot contain addresses */
1815 		SWAP(struct radix_node_head *, kt->pfrkt_ip4,
1816 		    shadow->pfrkt_ip4);
1817 		SWAP(struct radix_node_head *, kt->pfrkt_ip6,
1818 		    shadow->pfrkt_ip6);
1819 		SWAP(int, kt->pfrkt_cnt, shadow->pfrkt_cnt);
1820 		pfr_clstats_ktable(kt, tzero, 1);
1821 	}
1822 	nflags = ((shadow->pfrkt_flags & PFR_TFLAG_USRMASK) |
1823 	    (kt->pfrkt_flags & PFR_TFLAG_SETMASK) | PFR_TFLAG_ACTIVE)
1824 		& ~PFR_TFLAG_INACTIVE;
1825 	pfr_destroy_ktable(shadow, 0);
1826 	kt->pfrkt_shadow = NULL;
1827 	pfr_setflags_ktable(kt, nflags);
1828 }
1829 
1830 int
1831 pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved)
1832 {
1833 	int i;
1834 
1835 	if (!tbl->pfrt_name[0])
1836 		return (-1);
1837 	if (no_reserved && !strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR))
1838 		 return (-1);
1839 	if (tbl->pfrt_name[PF_TABLE_NAME_SIZE-1])
1840 		return (-1);
1841 	for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++)
1842 		if (tbl->pfrt_name[i])
1843 			return (-1);
1844 	if (pfr_fix_anchor(tbl->pfrt_anchor))
1845 		return (-1);
1846 	if (tbl->pfrt_flags & ~allowedflags)
1847 		return (-1);
1848 	return (0);
1849 }
1850 
1851 /*
1852  * Rewrite anchors referenced by tables to remove slashes
1853  * and check for validity.
1854  */
1855 int
1856 pfr_fix_anchor(char *anchor)
1857 {
1858 	size_t siz = MAXPATHLEN;
1859 	int i;
1860 
1861 	if (anchor[0] == '/') {
1862 		char *path;
1863 		int off;
1864 
1865 		path = anchor;
1866 		off = 1;
1867 		while (*++path == '/')
1868 			off++;
1869 		bcopy(path, anchor, siz - off);
1870 		memset(anchor + siz - off, 0, off);
1871 	}
1872 	if (anchor[siz - 1])
1873 		return (-1);
1874 	for (i = strlen(anchor); i < siz; i++)
1875 		if (anchor[i])
1876 			return (-1);
1877 	return (0);
1878 }
1879 
1880 int
1881 pfr_table_count(struct pfr_table *filter, int flags)
1882 {
1883 	struct pf_ruleset *rs;
1884 
1885 	if (flags & PFR_FLAG_ALLRSETS)
1886 		return (pfr_ktable_cnt);
1887 	if (filter->pfrt_anchor[0]) {
1888 		rs = pf_find_ruleset(filter->pfrt_anchor);
1889 		return ((rs != NULL) ? rs->tables : -1);
1890 	}
1891 	return (pf_main_ruleset.tables);
1892 }
1893 
1894 int
1895 pfr_skip_table(struct pfr_table *filter, struct pfr_ktable *kt, int flags)
1896 {
1897 	if (flags & PFR_FLAG_ALLRSETS)
1898 		return (0);
1899 	if (strcmp(filter->pfrt_anchor, kt->pfrkt_anchor))
1900 		return (1);
1901 	return (0);
1902 }
1903 
1904 void
1905 pfr_insert_ktables(struct pfr_ktableworkq *workq)
1906 {
1907 	struct pfr_ktable	*p;
1908 
1909 	SLIST_FOREACH(p, workq, pfrkt_workq)
1910 		pfr_insert_ktable(p);
1911 }
1912 
1913 void
1914 pfr_insert_ktable(struct pfr_ktable *kt)
1915 {
1916 	RB_INSERT(pfr_ktablehead, &pfr_ktables, kt);
1917 	pfr_ktable_cnt++;
1918 	if (kt->pfrkt_root != NULL)
1919 		if (!kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR]++)
1920 			pfr_setflags_ktable(kt->pfrkt_root,
1921 			    kt->pfrkt_root->pfrkt_flags|PFR_TFLAG_REFDANCHOR);
1922 }
1923 
1924 void
1925 pfr_setflags_ktables(struct pfr_ktableworkq *workq)
1926 {
1927 	struct pfr_ktable	*p, *q;
1928 
1929 	for (p = SLIST_FIRST(workq); p; p = q) {
1930 		q = SLIST_NEXT(p, pfrkt_workq);
1931 		pfr_setflags_ktable(p, p->pfrkt_nflags);
1932 	}
1933 }
1934 
1935 void
1936 pfr_setflags_ktable(struct pfr_ktable *kt, int newf)
1937 {
1938 	struct pfr_kentryworkq	addrq;
1939 
1940 	if (!(newf & PFR_TFLAG_REFERENCED) &&
1941 	    !(newf & PFR_TFLAG_REFDANCHOR) &&
1942 	    !(newf & PFR_TFLAG_PERSIST))
1943 		newf &= ~PFR_TFLAG_ACTIVE;
1944 	if (!(newf & PFR_TFLAG_ACTIVE))
1945 		newf &= ~PFR_TFLAG_USRMASK;
1946 	if (!(newf & PFR_TFLAG_SETMASK)) {
1947 		RB_REMOVE(pfr_ktablehead, &pfr_ktables, kt);
1948 		if (kt->pfrkt_root != NULL)
1949 			if (!--kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR])
1950 				pfr_setflags_ktable(kt->pfrkt_root,
1951 				    kt->pfrkt_root->pfrkt_flags &
1952 					~PFR_TFLAG_REFDANCHOR);
1953 		pfr_destroy_ktable(kt, 1);
1954 		pfr_ktable_cnt--;
1955 		return;
1956 	}
1957 	if (!(newf & PFR_TFLAG_ACTIVE) && kt->pfrkt_cnt) {
1958 		pfr_enqueue_addrs(kt, &addrq, NULL, 0);
1959 		pfr_remove_kentries(kt, &addrq);
1960 	}
1961 	if (!(newf & PFR_TFLAG_INACTIVE) && kt->pfrkt_shadow != NULL) {
1962 		pfr_destroy_ktable(kt->pfrkt_shadow, 1);
1963 		kt->pfrkt_shadow = NULL;
1964 	}
1965 	kt->pfrkt_flags = newf;
1966 }
1967 
1968 void
1969 pfr_clstats_ktables(struct pfr_ktableworkq *workq, time_t tzero, int recurse)
1970 {
1971 	struct pfr_ktable	*p;
1972 
1973 	SLIST_FOREACH(p, workq, pfrkt_workq)
1974 		pfr_clstats_ktable(p, tzero, recurse);
1975 }
1976 
1977 void
1978 pfr_clstats_ktable(struct pfr_ktable *kt, time_t tzero, int recurse)
1979 {
1980 	struct pfr_kentryworkq	 addrq;
1981 
1982 	if (recurse) {
1983 		pfr_enqueue_addrs(kt, &addrq, NULL, 0);
1984 		pfr_clstats_kentries(&addrq, tzero, 0);
1985 	}
1986 	bzero(kt->pfrkt_packets, sizeof(kt->pfrkt_packets));
1987 	bzero(kt->pfrkt_bytes, sizeof(kt->pfrkt_bytes));
1988 	kt->pfrkt_match = kt->pfrkt_nomatch = 0;
1989 	kt->pfrkt_tzero = tzero;
1990 }
1991 
1992 struct pfr_ktable *
1993 pfr_create_ktable(struct pfr_table *tbl, time_t tzero, int attachruleset,
1994     int intr)
1995 {
1996 	struct pfr_ktable	*kt;
1997 	struct pf_ruleset	*rs;
1998 
1999 	if (intr)
2000 		kt = pool_get(&pfr_ktable_pl, PR_NOWAIT|PR_ZERO|PR_LIMITFAIL);
2001 	else
2002 		kt = pool_get(&pfr_ktable_pl, PR_WAITOK|PR_ZERO|PR_LIMITFAIL);
2003 	if (kt == NULL)
2004 		return (NULL);
2005 	kt->pfrkt_t = *tbl;
2006 
2007 	if (attachruleset) {
2008 		rs = pf_find_or_create_ruleset(tbl->pfrt_anchor);
2009 		if (!rs) {
2010 			pfr_destroy_ktable(kt, 0);
2011 			return (NULL);
2012 		}
2013 		kt->pfrkt_rs = rs;
2014 		rs->tables++;
2015 	}
2016 
2017 	if (!rn_inithead((void **)&kt->pfrkt_ip4,
2018 	    offsetof(struct sockaddr_in, sin_addr)) ||
2019 	    !rn_inithead((void **)&kt->pfrkt_ip6,
2020 	    offsetof(struct sockaddr_in6, sin6_addr))) {
2021 		pfr_destroy_ktable(kt, 0);
2022 		return (NULL);
2023 	}
2024 	kt->pfrkt_tzero = tzero;
2025 	kt->pfrkt_refcntcost = 0;
2026 	kt->pfrkt_gcdweight = 0;
2027 	kt->pfrkt_maxweight = 1;
2028 
2029 	return (kt);
2030 }
2031 
2032 void
2033 pfr_destroy_ktables(struct pfr_ktableworkq *workq, int flushaddr)
2034 {
2035 	struct pfr_ktable	*p, *q;
2036 
2037 	for (p = SLIST_FIRST(workq); p; p = q) {
2038 		q = SLIST_NEXT(p, pfrkt_workq);
2039 		pfr_destroy_ktable(p, flushaddr);
2040 	}
2041 }
2042 
2043 void
2044 pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
2045 {
2046 	struct pfr_kentryworkq	 addrq;
2047 
2048 	if (flushaddr) {
2049 		pfr_enqueue_addrs(kt, &addrq, NULL, 0);
2050 		pfr_clean_node_mask(kt, &addrq);
2051 		pfr_destroy_kentries(&addrq);
2052 	}
2053 	if (kt->pfrkt_ip4 != NULL)
2054 		free(kt->pfrkt_ip4, M_RTABLE, sizeof(*kt->pfrkt_ip4));
2055 	if (kt->pfrkt_ip6 != NULL)
2056 		free(kt->pfrkt_ip6, M_RTABLE, sizeof(*kt->pfrkt_ip6));
2057 	if (kt->pfrkt_shadow != NULL)
2058 		pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr);
2059 	if (kt->pfrkt_rs != NULL) {
2060 		kt->pfrkt_rs->tables--;
2061 		pf_remove_if_empty_ruleset(kt->pfrkt_rs);
2062 	}
2063 	pool_put(&pfr_ktable_pl, kt);
2064 }
2065 
2066 int
2067 pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q)
2068 {
2069 	int d;
2070 
2071 	if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE)))
2072 		return (d);
2073 	return (strcmp(p->pfrkt_anchor, q->pfrkt_anchor));
2074 }
2075 
2076 struct pfr_ktable *
2077 pfr_lookup_table(struct pfr_table *tbl)
2078 {
2079 	/* struct pfr_ktable start like a struct pfr_table */
2080 	return (RB_FIND(pfr_ktablehead, &pfr_ktables,
2081 	    (struct pfr_ktable *)tbl));
2082 }
2083 
2084 int
2085 pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
2086 {
2087 	struct pfr_kentry	*ke = NULL;
2088 	int			 match;
2089 
2090 	ke = pfr_kentry_byaddr(kt, a, af, 0);
2091 
2092 	match = (ke && !(ke->pfrke_flags & PFRKE_FLAG_NOT));
2093 	if (match)
2094 		kt->pfrkt_match++;
2095 	else
2096 		kt->pfrkt_nomatch++;
2097 
2098 	return (match);
2099 }
2100 
2101 struct pfr_kentry *
2102 pfr_kentry_byaddr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
2103     int exact)
2104 {
2105 	struct pfr_kentry	*ke = NULL;
2106 	struct sockaddr_in	 tmp4;
2107 #ifdef INET6
2108 	struct sockaddr_in6	 tmp6;
2109 #endif /* INET6 */
2110 
2111 	kt = pfr_ktable_select_active(kt);
2112 	if (kt == NULL)
2113 		return (0);
2114 
2115 	switch (af) {
2116 	case AF_INET:
2117 		bzero(&tmp4, sizeof(tmp4));
2118 		tmp4.sin_len = sizeof(tmp4);
2119 		tmp4.sin_family = AF_INET;
2120 		tmp4.sin_addr.s_addr = a->addr32[0];
2121 		ke = (struct pfr_kentry *)rn_match(&tmp4, kt->pfrkt_ip4);
2122 		break;
2123 #ifdef INET6
2124 	case AF_INET6:
2125 		bzero(&tmp6, sizeof(tmp6));
2126 		tmp6.sin6_len = sizeof(tmp6);
2127 		tmp6.sin6_family = AF_INET6;
2128 		bcopy(a, &tmp6.sin6_addr, sizeof(tmp6.sin6_addr));
2129 		ke = (struct pfr_kentry *)rn_match(&tmp6, kt->pfrkt_ip6);
2130 		break;
2131 #endif /* INET6 */
2132 	default:
2133 		unhandled_af(af);
2134 	}
2135 	if (exact && ke && KENTRY_NETWORK(ke))
2136 		ke = NULL;
2137 
2138 	return (ke);
2139 }
2140 
2141 void
2142 pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, struct pf_pdesc *pd,
2143     int op, int notrule)
2144 {
2145 	struct pfr_kentry	*ke = NULL;
2146 	struct sockaddr_in	 tmp4;
2147 #ifdef INET6
2148 	struct sockaddr_in6	 tmp6;
2149 #endif /* INET6 */
2150 	sa_family_t		 af = pd->af;
2151 	u_int64_t		 len = pd->tot_len;
2152 	int			 dir_idx = (pd->dir == PF_OUT);
2153 	int			 op_idx;
2154 
2155 	kt = pfr_ktable_select_active(kt);
2156 	if (kt == NULL)
2157 		return;
2158 
2159 	switch (af) {
2160 	case AF_INET:
2161 		bzero(&tmp4, sizeof(tmp4));
2162 		tmp4.sin_len = sizeof(tmp4);
2163 		tmp4.sin_family = AF_INET;
2164 		tmp4.sin_addr.s_addr = a->addr32[0];
2165 		ke = (struct pfr_kentry *)rn_match(&tmp4, kt->pfrkt_ip4);
2166 		break;
2167 #ifdef INET6
2168 	case AF_INET6:
2169 		bzero(&tmp6, sizeof(tmp6));
2170 		tmp6.sin6_len = sizeof(tmp6);
2171 		tmp6.sin6_family = AF_INET6;
2172 		bcopy(a, &tmp6.sin6_addr, sizeof(tmp6.sin6_addr));
2173 		ke = (struct pfr_kentry *)rn_match(&tmp6, kt->pfrkt_ip6);
2174 		break;
2175 #endif /* INET6 */
2176 	default:
2177 		unhandled_af(af);
2178 	}
2179 
2180 	switch (op) {
2181 	case PF_PASS:
2182 		op_idx = PFR_OP_PASS;
2183 		break;
2184 	case PF_MATCH:
2185 		op_idx = PFR_OP_MATCH;
2186 		break;
2187 	case PF_DROP:
2188 		op_idx = PFR_OP_BLOCK;
2189 		break;
2190 	default:
2191 		panic("unhandled op");
2192 	}
2193 
2194 	if ((ke == NULL || (ke->pfrke_flags & PFRKE_FLAG_NOT)) != notrule) {
2195 		if (op_idx != PFR_OP_PASS)
2196 			DPFPRINTF(LOG_DEBUG,
2197 			    "pfr_update_stats: assertion failed.");
2198 		op_idx = PFR_OP_XPASS;
2199 	}
2200 	kt->pfrkt_packets[dir_idx][op_idx]++;
2201 	kt->pfrkt_bytes[dir_idx][op_idx] += len;
2202 	if (ke != NULL && op_idx != PFR_OP_XPASS &&
2203 	    (kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) {
2204 		if (ke->pfrke_counters == NULL)
2205 			ke->pfrke_counters = pool_get(&pfr_kcounters_pl,
2206 			    PR_NOWAIT | PR_ZERO);
2207 		if (ke->pfrke_counters != NULL) {
2208 			ke->pfrke_counters->pfrkc_packets[dir_idx][op_idx]++;
2209 			ke->pfrke_counters->pfrkc_bytes[dir_idx][op_idx] += len;
2210 		}
2211 	}
2212 }
2213 
2214 struct pfr_ktable *
2215 pfr_attach_table(struct pf_ruleset *rs, char *name, int intr)
2216 {
2217 	struct pfr_ktable	*kt, *rt;
2218 	struct pfr_table	 tbl;
2219 	struct pf_anchor	*ac = rs->anchor;
2220 
2221 	bzero(&tbl, sizeof(tbl));
2222 	strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name));
2223 	if (ac != NULL)
2224 		strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor));
2225 	kt = pfr_lookup_table(&tbl);
2226 	if (kt == NULL) {
2227 		kt = pfr_create_ktable(&tbl, gettime(), 1, intr);
2228 		if (kt == NULL)
2229 			return (NULL);
2230 		if (ac != NULL) {
2231 			bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor));
2232 			rt = pfr_lookup_table(&tbl);
2233 			if (rt == NULL) {
2234 				rt = pfr_create_ktable(&tbl, 0, 1, intr);
2235 				if (rt == NULL) {
2236 					pfr_destroy_ktable(kt, 0);
2237 					return (NULL);
2238 				}
2239 				pfr_insert_ktable(rt);
2240 			}
2241 			kt->pfrkt_root = rt;
2242 		}
2243 		pfr_insert_ktable(kt);
2244 	}
2245 	if (!kt->pfrkt_refcnt[PFR_REFCNT_RULE]++)
2246 		pfr_setflags_ktable(kt, kt->pfrkt_flags|PFR_TFLAG_REFERENCED);
2247 	return (kt);
2248 }
2249 
2250 void
2251 pfr_detach_table(struct pfr_ktable *kt)
2252 {
2253 	if (kt->pfrkt_refcnt[PFR_REFCNT_RULE] <= 0)
2254 		DPFPRINTF(LOG_NOTICE, "pfr_detach_table: refcount = %d.",
2255 		    kt->pfrkt_refcnt[PFR_REFCNT_RULE]);
2256 	else if (!--kt->pfrkt_refcnt[PFR_REFCNT_RULE])
2257 		pfr_setflags_ktable(kt, kt->pfrkt_flags&~PFR_TFLAG_REFERENCED);
2258 }
2259 
2260 int
2261 pfr_islinklocal(sa_family_t af, struct pf_addr *addr)
2262 {
2263 #ifdef	INET6
2264 	if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&addr->v6))
2265 		return (1);
2266 #endif	/* INET6 */
2267 	return (0);
2268 }
2269 
2270 int
2271 pfr_pool_get(struct pf_pool *rpool, struct pf_addr **raddr,
2272     struct pf_addr **rmask, sa_family_t af)
2273 {
2274 	struct pfr_ktable	*kt;
2275 	struct pfr_kentry	*ke, *ke2;
2276 	struct pf_addr		*addr, *counter;
2277 	union sockaddr_union	 mask;
2278 	struct sockaddr_in	 tmp4;
2279 #ifdef INET6
2280 	struct sockaddr_in6	 tmp6;
2281 #endif
2282 	int			 startidx, idx = -1, loop = 0, use_counter = 0;
2283 
2284 	switch (af) {
2285 	case AF_INET:
2286 		bzero(&tmp4, sizeof(tmp4));
2287 		tmp4.sin_len = sizeof(tmp4);
2288 		tmp4.sin_family = AF_INET;
2289 		addr = (struct pf_addr *)&tmp4.sin_addr;
2290 		break;
2291 #ifdef	INET6
2292 	case AF_INET6:
2293 		bzero(&tmp6, sizeof(tmp6));
2294 		tmp6.sin6_len = sizeof(tmp6);
2295 		tmp6.sin6_family = AF_INET6;
2296 		addr = (struct pf_addr *)&tmp6.sin6_addr;
2297 		break;
2298 #endif	/* INET6 */
2299 	default:
2300 		unhandled_af(af);
2301 	}
2302 
2303 	if (rpool->addr.type == PF_ADDR_TABLE)
2304 		kt = rpool->addr.p.tbl;
2305 	else if (rpool->addr.type == PF_ADDR_DYNIFTL)
2306 		kt = rpool->addr.p.dyn->pfid_kt;
2307 	else
2308 		return (-1);
2309 	kt = pfr_ktable_select_active(kt);
2310 	if (kt == NULL)
2311 		return (-1);
2312 
2313 	counter = &rpool->counter;
2314 	idx = rpool->tblidx;
2315 	if (idx < 0 || idx >= kt->pfrkt_cnt)
2316 		idx = 0;
2317 	else
2318 		use_counter = 1;
2319 	startidx = idx;
2320 
2321  _next_block:
2322 	if (loop && startidx == idx) {
2323 		kt->pfrkt_nomatch++;
2324 		return (1);
2325 	}
2326 
2327 	ke = pfr_kentry_byidx(kt, idx, af);
2328 	if (ke == NULL) {
2329 		/* we don't have this idx, try looping */
2330 		if (loop || (ke = pfr_kentry_byidx(kt, 0, af)) == NULL) {
2331 			kt->pfrkt_nomatch++;
2332 			return (1);
2333 		}
2334 		idx = 0;
2335 		loop++;
2336 	}
2337 
2338 	/* Get current weight for weighted round-robin */
2339 	if (idx == 0 && use_counter == 1 && kt->pfrkt_refcntcost > 0) {
2340 		rpool->curweight = rpool->curweight - kt->pfrkt_gcdweight;
2341 
2342 		if (rpool->curweight < 1)
2343 			rpool->curweight = kt->pfrkt_maxweight;
2344 	}
2345 
2346 	pfr_prepare_network(&pfr_mask, af, ke->pfrke_net);
2347 	*raddr = SUNION2PF(&ke->pfrke_sa, af);
2348 	*rmask = SUNION2PF(&pfr_mask, af);
2349 
2350 	if (use_counter && !PF_AZERO(counter, af)) {
2351 		/* is supplied address within block? */
2352 		if (!pf_match_addr(0, *raddr, *rmask, counter, af)) {
2353 			/* no, go to next block in table */
2354 			idx++;
2355 			use_counter = 0;
2356 			goto _next_block;
2357 		}
2358 		pf_addrcpy(addr, counter, af);
2359 	} else {
2360 		/* use first address of block */
2361 		pf_addrcpy(addr, *raddr, af);
2362 	}
2363 
2364 	if (!KENTRY_NETWORK(ke)) {
2365 		/* this is a single IP address - no possible nested block */
2366 		if (rpool->addr.type == PF_ADDR_DYNIFTL &&
2367 		    pfr_islinklocal(af, addr)) {
2368 			idx++;
2369 			goto _next_block;
2370 		}
2371 		pf_addrcpy(counter, addr, af);
2372 		rpool->tblidx = idx;
2373 		kt->pfrkt_match++;
2374 		rpool->states = 0;
2375 		if (ke->pfrke_counters != NULL)
2376 			rpool->states = ke->pfrke_counters->states;
2377 		switch (ke->pfrke_type) {
2378 		case PFRKE_COST:
2379 			rpool->weight = ((struct pfr_kentry_cost *)ke)->weight;
2380 			/* FALLTHROUGH */
2381 		case PFRKE_ROUTE:
2382 			rpool->kif = ((struct pfr_kentry_route *)ke)->kif;
2383 			break;
2384 		default:
2385 			rpool->weight = 1;
2386 			break;
2387 		}
2388 		return (0);
2389 	}
2390 	for (;;) {
2391 		/* we don't want to use a nested block */
2392 		switch (af) {
2393 		case AF_INET:
2394 			ke2 = (struct pfr_kentry *)rn_match(&tmp4,
2395 			    kt->pfrkt_ip4);
2396 			break;
2397 #ifdef	INET6
2398 		case AF_INET6:
2399 			ke2 = (struct pfr_kentry *)rn_match(&tmp6,
2400 			    kt->pfrkt_ip6);
2401 			break;
2402 #endif	/* INET6 */
2403 		default:
2404 			unhandled_af(af);
2405 		}
2406 		if (ke2 == ke) {
2407 			/* lookup return the same block - perfect */
2408 			if (rpool->addr.type == PF_ADDR_DYNIFTL &&
2409 			    pfr_islinklocal(af, addr))
2410 				goto _next_entry;
2411 			pf_addrcpy(counter, addr, af);
2412 			rpool->tblidx = idx;
2413 			kt->pfrkt_match++;
2414 			rpool->states = 0;
2415 			if (ke->pfrke_counters != NULL)
2416 				rpool->states = ke->pfrke_counters->states;
2417 			switch (ke->pfrke_type) {
2418 			case PFRKE_COST:
2419 				rpool->weight =
2420 				    ((struct pfr_kentry_cost *)ke)->weight;
2421 				/* FALLTHROUGH */
2422 			case PFRKE_ROUTE:
2423 				rpool->kif = ((struct pfr_kentry_route *)ke)->kif;
2424 				break;
2425 			default:
2426 				rpool->weight = 1;
2427 				break;
2428 			}
2429 			return (0);
2430 		}
2431 _next_entry:
2432 		/* we need to increase the counter past the nested block */
2433 		pfr_prepare_network(&mask, AF_INET, ke2->pfrke_net);
2434 		pf_poolmask(addr, addr, SUNION2PF(&mask, af), &pfr_ffaddr, af);
2435 		pf_addr_inc(addr, af);
2436 		if (!pf_match_addr(0, *raddr, *rmask, addr, af)) {
2437 			/* ok, we reached the end of our main block */
2438 			/* go to next block in table */
2439 			idx++;
2440 			use_counter = 0;
2441 			goto _next_block;
2442 		}
2443 	}
2444 }
2445 
2446 struct pfr_kentry *
2447 pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
2448 {
2449 	struct pfr_walktree	w;
2450 
2451 	bzero(&w, sizeof(w));
2452 	w.pfrw_op = PFRW_POOL_GET;
2453 	w.pfrw_cnt = idx;
2454 
2455 	switch (af) {
2456 	case AF_INET:
2457 		rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
2458 		return (w.pfrw_kentry);
2459 #ifdef INET6
2460 	case AF_INET6:
2461 		rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
2462 		return (w.pfrw_kentry);
2463 #endif /* INET6 */
2464 	default:
2465 		return (NULL);
2466 	}
2467 }
2468 
2469 /* Added for load balancing state counter use. */
2470 int
2471 pfr_states_increase(struct pfr_ktable *kt, struct pf_addr *addr, int af)
2472 {
2473 	struct pfr_kentry *ke;
2474 
2475 	ke = pfr_kentry_byaddr(kt, addr, af, 1);
2476 	if (ke == NULL)
2477 		return (-1);
2478 
2479 	if (ke->pfrke_counters == NULL)
2480 		ke->pfrke_counters = pool_get(&pfr_kcounters_pl,
2481 		    PR_NOWAIT | PR_ZERO);
2482 	if (ke->pfrke_counters == NULL)
2483 		return (-1);
2484 
2485 	ke->pfrke_counters->states++;
2486 	return ke->pfrke_counters->states;
2487 }
2488 
2489 /* Added for load balancing state counter use. */
2490 int
2491 pfr_states_decrease(struct pfr_ktable *kt, struct pf_addr *addr, int af)
2492 {
2493 	struct pfr_kentry *ke;
2494 
2495 	ke = pfr_kentry_byaddr(kt, addr, af, 1);
2496 	if (ke == NULL)
2497 		return (-1);
2498 
2499 	if (ke->pfrke_counters == NULL)
2500 		ke->pfrke_counters = pool_get(&pfr_kcounters_pl,
2501 		    PR_NOWAIT | PR_ZERO);
2502 	if (ke->pfrke_counters == NULL)
2503 		return (-1);
2504 
2505 	if (ke->pfrke_counters->states > 0)
2506 		ke->pfrke_counters->states--;
2507 	else
2508 		DPFPRINTF(LOG_DEBUG,
2509 		    "pfr_states_decrease: states-- when states <= 0");
2510 
2511 	return ke->pfrke_counters->states;
2512 }
2513 
2514 void
2515 pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn)
2516 {
2517 	struct pfr_walktree	w;
2518 
2519 	bzero(&w, sizeof(w));
2520 	w.pfrw_op = PFRW_DYNADDR_UPDATE;
2521 	w.pfrw_dyn = dyn;
2522 
2523 	dyn->pfid_acnt4 = 0;
2524 	dyn->pfid_acnt6 = 0;
2525 	switch (dyn->pfid_af) {
2526 	case AF_UNSPEC:	/* look up all both addresses IPv4 + IPv6 */
2527 		rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
2528 		rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
2529 		break;
2530 	case AF_INET:
2531 		rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
2532 		break;
2533 #ifdef	INET6
2534 	case AF_INET6:
2535 		rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
2536 		break;
2537 #endif	/* INET6 */
2538 	default:
2539 		unhandled_af(dyn->pfid_af);
2540 	}
2541 }
2542 
2543 void
2544 pfr_ktable_winfo_update(struct pfr_ktable *kt, struct pfr_kentry *p) {
2545 	/*
2546 	 * If cost flag is set,
2547 	 * gcdweight is needed for round-robin.
2548 	 */
2549 	if (kt->pfrkt_refcntcost > 0) {
2550 		u_int16_t weight;
2551 
2552 		weight = (p->pfrke_type == PFRKE_COST) ?
2553 		    ((struct pfr_kentry_cost *)p)->weight : 1;
2554 
2555 		if (kt->pfrkt_gcdweight == 0)
2556 			kt->pfrkt_gcdweight = weight;
2557 
2558 		kt->pfrkt_gcdweight =
2559 			pfr_gcd(weight, kt->pfrkt_gcdweight);
2560 
2561 		if (kt->pfrkt_maxweight < weight)
2562 			kt->pfrkt_maxweight = weight;
2563 	}
2564 }
2565 
2566 struct pfr_ktable *
2567 pfr_ktable_select_active(struct pfr_ktable *kt)
2568 {
2569 	if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
2570 		kt = kt->pfrkt_root;
2571 	if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
2572 		return (NULL);
2573 
2574 	return (kt);
2575 }
2576