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