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