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