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