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