]> CyberLeo.Net >> Repos - FreeBSD/releng/10.1.git/blob - sys/netpfil/pf/pf_table.c
Merge r273184, r273185 from stable/10:
[FreeBSD/releng/10.1.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_table_count(struct pfr_table *, int);
178 static int               pfr_skip_table(struct pfr_table *,
179                             struct pfr_ktable *, int);
180 static struct pfr_kentry
181                         *pfr_kentry_byidx(struct pfr_ktable *, int, int);
182
183 static RB_PROTOTYPE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
184 static RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
185
186 struct pfr_ktablehead    pfr_ktables;
187 struct pfr_table         pfr_nulltable;
188 int                      pfr_ktable_cnt;
189
190 void
191 pfr_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
204 void
205 pfr_cleanup(void)
206 {
207
208         uma_zdestroy(V_pfr_kentry_z);
209         uma_zdestroy(V_pfr_kcounters_z);
210 }
211
212 int
213 pfr_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
237 int
238 pfr_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
308 int
309 pfr_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
387 int
388 pfr_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
500 int
501 pfr_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
536 int
537 pfr_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
575 int
576 pfr_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
623 int
624 pfr_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
667 static int
668 pfr_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
701 static void
702 pfr_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
723 static void
724 pfr_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
737 static struct pfr_kentry *
738 pfr_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
769 static struct pfr_kentry *
770 pfr_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
788 static void
789 pfr_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
799 static void
800 pfr_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
807 static void
808 pfr_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
827 int
828 pfr_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
850 static void
851 pfr_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
865 static void
866 pfr_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
875 static void
876 pfr_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
891 static void
892 pfr_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
901 static void
902 pfr_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
926 static int
927 pfr_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
950 static int
951 pfr_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
975 static void
976 pfr_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
990 static int
991 pfr_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
1071 int
1072 pfr_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
1103 int
1104 pfr_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
1178 int
1179 pfr_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
1212 int
1213 pfr_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
1245 int
1246 pfr_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
1284 int
1285 pfr_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
1311 int
1312 pfr_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
1359 int
1360 pfr_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
1392 int
1393 pfr_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
1492 int
1493 pfr_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
1525 int
1526 pfr_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
1570 static void
1571 pfr_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
1631 static int
1632 pfr_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  */
1656 static int
1657 pfr_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
1681 static int
1682 pfr_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
1697 static int
1698 pfr_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
1707 static void
1708 pfr_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
1716 static void
1717 pfr_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
1730 static void
1731 pfr_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
1741 static void
1742 pfr_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
1775 static void
1776 pfr_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
1784 static void
1785 pfr_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
1799 static struct pfr_ktable *
1800 pfr_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
1834 static void
1835 pfr_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
1845 static void
1846 pfr_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
1872 static int
1873 pfr_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
1882 static struct pfr_ktable *
1883 pfr_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
1890 int
1891 pfr_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
1943 void
1944 pfr_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
2007 struct pfr_ktable *
2008 pfr_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
2045 void
2046 pfr_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
2057 int
2058 pfr_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
2156 static struct pfr_kentry *
2157 pfr_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
2181 void
2182 pfr_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 }