pf_table.c revision 273196
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: releng/10.1/sys/netpfil/pf/pf_table.c 273196 2014-10-16 23:03:04Z glebius $");
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					goto _skip;
1128			}
1129			SLIST_INSERT_HEAD(&addq, p, pfrkt_workq);
1130			xadd++;
1131			if (!key.pfrkt_anchor[0])
1132				goto _skip;
1133
1134			/* find or create root table */
1135			bzero(key.pfrkt_anchor, sizeof(key.pfrkt_anchor));
1136			r = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1137			if (r != NULL) {
1138				p->pfrkt_root = r;
1139				goto _skip;
1140			}
1141			SLIST_FOREACH(q, &addq, pfrkt_workq) {
1142				if (!pfr_ktable_compare(&key, q)) {
1143					p->pfrkt_root = q;
1144					goto _skip;
1145				}
1146			}
1147			key.pfrkt_flags = 0;
1148			r = pfr_create_ktable(&key.pfrkt_t, 0, 1);
1149			if (r == NULL)
1150				senderr(ENOMEM);
1151			SLIST_INSERT_HEAD(&addq, r, pfrkt_workq);
1152			p->pfrkt_root = r;
1153		} else if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1154			SLIST_FOREACH(q, &changeq, pfrkt_workq)
1155				if (!pfr_ktable_compare(&key, q))
1156					goto _skip;
1157			p->pfrkt_nflags = (p->pfrkt_flags &
1158			    ~PFR_TFLAG_USRMASK) | key.pfrkt_flags;
1159			SLIST_INSERT_HEAD(&changeq, p, pfrkt_workq);
1160			xadd++;
1161		}
1162_skip:
1163	;
1164	}
1165	if (!(flags & PFR_FLAG_DUMMY)) {
1166		pfr_insert_ktables(&addq);
1167		pfr_setflags_ktables(&changeq);
1168	} else
1169		 pfr_destroy_ktables(&addq, 0);
1170	if (nadd != NULL)
1171		*nadd = xadd;
1172	return (0);
1173_bad:
1174	pfr_destroy_ktables(&addq, 0);
1175	return (rv);
1176}
1177
1178int
1179pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
1180{
1181	struct pfr_ktableworkq	 workq;
1182	struct pfr_ktable	*p, *q, key;
1183	int			 i, xdel = 0;
1184
1185	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1186	SLIST_INIT(&workq);
1187	for (i = 0; i < size; i++) {
1188		bcopy(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t));
1189		if (pfr_validate_table(&key.pfrkt_t, 0,
1190		    flags & PFR_FLAG_USERIOCTL))
1191			return (EINVAL);
1192		p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1193		if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1194			SLIST_FOREACH(q, &workq, pfrkt_workq)
1195				if (!pfr_ktable_compare(p, q))
1196					goto _skip;
1197			p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
1198			SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1199			xdel++;
1200		}
1201_skip:
1202	;
1203	}
1204
1205	if (!(flags & PFR_FLAG_DUMMY))
1206		pfr_setflags_ktables(&workq);
1207	if (ndel != NULL)
1208		*ndel = xdel;
1209	return (0);
1210}
1211
1212int
1213pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
1214	int flags)
1215{
1216	struct pfr_ktable	*p;
1217	int			 n, nn;
1218
1219	PF_RULES_RASSERT();
1220
1221	ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS);
1222	if (pfr_fix_anchor(filter->pfrt_anchor))
1223		return (EINVAL);
1224	n = nn = pfr_table_count(filter, flags);
1225	if (n < 0)
1226		return (ENOENT);
1227	if (n > *size) {
1228		*size = n;
1229		return (0);
1230	}
1231	RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1232		if (pfr_skip_table(filter, p, flags))
1233			continue;
1234		if (n-- <= 0)
1235			continue;
1236		bcopy(&p->pfrkt_t, tbl++, sizeof(*tbl));
1237	}
1238
1239	KASSERT(n == 0, ("%s: corruption detected (%d)", __func__, n));
1240
1241	*size = nn;
1242	return (0);
1243}
1244
1245int
1246pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
1247	int flags)
1248{
1249	struct pfr_ktable	*p;
1250	struct pfr_ktableworkq	 workq;
1251	int			 n, nn;
1252	long			 tzero = time_second;
1253
1254	/* XXX PFR_FLAG_CLSTATS disabled */
1255	ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS);
1256	if (pfr_fix_anchor(filter->pfrt_anchor))
1257		return (EINVAL);
1258	n = nn = pfr_table_count(filter, flags);
1259	if (n < 0)
1260		return (ENOENT);
1261	if (n > *size) {
1262		*size = n;
1263		return (0);
1264	}
1265	SLIST_INIT(&workq);
1266	RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1267		if (pfr_skip_table(filter, p, flags))
1268			continue;
1269		if (n-- <= 0)
1270			continue;
1271		bcopy(&p->pfrkt_ts, tbl++, sizeof(*tbl));
1272		SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1273	}
1274	if (flags & PFR_FLAG_CLSTATS)
1275		pfr_clstats_ktables(&workq, tzero,
1276		    flags & PFR_FLAG_ADDRSTOO);
1277
1278	KASSERT(n == 0, ("%s: corruption detected (%d)", __func__, n));
1279
1280	*size = nn;
1281	return (0);
1282}
1283
1284int
1285pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
1286{
1287	struct pfr_ktableworkq	 workq;
1288	struct pfr_ktable	*p, key;
1289	int			 i, xzero = 0;
1290	long			 tzero = time_second;
1291
1292	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO);
1293	SLIST_INIT(&workq);
1294	for (i = 0; i < size; i++) {
1295		bcopy(tbl + i, &key.pfrkt_t, sizeof(key.pfrkt_t));
1296		if (pfr_validate_table(&key.pfrkt_t, 0, 0))
1297			return (EINVAL);
1298		p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1299		if (p != NULL) {
1300			SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1301			xzero++;
1302		}
1303	}
1304	if (!(flags & PFR_FLAG_DUMMY))
1305		pfr_clstats_ktables(&workq, tzero, flags & PFR_FLAG_ADDRSTOO);
1306	if (nzero != NULL)
1307		*nzero = xzero;
1308	return (0);
1309}
1310
1311int
1312pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
1313	int *nchange, int *ndel, int flags)
1314{
1315	struct pfr_ktableworkq	 workq;
1316	struct pfr_ktable	*p, *q, key;
1317	int			 i, xchange = 0, xdel = 0;
1318
1319	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1320	if ((setflag & ~PFR_TFLAG_USRMASK) ||
1321	    (clrflag & ~PFR_TFLAG_USRMASK) ||
1322	    (setflag & clrflag))
1323		return (EINVAL);
1324	SLIST_INIT(&workq);
1325	for (i = 0; i < size; i++) {
1326		bcopy(tbl + i, &key.pfrkt_t, sizeof(key.pfrkt_t));
1327		if (pfr_validate_table(&key.pfrkt_t, 0,
1328		    flags & PFR_FLAG_USERIOCTL))
1329			return (EINVAL);
1330		p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1331		if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
1332			p->pfrkt_nflags = (p->pfrkt_flags | setflag) &
1333			    ~clrflag;
1334			if (p->pfrkt_nflags == p->pfrkt_flags)
1335				goto _skip;
1336			SLIST_FOREACH(q, &workq, pfrkt_workq)
1337				if (!pfr_ktable_compare(p, q))
1338					goto _skip;
1339			SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1340			if ((p->pfrkt_flags & PFR_TFLAG_PERSIST) &&
1341			    (clrflag & PFR_TFLAG_PERSIST) &&
1342			    !(p->pfrkt_flags & PFR_TFLAG_REFERENCED))
1343				xdel++;
1344			else
1345				xchange++;
1346		}
1347_skip:
1348	;
1349	}
1350	if (!(flags & PFR_FLAG_DUMMY))
1351		pfr_setflags_ktables(&workq);
1352	if (nchange != NULL)
1353		*nchange = xchange;
1354	if (ndel != NULL)
1355		*ndel = xdel;
1356	return (0);
1357}
1358
1359int
1360pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags)
1361{
1362	struct pfr_ktableworkq	 workq;
1363	struct pfr_ktable	*p;
1364	struct pf_ruleset	*rs;
1365	int			 xdel = 0;
1366
1367	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1368	rs = pf_find_or_create_ruleset(trs->pfrt_anchor);
1369	if (rs == NULL)
1370		return (ENOMEM);
1371	SLIST_INIT(&workq);
1372	RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1373		if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
1374		    pfr_skip_table(trs, p, 0))
1375			continue;
1376		p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
1377		SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1378		xdel++;
1379	}
1380	if (!(flags & PFR_FLAG_DUMMY)) {
1381		pfr_setflags_ktables(&workq);
1382		if (ticket != NULL)
1383			*ticket = ++rs->tticket;
1384		rs->topen = 1;
1385	} else
1386		pf_remove_if_empty_ruleset(rs);
1387	if (ndel != NULL)
1388		*ndel = xdel;
1389	return (0);
1390}
1391
1392int
1393pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
1394    int *nadd, int *naddr, u_int32_t ticket, int flags)
1395{
1396	struct pfr_ktableworkq	 tableq;
1397	struct pfr_kentryworkq	 addrq;
1398	struct pfr_ktable	*kt, *rt, *shadow, key;
1399	struct pfr_kentry	*p;
1400	struct pfr_addr		*ad;
1401	struct pf_ruleset	*rs;
1402	int			 i, rv, xadd = 0, xaddr = 0;
1403
1404	PF_RULES_WASSERT();
1405
1406	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO);
1407	if (size && !(flags & PFR_FLAG_ADDRSTOO))
1408		return (EINVAL);
1409	if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
1410	    flags & PFR_FLAG_USERIOCTL))
1411		return (EINVAL);
1412	rs = pf_find_ruleset(tbl->pfrt_anchor);
1413	if (rs == NULL || !rs->topen || ticket != rs->tticket)
1414		return (EBUSY);
1415	tbl->pfrt_flags |= PFR_TFLAG_INACTIVE;
1416	SLIST_INIT(&tableq);
1417	kt = RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)tbl);
1418	if (kt == NULL) {
1419		kt = pfr_create_ktable(tbl, 0, 1);
1420		if (kt == NULL)
1421			return (ENOMEM);
1422		SLIST_INSERT_HEAD(&tableq, kt, pfrkt_workq);
1423		xadd++;
1424		if (!tbl->pfrt_anchor[0])
1425			goto _skip;
1426
1427		/* find or create root table */
1428		bzero(&key, sizeof(key));
1429		strlcpy(key.pfrkt_name, tbl->pfrt_name, sizeof(key.pfrkt_name));
1430		rt = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
1431		if (rt != NULL) {
1432			kt->pfrkt_root = rt;
1433			goto _skip;
1434		}
1435		rt = pfr_create_ktable(&key.pfrkt_t, 0, 1);
1436		if (rt == NULL) {
1437			pfr_destroy_ktables(&tableq, 0);
1438			return (ENOMEM);
1439		}
1440		SLIST_INSERT_HEAD(&tableq, rt, pfrkt_workq);
1441		kt->pfrkt_root = rt;
1442	} else if (!(kt->pfrkt_flags & PFR_TFLAG_INACTIVE))
1443		xadd++;
1444_skip:
1445	shadow = pfr_create_ktable(tbl, 0, 0);
1446	if (shadow == NULL) {
1447		pfr_destroy_ktables(&tableq, 0);
1448		return (ENOMEM);
1449	}
1450	SLIST_INIT(&addrq);
1451	for (i = 0, ad = addr; i < size; i++, ad++) {
1452		if (pfr_validate_addr(ad))
1453			senderr(EINVAL);
1454		if (pfr_lookup_addr(shadow, ad, 1) != NULL)
1455			continue;
1456		p = pfr_create_kentry(ad);
1457		if (p == NULL)
1458			senderr(ENOMEM);
1459		if (pfr_route_kentry(shadow, p)) {
1460			pfr_destroy_kentry(p);
1461			continue;
1462		}
1463		SLIST_INSERT_HEAD(&addrq, p, pfrke_workq);
1464		xaddr++;
1465	}
1466	if (!(flags & PFR_FLAG_DUMMY)) {
1467		if (kt->pfrkt_shadow != NULL)
1468			pfr_destroy_ktable(kt->pfrkt_shadow, 1);
1469		kt->pfrkt_flags |= PFR_TFLAG_INACTIVE;
1470		pfr_insert_ktables(&tableq);
1471		shadow->pfrkt_cnt = (flags & PFR_FLAG_ADDRSTOO) ?
1472		    xaddr : NO_ADDRESSES;
1473		kt->pfrkt_shadow = shadow;
1474	} else {
1475		pfr_clean_node_mask(shadow, &addrq);
1476		pfr_destroy_ktable(shadow, 0);
1477		pfr_destroy_ktables(&tableq, 0);
1478		pfr_destroy_kentries(&addrq);
1479	}
1480	if (nadd != NULL)
1481		*nadd = xadd;
1482	if (naddr != NULL)
1483		*naddr = xaddr;
1484	return (0);
1485_bad:
1486	pfr_destroy_ktable(shadow, 0);
1487	pfr_destroy_ktables(&tableq, 0);
1488	pfr_destroy_kentries(&addrq);
1489	return (rv);
1490}
1491
1492int
1493pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
1494{
1495	struct pfr_ktableworkq	 workq;
1496	struct pfr_ktable	*p;
1497	struct pf_ruleset	*rs;
1498	int			 xdel = 0;
1499
1500	PF_RULES_WASSERT();
1501
1502	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1503	rs = pf_find_ruleset(trs->pfrt_anchor);
1504	if (rs == NULL || !rs->topen || ticket != rs->tticket)
1505		return (0);
1506	SLIST_INIT(&workq);
1507	RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1508		if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
1509		    pfr_skip_table(trs, p, 0))
1510			continue;
1511		p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
1512		SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1513		xdel++;
1514	}
1515	if (!(flags & PFR_FLAG_DUMMY)) {
1516		pfr_setflags_ktables(&workq);
1517		rs->topen = 0;
1518		pf_remove_if_empty_ruleset(rs);
1519	}
1520	if (ndel != NULL)
1521		*ndel = xdel;
1522	return (0);
1523}
1524
1525int
1526pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
1527    int *nchange, int flags)
1528{
1529	struct pfr_ktable	*p, *q;
1530	struct pfr_ktableworkq	 workq;
1531	struct pf_ruleset	*rs;
1532	int			 xadd = 0, xchange = 0;
1533	long			 tzero = time_second;
1534
1535	PF_RULES_WASSERT();
1536
1537	ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY);
1538	rs = pf_find_ruleset(trs->pfrt_anchor);
1539	if (rs == NULL || !rs->topen || ticket != rs->tticket)
1540		return (EBUSY);
1541
1542	SLIST_INIT(&workq);
1543	RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
1544		if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
1545		    pfr_skip_table(trs, p, 0))
1546			continue;
1547		SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
1548		if (p->pfrkt_flags & PFR_TFLAG_ACTIVE)
1549			xchange++;
1550		else
1551			xadd++;
1552	}
1553
1554	if (!(flags & PFR_FLAG_DUMMY)) {
1555		for (p = SLIST_FIRST(&workq); p != NULL; p = q) {
1556			q = SLIST_NEXT(p, pfrkt_workq);
1557			pfr_commit_ktable(p, tzero);
1558		}
1559		rs->topen = 0;
1560		pf_remove_if_empty_ruleset(rs);
1561	}
1562	if (nadd != NULL)
1563		*nadd = xadd;
1564	if (nchange != NULL)
1565		*nchange = xchange;
1566
1567	return (0);
1568}
1569
1570static void
1571pfr_commit_ktable(struct pfr_ktable *kt, long tzero)
1572{
1573	struct pfr_ktable	*shadow = kt->pfrkt_shadow;
1574	int			 nflags;
1575
1576	PF_RULES_WASSERT();
1577
1578	if (shadow->pfrkt_cnt == NO_ADDRESSES) {
1579		if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
1580			pfr_clstats_ktable(kt, tzero, 1);
1581	} else if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) {
1582		/* kt might contain addresses */
1583		struct pfr_kentryworkq	 addrq, addq, changeq, delq, garbageq;
1584		struct pfr_kentry	*p, *q, *next;
1585		struct pfr_addr		 ad;
1586
1587		pfr_enqueue_addrs(shadow, &addrq, NULL, 0);
1588		pfr_mark_addrs(kt);
1589		SLIST_INIT(&addq);
1590		SLIST_INIT(&changeq);
1591		SLIST_INIT(&delq);
1592		SLIST_INIT(&garbageq);
1593		pfr_clean_node_mask(shadow, &addrq);
1594		for (p = SLIST_FIRST(&addrq); p != NULL; p = next) {
1595			next = SLIST_NEXT(p, pfrke_workq);	/* XXX */
1596			pfr_copyout_addr(&ad, p);
1597			q = pfr_lookup_addr(kt, &ad, 1);
1598			if (q != NULL) {
1599				if (q->pfrke_not != p->pfrke_not)
1600					SLIST_INSERT_HEAD(&changeq, q,
1601					    pfrke_workq);
1602				q->pfrke_mark = 1;
1603				SLIST_INSERT_HEAD(&garbageq, p, pfrke_workq);
1604			} else {
1605				p->pfrke_tzero = tzero;
1606				SLIST_INSERT_HEAD(&addq, p, pfrke_workq);
1607			}
1608		}
1609		pfr_enqueue_addrs(kt, &delq, NULL, ENQUEUE_UNMARKED_ONLY);
1610		pfr_insert_kentries(kt, &addq, tzero);
1611		pfr_remove_kentries(kt, &delq);
1612		pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG);
1613		pfr_destroy_kentries(&garbageq);
1614	} else {
1615		/* kt cannot contain addresses */
1616		SWAP(struct radix_node_head *, kt->pfrkt_ip4,
1617		    shadow->pfrkt_ip4);
1618		SWAP(struct radix_node_head *, kt->pfrkt_ip6,
1619		    shadow->pfrkt_ip6);
1620		SWAP(int, kt->pfrkt_cnt, shadow->pfrkt_cnt);
1621		pfr_clstats_ktable(kt, tzero, 1);
1622	}
1623	nflags = ((shadow->pfrkt_flags & PFR_TFLAG_USRMASK) |
1624	    (kt->pfrkt_flags & PFR_TFLAG_SETMASK) | PFR_TFLAG_ACTIVE)
1625		& ~PFR_TFLAG_INACTIVE;
1626	pfr_destroy_ktable(shadow, 0);
1627	kt->pfrkt_shadow = NULL;
1628	pfr_setflags_ktable(kt, nflags);
1629}
1630
1631static int
1632pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved)
1633{
1634	int i;
1635
1636	if (!tbl->pfrt_name[0])
1637		return (-1);
1638	if (no_reserved && !strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR))
1639		 return (-1);
1640	if (tbl->pfrt_name[PF_TABLE_NAME_SIZE-1])
1641		return (-1);
1642	for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++)
1643		if (tbl->pfrt_name[i])
1644			return (-1);
1645	if (pfr_fix_anchor(tbl->pfrt_anchor))
1646		return (-1);
1647	if (tbl->pfrt_flags & ~allowedflags)
1648		return (-1);
1649	return (0);
1650}
1651
1652/*
1653 * Rewrite anchors referenced by tables to remove slashes
1654 * and check for validity.
1655 */
1656static int
1657pfr_fix_anchor(char *anchor)
1658{
1659	size_t siz = MAXPATHLEN;
1660	int i;
1661
1662	if (anchor[0] == '/') {
1663		char *path;
1664		int off;
1665
1666		path = anchor;
1667		off = 1;
1668		while (*++path == '/')
1669			off++;
1670		bcopy(path, anchor, siz - off);
1671		memset(anchor + siz - off, 0, off);
1672	}
1673	if (anchor[siz - 1])
1674		return (-1);
1675	for (i = strlen(anchor); i < siz; i++)
1676		if (anchor[i])
1677			return (-1);
1678	return (0);
1679}
1680
1681static int
1682pfr_table_count(struct pfr_table *filter, int flags)
1683{
1684	struct pf_ruleset *rs;
1685
1686	PF_RULES_ASSERT();
1687
1688	if (flags & PFR_FLAG_ALLRSETS)
1689		return (pfr_ktable_cnt);
1690	if (filter->pfrt_anchor[0]) {
1691		rs = pf_find_ruleset(filter->pfrt_anchor);
1692		return ((rs != NULL) ? rs->tables : -1);
1693	}
1694	return (pf_main_ruleset.tables);
1695}
1696
1697static int
1698pfr_skip_table(struct pfr_table *filter, struct pfr_ktable *kt, int flags)
1699{
1700	if (flags & PFR_FLAG_ALLRSETS)
1701		return (0);
1702	if (strcmp(filter->pfrt_anchor, kt->pfrkt_anchor))
1703		return (1);
1704	return (0);
1705}
1706
1707static void
1708pfr_insert_ktables(struct pfr_ktableworkq *workq)
1709{
1710	struct pfr_ktable	*p;
1711
1712	SLIST_FOREACH(p, workq, pfrkt_workq)
1713		pfr_insert_ktable(p);
1714}
1715
1716static void
1717pfr_insert_ktable(struct pfr_ktable *kt)
1718{
1719
1720	PF_RULES_WASSERT();
1721
1722	RB_INSERT(pfr_ktablehead, &pfr_ktables, kt);
1723	pfr_ktable_cnt++;
1724	if (kt->pfrkt_root != NULL)
1725		if (!kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR]++)
1726			pfr_setflags_ktable(kt->pfrkt_root,
1727			    kt->pfrkt_root->pfrkt_flags|PFR_TFLAG_REFDANCHOR);
1728}
1729
1730static void
1731pfr_setflags_ktables(struct pfr_ktableworkq *workq)
1732{
1733	struct pfr_ktable	*p, *q;
1734
1735	for (p = SLIST_FIRST(workq); p; p = q) {
1736		q = SLIST_NEXT(p, pfrkt_workq);
1737		pfr_setflags_ktable(p, p->pfrkt_nflags);
1738	}
1739}
1740
1741static void
1742pfr_setflags_ktable(struct pfr_ktable *kt, int newf)
1743{
1744	struct pfr_kentryworkq	addrq;
1745
1746	PF_RULES_WASSERT();
1747
1748	if (!(newf & PFR_TFLAG_REFERENCED) &&
1749	    !(newf & PFR_TFLAG_PERSIST))
1750		newf &= ~PFR_TFLAG_ACTIVE;
1751	if (!(newf & PFR_TFLAG_ACTIVE))
1752		newf &= ~PFR_TFLAG_USRMASK;
1753	if (!(newf & PFR_TFLAG_SETMASK)) {
1754		RB_REMOVE(pfr_ktablehead, &pfr_ktables, kt);
1755		if (kt->pfrkt_root != NULL)
1756			if (!--kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR])
1757				pfr_setflags_ktable(kt->pfrkt_root,
1758				    kt->pfrkt_root->pfrkt_flags &
1759					~PFR_TFLAG_REFDANCHOR);
1760		pfr_destroy_ktable(kt, 1);
1761		pfr_ktable_cnt--;
1762		return;
1763	}
1764	if (!(newf & PFR_TFLAG_ACTIVE) && kt->pfrkt_cnt) {
1765		pfr_enqueue_addrs(kt, &addrq, NULL, 0);
1766		pfr_remove_kentries(kt, &addrq);
1767	}
1768	if (!(newf & PFR_TFLAG_INACTIVE) && kt->pfrkt_shadow != NULL) {
1769		pfr_destroy_ktable(kt->pfrkt_shadow, 1);
1770		kt->pfrkt_shadow = NULL;
1771	}
1772	kt->pfrkt_flags = newf;
1773}
1774
1775static void
1776pfr_clstats_ktables(struct pfr_ktableworkq *workq, long tzero, int recurse)
1777{
1778	struct pfr_ktable	*p;
1779
1780	SLIST_FOREACH(p, workq, pfrkt_workq)
1781		pfr_clstats_ktable(p, tzero, recurse);
1782}
1783
1784static void
1785pfr_clstats_ktable(struct pfr_ktable *kt, long tzero, int recurse)
1786{
1787	struct pfr_kentryworkq	 addrq;
1788
1789	if (recurse) {
1790		pfr_enqueue_addrs(kt, &addrq, NULL, 0);
1791		pfr_clstats_kentries(&addrq, tzero, 0);
1792	}
1793	bzero(kt->pfrkt_packets, sizeof(kt->pfrkt_packets));
1794	bzero(kt->pfrkt_bytes, sizeof(kt->pfrkt_bytes));
1795	kt->pfrkt_match = kt->pfrkt_nomatch = 0;
1796	kt->pfrkt_tzero = tzero;
1797}
1798
1799static struct pfr_ktable *
1800pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset)
1801{
1802	struct pfr_ktable	*kt;
1803	struct pf_ruleset	*rs;
1804
1805	PF_RULES_WASSERT();
1806
1807	kt = malloc(sizeof(*kt), M_PFTABLE, M_NOWAIT|M_ZERO);
1808	if (kt == NULL)
1809		return (NULL);
1810	kt->pfrkt_t = *tbl;
1811
1812	if (attachruleset) {
1813		rs = pf_find_or_create_ruleset(tbl->pfrt_anchor);
1814		if (!rs) {
1815			pfr_destroy_ktable(kt, 0);
1816			return (NULL);
1817		}
1818		kt->pfrkt_rs = rs;
1819		rs->tables++;
1820	}
1821
1822	if (!rn_inithead((void **)&kt->pfrkt_ip4,
1823	    offsetof(struct sockaddr_in, sin_addr) * 8) ||
1824	    !rn_inithead((void **)&kt->pfrkt_ip6,
1825	    offsetof(struct sockaddr_in6, sin6_addr) * 8)) {
1826		pfr_destroy_ktable(kt, 0);
1827		return (NULL);
1828	}
1829	kt->pfrkt_tzero = tzero;
1830
1831	return (kt);
1832}
1833
1834static void
1835pfr_destroy_ktables(struct pfr_ktableworkq *workq, int flushaddr)
1836{
1837	struct pfr_ktable	*p, *q;
1838
1839	for (p = SLIST_FIRST(workq); p; p = q) {
1840		q = SLIST_NEXT(p, pfrkt_workq);
1841		pfr_destroy_ktable(p, flushaddr);
1842	}
1843}
1844
1845static void
1846pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
1847{
1848	struct pfr_kentryworkq	 addrq;
1849
1850	if (flushaddr) {
1851		pfr_enqueue_addrs(kt, &addrq, NULL, 0);
1852		pfr_clean_node_mask(kt, &addrq);
1853		pfr_destroy_kentries(&addrq);
1854	}
1855	if (kt->pfrkt_ip4 != NULL) {
1856		RADIX_NODE_HEAD_DESTROY(kt->pfrkt_ip4);
1857		rn_detachhead((void **)&kt->pfrkt_ip4);
1858	}
1859	if (kt->pfrkt_ip6 != NULL) {
1860		RADIX_NODE_HEAD_DESTROY(kt->pfrkt_ip6);
1861		rn_detachhead((void **)&kt->pfrkt_ip6);
1862	}
1863	if (kt->pfrkt_shadow != NULL)
1864		pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr);
1865	if (kt->pfrkt_rs != NULL) {
1866		kt->pfrkt_rs->tables--;
1867		pf_remove_if_empty_ruleset(kt->pfrkt_rs);
1868	}
1869	free(kt, M_PFTABLE);
1870}
1871
1872static int
1873pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q)
1874{
1875	int d;
1876
1877	if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE)))
1878		return (d);
1879	return (strcmp(p->pfrkt_anchor, q->pfrkt_anchor));
1880}
1881
1882static struct pfr_ktable *
1883pfr_lookup_table(struct pfr_table *tbl)
1884{
1885	/* struct pfr_ktable start like a struct pfr_table */
1886	return (RB_FIND(pfr_ktablehead, &pfr_ktables,
1887	    (struct pfr_ktable *)tbl));
1888}
1889
1890int
1891pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
1892{
1893	struct pfr_kentry	*ke = NULL;
1894	int			 match;
1895
1896	PF_RULES_RASSERT();
1897
1898	if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
1899		kt = kt->pfrkt_root;
1900	if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
1901		return (0);
1902
1903	switch (af) {
1904#ifdef INET
1905	case AF_INET:
1906	    {
1907		struct sockaddr_in sin;
1908
1909		bzero(&sin, sizeof(sin));
1910		sin.sin_len = sizeof(sin);
1911		sin.sin_family = AF_INET;
1912		sin.sin_addr.s_addr = a->addr32[0];
1913		ke = (struct pfr_kentry *)rn_match(&sin, kt->pfrkt_ip4);
1914		if (ke && KENTRY_RNF_ROOT(ke))
1915			ke = NULL;
1916		break;
1917	    }
1918#endif /* INET */
1919#ifdef INET6
1920	case AF_INET6:
1921	    {
1922		struct sockaddr_in6 sin6;
1923
1924		bzero(&sin6, sizeof(sin6));
1925		sin6.sin6_len = sizeof(sin6);
1926		sin6.sin6_family = AF_INET6;
1927		bcopy(a, &sin6.sin6_addr, sizeof(sin6.sin6_addr));
1928		ke = (struct pfr_kentry *)rn_match(&sin6, kt->pfrkt_ip6);
1929		if (ke && KENTRY_RNF_ROOT(ke))
1930			ke = NULL;
1931		break;
1932	    }
1933#endif /* INET6 */
1934	}
1935	match = (ke && !ke->pfrke_not);
1936	if (match)
1937		kt->pfrkt_match++;
1938	else
1939		kt->pfrkt_nomatch++;
1940	return (match);
1941}
1942
1943void
1944pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
1945    u_int64_t len, int dir_out, int op_pass, int notrule)
1946{
1947	struct pfr_kentry	*ke = NULL;
1948
1949	if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
1950		kt = kt->pfrkt_root;
1951	if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
1952		return;
1953
1954	switch (af) {
1955#ifdef INET
1956	case AF_INET:
1957	    {
1958		struct sockaddr_in sin;
1959
1960		bzero(&sin, sizeof(sin));
1961		sin.sin_len = sizeof(sin);
1962		sin.sin_family = AF_INET;
1963		sin.sin_addr.s_addr = a->addr32[0];
1964		ke = (struct pfr_kentry *)rn_match(&sin, kt->pfrkt_ip4);
1965		if (ke && KENTRY_RNF_ROOT(ke))
1966			ke = NULL;
1967		break;
1968	    }
1969#endif /* INET */
1970#ifdef INET6
1971	case AF_INET6:
1972	    {
1973		struct sockaddr_in6 sin6;
1974
1975		bzero(&sin6, sizeof(sin6));
1976		sin6.sin6_len = sizeof(sin6);
1977		sin6.sin6_family = AF_INET6;
1978		bcopy(a, &sin6.sin6_addr, sizeof(sin6.sin6_addr));
1979		ke = (struct pfr_kentry *)rn_match(&sin6, kt->pfrkt_ip6);
1980		if (ke && KENTRY_RNF_ROOT(ke))
1981			ke = NULL;
1982		break;
1983	    }
1984#endif /* INET6 */
1985	default:
1986		panic("%s: unknown address family %u", __func__, af);
1987	}
1988	if ((ke == NULL || ke->pfrke_not) != notrule) {
1989		if (op_pass != PFR_OP_PASS)
1990			printf("pfr_update_stats: assertion failed.\n");
1991		op_pass = PFR_OP_XPASS;
1992	}
1993	kt->pfrkt_packets[dir_out][op_pass]++;
1994	kt->pfrkt_bytes[dir_out][op_pass] += len;
1995	if (ke != NULL && op_pass != PFR_OP_XPASS &&
1996	    (kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) {
1997		if (ke->pfrke_counters == NULL)
1998			ke->pfrke_counters = uma_zalloc(V_pfr_kcounters_z,
1999			    M_NOWAIT | M_ZERO);
2000		if (ke->pfrke_counters != NULL) {
2001			ke->pfrke_counters->pfrkc_packets[dir_out][op_pass]++;
2002			ke->pfrke_counters->pfrkc_bytes[dir_out][op_pass] += len;
2003		}
2004	}
2005}
2006
2007struct pfr_ktable *
2008pfr_attach_table(struct pf_ruleset *rs, char *name)
2009{
2010	struct pfr_ktable	*kt, *rt;
2011	struct pfr_table	 tbl;
2012	struct pf_anchor	*ac = rs->anchor;
2013
2014	PF_RULES_WASSERT();
2015
2016	bzero(&tbl, sizeof(tbl));
2017	strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name));
2018	if (ac != NULL)
2019		strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor));
2020	kt = pfr_lookup_table(&tbl);
2021	if (kt == NULL) {
2022		kt = pfr_create_ktable(&tbl, time_second, 1);
2023		if (kt == NULL)
2024			return (NULL);
2025		if (ac != NULL) {
2026			bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor));
2027			rt = pfr_lookup_table(&tbl);
2028			if (rt == NULL) {
2029				rt = pfr_create_ktable(&tbl, 0, 1);
2030				if (rt == NULL) {
2031					pfr_destroy_ktable(kt, 0);
2032					return (NULL);
2033				}
2034				pfr_insert_ktable(rt);
2035			}
2036			kt->pfrkt_root = rt;
2037		}
2038		pfr_insert_ktable(kt);
2039	}
2040	if (!kt->pfrkt_refcnt[PFR_REFCNT_RULE]++)
2041		pfr_setflags_ktable(kt, kt->pfrkt_flags|PFR_TFLAG_REFERENCED);
2042	return (kt);
2043}
2044
2045void
2046pfr_detach_table(struct pfr_ktable *kt)
2047{
2048
2049	PF_RULES_WASSERT();
2050	KASSERT(kt->pfrkt_refcnt[PFR_REFCNT_RULE] > 0, ("%s: refcount %d\n",
2051	    __func__, kt->pfrkt_refcnt[PFR_REFCNT_RULE]));
2052
2053	if (!--kt->pfrkt_refcnt[PFR_REFCNT_RULE])
2054		pfr_setflags_ktable(kt, kt->pfrkt_flags&~PFR_TFLAG_REFERENCED);
2055}
2056
2057int
2058pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
2059    sa_family_t af)
2060{
2061	struct pf_addr		 *addr, *cur, *mask;
2062	union sockaddr_union	 uaddr, umask;
2063	struct pfr_kentry	*ke, *ke2 = NULL;
2064	int			 idx = -1, use_counter = 0;
2065
2066	switch (af) {
2067	case AF_INET:
2068		uaddr.sin.sin_len = sizeof(struct sockaddr_in);
2069		uaddr.sin.sin_family = AF_INET;
2070		break;
2071	case AF_INET6:
2072		uaddr.sin6.sin6_len = sizeof(struct sockaddr_in6);
2073		uaddr.sin6.sin6_family = AF_INET6;
2074		break;
2075	}
2076	addr = SUNION2PF(&uaddr, af);
2077
2078	if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
2079		kt = kt->pfrkt_root;
2080	if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
2081		return (-1);
2082
2083	if (pidx != NULL)
2084		idx = *pidx;
2085	if (counter != NULL && idx >= 0)
2086		use_counter = 1;
2087	if (idx < 0)
2088		idx = 0;
2089
2090_next_block:
2091	ke = pfr_kentry_byidx(kt, idx, af);
2092	if (ke == NULL) {
2093		kt->pfrkt_nomatch++;
2094		return (1);
2095	}
2096	pfr_prepare_network(&umask, af, ke->pfrke_net);
2097	cur = SUNION2PF(&ke->pfrke_sa, af);
2098	mask = SUNION2PF(&umask, af);
2099
2100	if (use_counter) {
2101		/* is supplied address within block? */
2102		if (!PF_MATCHA(0, cur, mask, counter, af)) {
2103			/* no, go to next block in table */
2104			idx++;
2105			use_counter = 0;
2106			goto _next_block;
2107		}
2108		PF_ACPY(addr, counter, af);
2109	} else {
2110		/* use first address of block */
2111		PF_ACPY(addr, cur, af);
2112	}
2113
2114	if (!KENTRY_NETWORK(ke)) {
2115		/* this is a single IP address - no possible nested block */
2116		PF_ACPY(counter, addr, af);
2117		*pidx = idx;
2118		kt->pfrkt_match++;
2119		return (0);
2120	}
2121	for (;;) {
2122		/* we don't want to use a nested block */
2123		switch (af) {
2124		case AF_INET:
2125			ke2 = (struct pfr_kentry *)rn_match(&uaddr,
2126			    kt->pfrkt_ip4);
2127			break;
2128		case AF_INET6:
2129			ke2 = (struct pfr_kentry *)rn_match(&uaddr,
2130			    kt->pfrkt_ip6);
2131			break;
2132		}
2133		/* no need to check KENTRY_RNF_ROOT() here */
2134		if (ke2 == ke) {
2135			/* lookup return the same block - perfect */
2136			PF_ACPY(counter, addr, af);
2137			*pidx = idx;
2138			kt->pfrkt_match++;
2139			return (0);
2140		}
2141
2142		/* we need to increase the counter past the nested block */
2143		pfr_prepare_network(&umask, AF_INET, ke2->pfrke_net);
2144		PF_POOLMASK(addr, addr, SUNION2PF(&umask, af), &pfr_ffaddr, af);
2145		PF_AINC(addr, af);
2146		if (!PF_MATCHA(0, cur, mask, addr, af)) {
2147			/* ok, we reached the end of our main block */
2148			/* go to next block in table */
2149			idx++;
2150			use_counter = 0;
2151			goto _next_block;
2152		}
2153	}
2154}
2155
2156static struct pfr_kentry *
2157pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
2158{
2159	struct pfr_walktree	w;
2160
2161	bzero(&w, sizeof(w));
2162	w.pfrw_op = PFRW_POOL_GET;
2163	w.pfrw_cnt = idx;
2164
2165	switch (af) {
2166#ifdef INET
2167	case AF_INET:
2168		kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
2169		return (w.pfrw_kentry);
2170#endif /* INET */
2171#ifdef INET6
2172	case AF_INET6:
2173		kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
2174		return (w.pfrw_kentry);
2175#endif /* INET6 */
2176	default:
2177		return (NULL);
2178	}
2179}
2180
2181void
2182pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn)
2183{
2184	struct pfr_walktree	w;
2185
2186	bzero(&w, sizeof(w));
2187	w.pfrw_op = PFRW_DYNADDR_UPDATE;
2188	w.pfrw_dyn = dyn;
2189
2190	dyn->pfid_acnt4 = 0;
2191	dyn->pfid_acnt6 = 0;
2192	if (!dyn->pfid_af || dyn->pfid_af == AF_INET)
2193		kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
2194	if (!dyn->pfid_af || dyn->pfid_af == AF_INET6)
2195		kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
2196}
2197