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