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