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