Rename functions to avoid conflicts with libc.
[dragonfly.git] / sys / net / pf / pf_ioctl.c
1 /*      $FreeBSD: src/sys/contrib/pf/net/pf_ioctl.c,v 1.12 2004/08/12 14:15:42 mlaier Exp $     */
2 /*      $OpenBSD: pf_ioctl.c,v 1.112.2.2 2004/07/24 18:28:12 brad Exp $ */
3 /*      $DragonFly: src/sys/net/pf/pf_ioctl.c,v 1.7 2006/09/03 17:31:55 dillon Exp $ */
4
5 /*
6  * Copyright (c) 2004 The DragonFly Project.  All rights reserved.
7  *
8  * Copyright (c) 2001 Daniel Hartmeier
9  * Copyright (c) 2002,2003 Henning Brauer
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  * Effort sponsored in part by the Defense Advanced Research Projects
37  * Agency (DARPA) and Air Force Research Laboratory, Air Force
38  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
39  *
40  */
41
42 #include "opt_inet.h"
43 #include "opt_inet6.h"
44 #include "use_pfsync.h"
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/conf.h>
49 #include <sys/device.h>
50 #include <sys/mbuf.h>
51 #include <sys/filio.h>
52 #include <sys/fcntl.h>
53 #include <sys/socket.h>
54 #include <sys/socketvar.h>
55 #include <sys/kernel.h>
56 #include <sys/thread2.h>
57 #include <sys/time.h>
58 #include <sys/malloc.h>
59 #include <sys/module.h>
60 #include <vm/vm_zone.h>
61
62 #include <net/if.h>
63 #include <net/if_types.h>
64 #include <net/route.h>
65
66 #include <netinet/in.h>
67 #include <netinet/in_var.h>
68 #include <netinet/in_systm.h>
69 #include <netinet/ip.h>
70 #include <netinet/ip_var.h>
71 #include <netinet/ip_icmp.h>
72
73 #include <net/pf/pfvar.h>
74
75 #if NPFSYNC > 0
76 #include <net/pf/if_pfsync.h>
77 #endif /* NPFSYNC > 0 */
78
79 #ifdef INET6
80 #include <netinet/ip6.h>
81 #include <netinet/in_pcb.h>
82 #endif /* INET6 */
83
84 #ifdef ALTQ
85 #include <net/altq/altq.h>
86 #endif
87
88 #include <machine/limits.h>
89 #include <net/pfil.h>
90
91 void                     init_zone_var(void);
92 void                     cleanup_pf_zone(void);
93 int                      pfattach(void);
94 struct pf_pool          *pf_get_pool(char *, char *, u_int32_t,
95                             u_int8_t, u_int32_t, u_int8_t, u_int8_t, u_int8_t);
96 int                      pf_get_ruleset_number(u_int8_t);
97 void                     pf_init_ruleset(struct pf_ruleset *);
98 void                     pf_mv_pool(struct pf_palist *, struct pf_palist *);
99 void                     pf_empty_pool(struct pf_palist *);
100 #ifdef ALTQ
101 int                      pf_begin_altq(u_int32_t *);
102 int                      pf_rollback_altq(u_int32_t);
103 int                      pf_commit_altq(u_int32_t);
104 #endif /* ALTQ */
105 int                      pf_begin_rules(u_int32_t *, int, char *, char *);
106 int                      pf_rollback_rules(u_int32_t, int, char *, char *);
107 int                      pf_commit_rules(u_int32_t, int, char *, char *);
108
109 extern struct callout    pf_expire_to;
110
111 struct pf_rule           pf_default_rule;
112
113 #define TAGID_MAX        50000
114 TAILQ_HEAD(pf_tags, pf_tagname) pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags),
115                                 pf_qids = TAILQ_HEAD_INITIALIZER(pf_qids);
116
117 #if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
118 #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
119 #endif
120 static u_int16_t         tagname2tag(struct pf_tags *, char *);
121 static void              tag2tagname(struct pf_tags *, u_int16_t, char *);
122 static void              tag_unref(struct pf_tags *, u_int16_t);
123
124 #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
125
126 static dev_t    pf_dev;
127
128 /*
129  * XXX - These are new and need to be checked when moveing to a new version
130  */
131 static void              pf_clear_states(void);
132 static int               pf_clear_tables(void);
133 static void              pf_clear_srcnodes(void);
134 /*
135  * XXX - These are new and need to be checked when moveing to a new version
136  */
137  
138 /*
139  * Wrapper functions for pfil(9) hooks
140  */
141 static int pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp,
142                 int dir);
143 static int pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp,
144                 int dir);
145 #ifdef INET6
146 static int pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp,
147                 int dir);
148 static int pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp,
149                 int dir);
150 #endif
151
152 static int               hook_pf(void);
153 static int               dehook_pf(void);
154 static int               shutdown_pf(void);
155 static int               pf_load(void);
156 static int               pf_unload(void);
157
158 d_open_t        pfopen;
159 d_close_t       pfclose;
160 d_ioctl_t       pfioctl;
161
162 static struct dev_ops pf_ops = {            /* XXX convert to port model */
163         { PF_NAME, 73, 0 },
164         .d_open =       pfopen,
165         .d_close =      pfclose,
166         .d_ioctl =      pfioctl
167 };
168
169 static volatile int pf_pfil_hooked = 0;
170
171 void
172 init_zone_var(void)
173 {
174         pf_src_tree_pl = pf_rule_pl = NULL;
175         pf_state_pl = pf_altq_pl = pf_pooladdr_pl = NULL;
176         pf_frent_pl = pf_frag_pl = pf_cache_pl = pf_cent_pl = NULL;
177         pf_state_scrub_pl = NULL;
178         pfr_ktable_pl = pfr_kentry_pl = NULL;
179 }
180
181 void
182 cleanup_pf_zone(void)
183 {
184         ZONE_DESTROY(pf_src_tree_pl);
185         ZONE_DESTROY(pf_rule_pl);
186         ZONE_DESTROY(pf_state_pl);
187         ZONE_DESTROY(pf_altq_pl);
188         ZONE_DESTROY(pf_pooladdr_pl);
189         ZONE_DESTROY(pf_frent_pl);
190         ZONE_DESTROY(pf_frag_pl);
191         ZONE_DESTROY(pf_cache_pl);
192         ZONE_DESTROY(pf_cent_pl);
193         ZONE_DESTROY(pfr_ktable_pl);
194         ZONE_DESTROY(pfr_kentry_pl);
195         ZONE_DESTROY(pf_state_scrub_pl);
196         ZONE_DESTROY(pfi_addr_pl);
197 }
198
199 int
200 pfattach(void)
201 {
202         u_int32_t *my_timeout = pf_default_rule.timeout;
203         int error = 1;
204
205         do {
206                 ZONE_CREATE(pf_src_tree_pl,struct pf_src_node, "pfsrctrpl");
207                 ZONE_CREATE(pf_rule_pl,    struct pf_rule, "pfrulepl");
208                 ZONE_CREATE(pf_state_pl,   struct pf_state, "pfstatepl");
209                 ZONE_CREATE(pf_altq_pl,    struct pf_altq, "pfaltqpl");
210                 ZONE_CREATE(pf_pooladdr_pl,struct pf_pooladdr, "pfpooladdrpl");
211                 ZONE_CREATE(pfr_ktable_pl, struct pfr_ktable, "pfrktable");
212                 ZONE_CREATE(pfr_kentry_pl, struct pfr_kentry, "pfrkentry");
213                 ZONE_CREATE(pf_frent_pl,   struct pf_frent, "pffrent");
214                 ZONE_CREATE(pf_frag_pl,    struct pf_fragment, "pffrag");
215                 ZONE_CREATE(pf_cache_pl,   struct pf_fragment, "pffrcache");
216                 ZONE_CREATE(pf_cent_pl,    struct pf_frcache, "pffrcent");
217                 ZONE_CREATE(pf_state_scrub_pl, struct pf_state_scrub, 
218                     "pfstatescrub");
219                 ZONE_CREATE(pfi_addr_pl,   struct pfi_dynaddr, "pfiaddrpl");
220                 error = 0;
221         } while(0);
222         if (error) {
223                 cleanup_pf_zone();
224                 return (error);
225         }
226         pfr_initialize();
227         pfi_initialize();
228         error = pf_osfp_initialize();
229         if (error) {
230                 cleanup_pf_zone();
231                 pf_osfp_cleanup();
232                 return (error);
233         }
234
235         pf_pool_limits[PF_LIMIT_STATES].pp = pf_state_pl;
236         pf_pool_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT;
237         pf_pool_limits[PF_LIMIT_FRAGS].pp = pf_frent_pl;
238         pf_pool_limits[PF_LIMIT_FRAGS].limit = PFFRAG_FRENT_HIWAT;
239         /* XXX uma_zone_set_max(pf_pool_limits[PF_LIMIT_STATES].pp,
240                 pf_pool_limits[PF_LIMIT_STATES].limit);
241         */
242
243         RB_INIT(&tree_src_tracking);
244         TAILQ_INIT(&pf_anchors);
245         pf_init_ruleset(&pf_main_ruleset);
246         TAILQ_INIT(&pf_altqs[0]);
247         TAILQ_INIT(&pf_altqs[1]);
248         TAILQ_INIT(&pf_pabuf);
249         pf_altqs_active = &pf_altqs[0];
250         pf_altqs_inactive = &pf_altqs[1];
251         TAILQ_INIT(&state_updates);
252
253         /* default rule should never be garbage collected */
254         pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
255         pf_default_rule.action = PF_PASS;
256         pf_default_rule.nr = (uint32_t)(-1);
257
258         /* initialize default timeouts */
259         my_timeout[PFTM_TCP_FIRST_PACKET] = 120;        /* First TCP packet */
260         my_timeout[PFTM_TCP_OPENING] = 30;              /* No response yet */
261         my_timeout[PFTM_TCP_ESTABLISHED] = 24*60*60;    /* Established */
262         my_timeout[PFTM_TCP_CLOSING] = 15 * 60;         /* Half closed */
263         my_timeout[PFTM_TCP_FIN_WAIT] = 45;             /* Got both FINs */
264         my_timeout[PFTM_TCP_CLOSED] = 90;               /* Got a RST */
265         my_timeout[PFTM_UDP_FIRST_PACKET] = 60;         /* First UDP packet */
266         my_timeout[PFTM_UDP_SINGLE] = 30;               /* Unidirectional */
267         my_timeout[PFTM_UDP_MULTIPLE] = 60;             /* Bidirectional */
268         my_timeout[PFTM_ICMP_FIRST_PACKET] = 20;        /* First ICMP packet */
269         my_timeout[PFTM_ICMP_ERROR_REPLY] = 10;         /* Got error response */
270         my_timeout[PFTM_OTHER_FIRST_PACKET] = 60;       /* First packet */
271         my_timeout[PFTM_OTHER_SINGLE] = 30;             /* Unidirectional */
272         my_timeout[PFTM_OTHER_MULTIPLE] = 60;           /* Bidirectional */
273         my_timeout[PFTM_FRAG] = 30;                     /* Fragment expire */
274         my_timeout[PFTM_INTERVAL] = 10;                 /* Expire interval */
275
276         callout_init(&pf_expire_to);
277         callout_reset(&pf_expire_to, my_timeout[PFTM_INTERVAL] * hz,
278             pf_purge_timeout, &pf_expire_to);
279
280         pf_normalize_init();
281         bzero(&pf_status, sizeof(pf_status));
282         pf_status.debug = PF_DEBUG_URGENT;
283         pf_pfil_hooked = 0;
284
285         /* XXX do our best to avoid a conflict */
286         pf_status.hostid = karc4random();
287
288         return (error);
289 }
290
291 int
292 pfopen(struct dev_open_args *ap)
293 {
294         dev_t dev = ap->a_head.a_dev;
295         if (minor(dev) >= 1)
296                 return (ENXIO);
297         return (0);
298 }
299
300 int
301 pfclose(struct dev_close_args *ap)
302 {
303         dev_t dev = ap->a_head.a_dev;
304         if (minor(dev) >= 1)
305                 return (ENXIO);
306         return (0);
307 }
308
309 struct pf_pool *
310 pf_get_pool(char *anchorname, char *rulesetname, u_int32_t ticket,
311     u_int8_t rule_action, u_int32_t rule_number, u_int8_t r_last,
312     u_int8_t active, u_int8_t check_ticket)
313 {
314         struct pf_ruleset       *ruleset;
315         struct pf_rule          *rule;
316         int                      rs_num;
317
318         ruleset = pf_find_ruleset(anchorname, rulesetname);
319         if (ruleset == NULL)
320                 return (NULL);
321         rs_num = pf_get_ruleset_number(rule_action);
322         if (rs_num >= PF_RULESET_MAX)
323                 return (NULL);
324         if (active) {
325                 if (check_ticket && ticket !=
326                     ruleset->rules[rs_num].active.ticket)
327                         return (NULL);
328                 if (r_last)
329                         rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
330                             pf_rulequeue);
331                 else
332                         rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
333         } else {
334                 if (check_ticket && ticket !=
335                     ruleset->rules[rs_num].inactive.ticket)
336                         return (NULL);
337                 if (r_last)
338                         rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
339                             pf_rulequeue);
340                 else
341                         rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr);
342         }
343         if (!r_last) {
344                 while ((rule != NULL) && (rule->nr != rule_number))
345                         rule = TAILQ_NEXT(rule, entries);
346         }
347         if (rule == NULL)
348                 return (NULL);
349
350         return (&rule->rpool);
351 }
352
353 int
354 pf_get_ruleset_number(u_int8_t action)
355 {
356         switch (action) {
357         case PF_SCRUB:
358                 return (PF_RULESET_SCRUB);
359                 break;
360         case PF_PASS:
361         case PF_DROP:
362                 return (PF_RULESET_FILTER);
363                 break;
364         case PF_NAT:
365         case PF_NONAT:
366                 return (PF_RULESET_NAT);
367                 break;
368         case PF_BINAT:
369         case PF_NOBINAT:
370                 return (PF_RULESET_BINAT);
371                 break;
372         case PF_RDR:
373         case PF_NORDR:
374                 return (PF_RULESET_RDR);
375                 break;
376         default:
377                 return (PF_RULESET_MAX);
378                 break;
379         }
380 }
381
382 void
383 pf_init_ruleset(struct pf_ruleset *ruleset)
384 {
385         int     i;
386
387         memset(ruleset, 0, sizeof(struct pf_ruleset));
388         for (i = 0; i < PF_RULESET_MAX; i++) {
389                 TAILQ_INIT(&ruleset->rules[i].queues[0]);
390                 TAILQ_INIT(&ruleset->rules[i].queues[1]);
391                 ruleset->rules[i].active.ptr = &ruleset->rules[i].queues[0];
392                 ruleset->rules[i].inactive.ptr = &ruleset->rules[i].queues[1];
393         }
394 }
395
396 struct pf_anchor *
397 pf_find_anchor(const char *anchorname)
398 {
399         struct pf_anchor        *anchor;
400         int                      n = -1;
401
402         anchor = TAILQ_FIRST(&pf_anchors);
403         while (anchor != NULL && (n = strcmp(anchor->name, anchorname)) < 0)
404                 anchor = TAILQ_NEXT(anchor, entries);
405         if (n == 0)
406                 return (anchor);
407         else
408                 return (NULL);
409 }
410
411 struct pf_ruleset *
412 pf_find_ruleset(char *anchorname, char *rulesetname)
413 {
414         struct pf_anchor        *anchor;
415         struct pf_ruleset       *ruleset;
416
417         if (!anchorname[0] && !rulesetname[0])
418                 return (&pf_main_ruleset);
419         if (!anchorname[0] || !rulesetname[0])
420                 return (NULL);
421         anchorname[PF_ANCHOR_NAME_SIZE-1] = 0;
422         rulesetname[PF_RULESET_NAME_SIZE-1] = 0;
423         anchor = pf_find_anchor(anchorname);
424         if (anchor == NULL)
425                 return (NULL);
426         ruleset = TAILQ_FIRST(&anchor->rulesets);
427         while (ruleset != NULL && strcmp(ruleset->name, rulesetname) < 0)
428                 ruleset = TAILQ_NEXT(ruleset, entries);
429         if (ruleset != NULL && !strcmp(ruleset->name, rulesetname))
430                 return (ruleset);
431         else
432                 return (NULL);
433 }
434
435 struct pf_ruleset *
436 pf_find_or_create_ruleset(char anchorname[PF_ANCHOR_NAME_SIZE],
437     char rulesetname[PF_RULESET_NAME_SIZE])
438 {
439         struct pf_anchor        *anchor, *a;
440         struct pf_ruleset       *ruleset, *r;
441
442         if (!anchorname[0] && !rulesetname[0])
443                 return (&pf_main_ruleset);
444         if (!anchorname[0] || !rulesetname[0])
445                 return (NULL);
446         anchorname[PF_ANCHOR_NAME_SIZE-1] = 0;
447         rulesetname[PF_RULESET_NAME_SIZE-1] = 0;
448         a = TAILQ_FIRST(&pf_anchors);
449         while (a != NULL && strcmp(a->name, anchorname) < 0)
450                 a = TAILQ_NEXT(a, entries);
451         if (a != NULL && !strcmp(a->name, anchorname))
452                 anchor = a;
453         else {
454                 anchor = (struct pf_anchor *)malloc(sizeof(struct pf_anchor),
455                     M_TEMP, M_NOWAIT);
456                 if (anchor == NULL)
457                         return (NULL);
458                 memset(anchor, 0, sizeof(struct pf_anchor));
459                 bcopy(anchorname, anchor->name, sizeof(anchor->name));
460                 TAILQ_INIT(&anchor->rulesets);
461                 if (a != NULL)
462                         TAILQ_INSERT_BEFORE(a, anchor, entries);
463                 else
464                         TAILQ_INSERT_TAIL(&pf_anchors, anchor, entries);
465         }
466         r = TAILQ_FIRST(&anchor->rulesets);
467         while (r != NULL && strcmp(r->name, rulesetname) < 0)
468                 r = TAILQ_NEXT(r, entries);
469         if (r != NULL && !strcmp(r->name, rulesetname))
470                 return (r);
471         ruleset = (struct pf_ruleset *)malloc(sizeof(struct pf_ruleset),
472             M_TEMP, M_NOWAIT);
473         if (ruleset != NULL) {
474                 pf_init_ruleset(ruleset);
475                 bcopy(rulesetname, ruleset->name, sizeof(ruleset->name));
476                 ruleset->anchor = anchor;
477                 if (r != NULL)
478                         TAILQ_INSERT_BEFORE(r, ruleset, entries);
479                 else
480                         TAILQ_INSERT_TAIL(&anchor->rulesets, ruleset, entries);
481         }
482         return (ruleset);
483 }
484
485 void
486 pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
487 {
488         struct pf_anchor        *anchor;
489         int                      i;
490
491         if (ruleset == NULL || ruleset->anchor == NULL || ruleset->tables > 0 ||
492             ruleset->topen)
493                 return;
494         for (i = 0; i < PF_RULESET_MAX; ++i)
495                 if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
496                     !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
497                     ruleset->rules[i].inactive.open)
498                         return;
499
500         anchor = ruleset->anchor;
501         TAILQ_REMOVE(&anchor->rulesets, ruleset, entries);
502         free(ruleset, M_TEMP);
503
504         if (TAILQ_EMPTY(&anchor->rulesets)) {
505                 TAILQ_REMOVE(&pf_anchors, anchor, entries);
506                 free(anchor, M_TEMP);
507                 pf_update_anchor_rules();
508         }
509 }
510
511 void
512 pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb)
513 {
514         struct pf_pooladdr      *mv_pool_pa;
515
516         while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) {
517                 TAILQ_REMOVE(poola, mv_pool_pa, entries);
518                 TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries);
519         }
520 }
521
522 void
523 pf_empty_pool(struct pf_palist *poola)
524 {
525         struct pf_pooladdr      *empty_pool_pa;
526
527         while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) {
528                 pfi_dynaddr_remove(&empty_pool_pa->addr);
529                 pf_tbladdr_remove(&empty_pool_pa->addr);
530                 pfi_detach_rule(empty_pool_pa->kif);
531                 TAILQ_REMOVE(poola, empty_pool_pa, entries);
532                 pool_put(&pf_pooladdr_pl, empty_pool_pa);
533         }
534 }
535
536 void
537 pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
538 {
539         if (rulequeue != NULL) {
540                 if (rule->states <= 0) {
541                         /*
542                          * XXX - we need to remove the table *before* detaching
543                          * the rule to make sure the table code does not delete
544                          * the anchor under our feet.
545                          */
546                         pf_tbladdr_remove(&rule->src.addr);
547                         pf_tbladdr_remove(&rule->dst.addr);
548                 }
549                 TAILQ_REMOVE(rulequeue, rule, entries);
550                 rule->entries.tqe_prev = NULL;
551                 rule->nr = (uint32_t)(-1);
552         }
553
554         if (rule->states > 0 || rule->src_nodes > 0 ||
555             rule->entries.tqe_prev != NULL)
556                 return;
557         pf_tag_unref(rule->tag);
558         pf_tag_unref(rule->match_tag);
559 #ifdef ALTQ
560         if (rule->pqid != rule->qid)
561                 pf_qid_unref(rule->pqid);
562         pf_qid_unref(rule->qid);
563 #endif
564         pfi_dynaddr_remove(&rule->src.addr);
565         pfi_dynaddr_remove(&rule->dst.addr);
566         if (rulequeue == NULL) {
567                 pf_tbladdr_remove(&rule->src.addr);
568                 pf_tbladdr_remove(&rule->dst.addr);
569         }
570         pfi_detach_rule(rule->kif);
571         pf_empty_pool(&rule->rpool.list);
572         pool_put(&pf_rule_pl, rule);
573 }
574
575 static  u_int16_t
576 tagname2tag(struct pf_tags *head, char *tagname)
577 {
578         struct pf_tagname       *tag, *p = NULL;
579         u_int16_t                new_tagid = 1;
580
581         TAILQ_FOREACH(tag, head, entries)
582                 if (strcmp(tagname, tag->name) == 0) {
583                         tag->ref++;
584                         return (tag->tag);
585                 }
586
587         /*
588          * to avoid fragmentation, we do a linear search from the beginning
589          * and take the first free slot we find. if there is none or the list
590          * is empty, append a new entry at the end.
591          */
592
593         /* new entry */
594         if (!TAILQ_EMPTY(head))
595                 for (p = TAILQ_FIRST(head); p != NULL &&
596                     p->tag == new_tagid; p = TAILQ_NEXT(p, entries))
597                         new_tagid = p->tag + 1;
598
599         if (new_tagid > TAGID_MAX)
600                 return (0);
601
602         /* allocate and fill new struct pf_tagname */
603         tag = (struct pf_tagname *)malloc(sizeof(struct pf_tagname),
604             M_TEMP, M_NOWAIT);
605         if (tag == NULL)
606                 return (0);
607         bzero(tag, sizeof(struct pf_tagname));
608         strlcpy(tag->name, tagname, sizeof(tag->name));
609         tag->tag = new_tagid;
610         tag->ref++;
611
612         if (p != NULL)  /* insert new entry before p */
613                 TAILQ_INSERT_BEFORE(p, tag, entries);
614         else    /* either list empty or no free slot in between */
615                 TAILQ_INSERT_TAIL(head, tag, entries);
616
617         return (tag->tag);
618 }
619
620 static  void
621 tag2tagname(struct pf_tags *head, u_int16_t tagid, char *p)
622 {
623         struct pf_tagname       *tag;
624
625         TAILQ_FOREACH(tag, head, entries)
626                 if (tag->tag == tagid) {
627                         strlcpy(p, tag->name, PF_TAG_NAME_SIZE);
628                         return;
629                 }
630 }
631
632 static  void
633 tag_unref(struct pf_tags *head, u_int16_t tag)
634 {
635         struct pf_tagname       *p, *next;
636
637         if (tag == 0)
638                 return;
639
640         for (p = TAILQ_FIRST(head); p != NULL; p = next) {
641                 next = TAILQ_NEXT(p, entries);
642                 if (tag == p->tag) {
643                         if (--p->ref == 0) {
644                                 TAILQ_REMOVE(head, p, entries);
645                                 free(p, M_TEMP);
646                         }
647                         break;
648                 }
649         }
650 }
651
652 u_int16_t
653 pf_tagname2tag(char *tagname)
654 {
655         return (tagname2tag(&pf_tags, tagname));
656 }
657
658 void
659 pf_tag2tagname(u_int16_t tagid, char *p)
660 {
661         return (tag2tagname(&pf_tags, tagid, p));
662 }
663
664 void
665 pf_tag_unref(u_int16_t tag)
666 {
667         return (tag_unref(&pf_tags, tag));
668 }
669
670 #ifdef ALTQ
671 u_int32_t
672 pf_qname2qid(char *qname)
673 {
674         return ((u_int32_t)tagname2tag(&pf_qids, qname));
675 }
676
677 void
678 pf_qid2qname(u_int32_t qid, char *p)
679 {
680         return (tag2tagname(&pf_qids, (u_int16_t)qid, p));
681 }
682
683 void
684 pf_qid_unref(u_int32_t qid)
685 {
686         return (tag_unref(&pf_qids, (u_int16_t)qid));
687 }
688
689 int
690 pf_begin_altq(u_int32_t *ticket)
691 {
692         struct pf_altq  *altq;
693         int              error = 0;
694
695         /* Purge the old altq list */
696         while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
697                 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
698                 if (altq->qname[0] == 0) {
699                         /* detach and destroy the discipline */
700                         error = altq_remove(altq);
701                 } else
702                         pf_qid_unref(altq->qid);
703                 pool_put(&pf_altq_pl, altq);
704         }
705         if (error)
706                 return (error);
707         *ticket = ++ticket_altqs_inactive;
708         altqs_inactive_open = 1;
709         return (0);
710 }
711
712 int
713 pf_rollback_altq(u_int32_t ticket)
714 {
715         struct pf_altq  *altq;
716         int              error = 0;
717
718         if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
719                 return (0);
720         /* Purge the old altq list */
721         while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
722                 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
723                 if (altq->qname[0] == 0) {
724                         /* detach and destroy the discipline */
725                         error = altq_remove(altq);
726                 } else
727                         pf_qid_unref(altq->qid);
728                 pool_put(&pf_altq_pl, altq);
729         }
730         altqs_inactive_open = 0;
731         return (error);
732 }
733
734 int
735 pf_commit_altq(u_int32_t ticket)
736 {
737         struct pf_altqqueue     *old_altqs;
738         struct pf_altq          *altq;
739         int                      err, error = 0;
740
741         if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
742                 return (EBUSY);
743
744         /* swap altqs, keep the old. */
745         crit_enter();
746         old_altqs = pf_altqs_active;
747         pf_altqs_active = pf_altqs_inactive;
748         pf_altqs_inactive = old_altqs;
749         ticket_altqs_active = ticket_altqs_inactive;
750
751         /* Attach new disciplines */
752         TAILQ_FOREACH(altq, pf_altqs_active, entries) {
753                 if (altq->qname[0] == 0) {
754                         /* attach the discipline */
755                         error = altq_pfattach(altq);
756                         if (error) {
757                                 crit_exit();
758                                 return (error);
759                         }
760                 }
761         }
762
763         /* Purge the old altq list */
764         while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
765                 TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
766                 if (altq->qname[0] == 0) {
767                         /* detach and destroy the discipline */
768                         err = altq_pfdetach(altq);
769                         if (err != 0 && error == 0)
770                                 error = err;
771                         err = altq_remove(altq);
772                         if (err != 0 && error == 0)
773                                 error = err;
774                 } else
775                         pf_qid_unref(altq->qid);
776                 pool_put(&pf_altq_pl, altq);
777         }
778         crit_exit();
779
780         altqs_inactive_open = 0;
781         return (error);
782 }
783 #endif /* ALTQ */
784
785 int
786 pf_begin_rules(u_int32_t *ticket, int rs_num, char *anchor, char *ruleset)
787 {
788         struct pf_ruleset       *rs;
789         struct pf_rule          *rule;
790
791         if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
792                 return (EINVAL);
793         rs = pf_find_or_create_ruleset(anchor, ruleset);
794         if (rs == NULL)
795                 return (EINVAL);
796         while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL)
797                 pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
798         *ticket = ++rs->rules[rs_num].inactive.ticket;
799         rs->rules[rs_num].inactive.open = 1;
800         return (0);
801 }
802
803 int
804 pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset)
805 {
806         struct pf_ruleset       *rs;
807         struct pf_rule          *rule;
808
809         if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
810                 return (EINVAL);
811         rs = pf_find_ruleset(anchor, ruleset);
812         if (rs == NULL || !rs->rules[rs_num].inactive.open ||
813             rs->rules[rs_num].inactive.ticket != ticket)
814                 return (0);
815         while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL)
816                 pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
817         rs->rules[rs_num].inactive.open = 0;
818         return (0);
819 }
820
821 int
822 pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset)
823 {
824         struct pf_ruleset       *rs;
825         struct pf_rule          *rule;
826         struct pf_rulequeue     *old_rules;
827
828         if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
829                 return (EINVAL);
830         rs = pf_find_ruleset(anchor, ruleset);
831         if (rs == NULL || !rs->rules[rs_num].inactive.open ||
832             ticket != rs->rules[rs_num].inactive.ticket)
833                 return (EBUSY);
834
835         /* Swap rules, keep the old. */
836         crit_enter();
837         old_rules = rs->rules[rs_num].active.ptr;
838         rs->rules[rs_num].active.ptr =
839             rs->rules[rs_num].inactive.ptr;
840         rs->rules[rs_num].inactive.ptr = old_rules;
841         rs->rules[rs_num].active.ticket =
842             rs->rules[rs_num].inactive.ticket;
843         pf_calc_skip_steps(rs->rules[rs_num].active.ptr);
844
845         /* Purge the old rule list. */
846         while ((rule = TAILQ_FIRST(old_rules)) != NULL)
847                 pf_rm_rule(old_rules, rule);
848         rs->rules[rs_num].inactive.open = 0;
849         pf_remove_if_empty_ruleset(rs);
850         pf_update_anchor_rules();
851         crit_exit();
852         return (0);
853 }
854
855 int
856 pfioctl(struct dev_ioctl_args *ap)
857 {
858         u_long cmd = ap->a_cmd;
859         caddr_t addr = ap->a_data;
860         struct pf_pooladdr      *pa = NULL;
861         struct pf_pool          *pool = NULL;
862         int                      error = 0;
863
864         /* XXX keep in sync with switch() below */
865         if (securelevel > 1)
866                 switch (cmd) {
867                 case DIOCGETRULES:
868                 case DIOCGETRULE:
869                 case DIOCGETADDRS:
870                 case DIOCGETADDR:
871                 case DIOCGETSTATE:
872                 case DIOCSETSTATUSIF:
873                 case DIOCGETSTATUS:
874                 case DIOCCLRSTATUS:
875                 case DIOCNATLOOK:
876                 case DIOCSETDEBUG:
877                 case DIOCGETSTATES:
878                 case DIOCGETTIMEOUT:
879                 case DIOCCLRRULECTRS:
880                 case DIOCGETLIMIT:
881                 case DIOCGETALTQS:
882                 case DIOCGETALTQ:
883                 case DIOCGETQSTATS:
884                 case DIOCGETANCHORS:
885                 case DIOCGETANCHOR:
886                 case DIOCGETRULESETS:
887                 case DIOCGETRULESET:
888                 case DIOCRGETTABLES:
889                 case DIOCRGETTSTATS:
890                 case DIOCRCLRTSTATS:
891                 case DIOCRCLRADDRS:
892                 case DIOCRADDADDRS:
893                 case DIOCRDELADDRS:
894                 case DIOCRSETADDRS:
895                 case DIOCRGETADDRS:
896                 case DIOCRGETASTATS:
897                 case DIOCRCLRASTATS:
898                 case DIOCRTSTADDRS:
899                 case DIOCOSFPGET:
900                 case DIOCGETSRCNODES:
901                 case DIOCCLRSRCNODES:
902                 case DIOCIGETIFACES:
903                 case DIOCICLRISTATS:
904                 case DIOCGIFSPEED:
905                         break;
906                 case DIOCRCLRTABLES:
907                 case DIOCRADDTABLES:
908                 case DIOCRDELTABLES:
909                 case DIOCRSETTFLAGS:
910                         if (((struct pfioc_table *)addr)->pfrio_flags &
911                             PFR_FLAG_DUMMY)
912                                 break; /* dummy operation ok */
913                         return (EPERM);
914                 default:
915                         return (EPERM);
916                 }
917
918         if (!(ap->a_fflag & FWRITE))
919                 switch (cmd) {
920                 case DIOCGETRULES:
921                 case DIOCGETRULE:
922                 case DIOCGETADDRS:
923                 case DIOCGETADDR:
924                 case DIOCGETSTATE:
925                 case DIOCGETSTATUS:
926                 case DIOCGETSTATES:
927                 case DIOCGETTIMEOUT:
928                 case DIOCGETLIMIT:
929                 case DIOCGETALTQS:
930                 case DIOCGETALTQ:
931                 case DIOCGETQSTATS:
932                 case DIOCGETANCHORS:
933                 case DIOCGETANCHOR:
934                 case DIOCGETRULESETS:
935                 case DIOCGETRULESET:
936                 case DIOCRGETTABLES:
937                 case DIOCRGETTSTATS:
938                 case DIOCRGETADDRS:
939                 case DIOCRGETASTATS:
940                 case DIOCRTSTADDRS:
941                 case DIOCOSFPGET:
942                 case DIOCGETSRCNODES:
943                 case DIOCIGETIFACES:
944                 case DIOCGIFSPEED:
945                         break;
946                 case DIOCRCLRTABLES:
947                 case DIOCRADDTABLES:
948                 case DIOCRDELTABLES:
949                 case DIOCRCLRTSTATS:
950                 case DIOCRCLRADDRS:
951                 case DIOCRADDADDRS:
952                 case DIOCRDELADDRS:
953                 case DIOCRSETADDRS:
954                 case DIOCRSETTFLAGS:
955                         if (((struct pfioc_table *)addr)->pfrio_flags &
956                             PFR_FLAG_DUMMY)
957                                 break; /* dummy operation ok */
958                         return (EACCES);
959                 default:
960                         return (EACCES);
961                 }
962
963         switch (cmd) {
964
965         case DIOCSTART:
966                 if (pf_status.running)
967                         error = EEXIST;
968                 else {
969                         error = hook_pf();
970                         if (error) {
971                                 DPFPRINTF(PF_DEBUG_MISC,
972                                     ("pf: pfil registeration fail\n"));
973                                 break;
974                         }
975                         pf_status.running = 1;
976                         pf_status.since = time_second;
977                         if (pf_status.stateid == 0) {
978                                 pf_status.stateid = time_second;
979                                 pf_status.stateid = pf_status.stateid << 32;
980                         }
981                         DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
982                 }
983                 break;
984
985         case DIOCSTOP:
986                 if (!pf_status.running)
987                         error = ENOENT;
988                 else {
989                         pf_status.running = 0;
990                         error = dehook_pf();
991                         if (error) {
992                                 pf_status.running = 1;
993                                 DPFPRINTF(PF_DEBUG_MISC,
994                                         ("pf: pfil unregisteration failed\n"));
995                         }
996                         pf_status.since = time_second;
997                         DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
998                 }
999                 break;
1000
1001         case DIOCBEGINRULES: {
1002                 struct pfioc_rule       *pr = (struct pfioc_rule *)addr;
1003
1004                 error = pf_begin_rules(&pr->ticket, pf_get_ruleset_number(
1005                     pr->rule.action), pr->anchor, pr->ruleset);
1006                 break;
1007         }
1008
1009         case DIOCADDRULE: {
1010                 struct pfioc_rule       *pr = (struct pfioc_rule *)addr;
1011                 struct pf_ruleset       *ruleset;
1012                 struct pf_rule          *rule, *tail;
1013                 struct pf_pooladdr      *pa;
1014                 int                      rs_num;
1015
1016                 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
1017                 if (ruleset == NULL) {
1018                         error = EINVAL;
1019                         break;
1020                 }
1021                 rs_num = pf_get_ruleset_number(pr->rule.action);
1022                 if (rs_num >= PF_RULESET_MAX) {
1023                         error = EINVAL;
1024                         break;
1025                 }
1026                 if (pr->rule.anchorname[0] && ruleset != &pf_main_ruleset) {
1027                         error = EINVAL;
1028                         break;
1029                 }
1030                 if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
1031                         error = EINVAL;
1032                         break;
1033                 }
1034                 if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) {
1035                         error = EBUSY;
1036                         break;
1037                 }
1038                 if (pr->pool_ticket != ticket_pabuf) {
1039                         error = EBUSY;
1040                         break;
1041                 }
1042                 rule = pool_get(&pf_rule_pl, PR_NOWAIT);
1043                 if (rule == NULL) {
1044                         error = ENOMEM;
1045                         break;
1046                 }
1047                 bcopy(&pr->rule, rule, sizeof(struct pf_rule));
1048                 rule->anchor = NULL;
1049                 rule->kif = NULL;
1050                 TAILQ_INIT(&rule->rpool.list);
1051                 /* initialize refcounting */
1052                 rule->states = 0;
1053                 rule->src_nodes = 0;
1054                 rule->entries.tqe_prev = NULL;
1055 #ifndef INET
1056                 if (rule->af == AF_INET) {
1057                         pool_put(&pf_rule_pl, rule);
1058                         error = EAFNOSUPPORT;
1059                         break;
1060                 }
1061 #endif /* INET */
1062 #ifndef INET6
1063                 if (rule->af == AF_INET6) {
1064                         pool_put(&pf_rule_pl, rule);
1065                         error = EAFNOSUPPORT;
1066                         break;
1067                 }
1068 #endif /* INET6 */
1069                 tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
1070                     pf_rulequeue);
1071                 if (tail)
1072                         rule->nr = tail->nr + 1;
1073                 else
1074                         rule->nr = 0;
1075                 if (rule->ifname[0]) {
1076                         rule->kif = pfi_attach_rule(rule->ifname);
1077                         if (rule->kif == NULL) {
1078                                 pool_put(&pf_rule_pl, rule);
1079                                 error = EINVAL;
1080                                 break;
1081                         }
1082                 }
1083
1084 #ifdef ALTQ
1085                 /* set queue IDs */
1086                 if (rule->qname[0] != 0) {
1087                         if ((rule->qid = pf_qname2qid(rule->qname)) == 0)
1088                                 error = EBUSY;
1089                         else if (rule->pqname[0] != 0) {
1090                                 if ((rule->pqid =
1091                                     pf_qname2qid(rule->pqname)) == 0)
1092                                         error = EBUSY;
1093                         } else
1094                                 rule->pqid = rule->qid;
1095                 }
1096 #endif
1097                 if (rule->tagname[0])
1098                         if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
1099                                 error = EBUSY;
1100                 if (rule->match_tagname[0])
1101                         if ((rule->match_tag =
1102                             pf_tagname2tag(rule->match_tagname)) == 0)
1103                                 error = EBUSY;
1104                 if (rule->rt && !rule->direction)
1105                         error = EINVAL;
1106                 if (pfi_dynaddr_setup(&rule->src.addr, rule->af))
1107                         error = EINVAL;
1108                 if (pfi_dynaddr_setup(&rule->dst.addr, rule->af))
1109                         error = EINVAL;
1110                 if (pf_tbladdr_setup(ruleset, &rule->src.addr))
1111                         error = EINVAL;
1112                 if (pf_tbladdr_setup(ruleset, &rule->dst.addr))
1113                         error = EINVAL;
1114                 TAILQ_FOREACH(pa, &pf_pabuf, entries)
1115                         if (pf_tbladdr_setup(ruleset, &pa->addr))
1116                                 error = EINVAL;
1117
1118                 pf_mv_pool(&pf_pabuf, &rule->rpool.list);
1119                 if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
1120                     (rule->action == PF_BINAT)) && !rule->anchorname[0]) ||
1121                     (rule->rt > PF_FASTROUTE)) &&
1122                     (TAILQ_FIRST(&rule->rpool.list) == NULL))
1123                         error = EINVAL;
1124
1125                 if (error) {
1126                         pf_rm_rule(NULL, rule);
1127                         break;
1128                 }
1129                 rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
1130                 rule->evaluations = rule->packets = rule->bytes = 0;
1131                 TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr,
1132                     rule, entries);
1133                 break;
1134         }
1135
1136         case DIOCCOMMITRULES: {
1137                 struct pfioc_rule       *pr = (struct pfioc_rule *)addr;
1138
1139                 error = pf_commit_rules(pr->ticket, pf_get_ruleset_number(
1140                     pr->rule.action), pr->anchor, pr->ruleset);
1141                 break;
1142         }
1143
1144         case DIOCGETRULES: {
1145                 struct pfioc_rule       *pr = (struct pfioc_rule *)addr;
1146                 struct pf_ruleset       *ruleset;
1147                 struct pf_rule          *tail;
1148                 int                      rs_num;
1149
1150                 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
1151                 if (ruleset == NULL) {
1152                         error = EINVAL;
1153                         break;
1154                 }
1155                 rs_num = pf_get_ruleset_number(pr->rule.action);
1156                 if (rs_num >= PF_RULESET_MAX) {
1157                         error = EINVAL;
1158                         break;
1159                 }
1160                 crit_enter();
1161                 tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
1162                     pf_rulequeue);
1163                 if (tail)
1164                         pr->nr = tail->nr + 1;
1165                 else
1166                         pr->nr = 0;
1167                 pr->ticket = ruleset->rules[rs_num].active.ticket;
1168                 crit_exit();
1169                 break;
1170         }
1171
1172         case DIOCGETRULE: {
1173                 struct pfioc_rule       *pr = (struct pfioc_rule *)addr;
1174                 struct pf_ruleset       *ruleset;
1175                 struct pf_rule          *rule;
1176                 int                      rs_num, i;
1177
1178                 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset);
1179                 if (ruleset == NULL) {
1180                         error = EINVAL;
1181                         break;
1182                 }
1183                 rs_num = pf_get_ruleset_number(pr->rule.action);
1184                 if (rs_num >= PF_RULESET_MAX) {
1185                         error = EINVAL;
1186                         break;
1187                 }
1188                 if (pr->ticket != ruleset->rules[rs_num].active.ticket) {
1189                         error = EBUSY;
1190                         break;
1191                 }
1192                 crit_enter();
1193                 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
1194                 while ((rule != NULL) && (rule->nr != pr->nr))
1195                         rule = TAILQ_NEXT(rule, entries);
1196                 if (rule == NULL) {
1197                         error = EBUSY;
1198                         crit_exit();
1199                         break;
1200                 }
1201                 bcopy(rule, &pr->rule, sizeof(struct pf_rule));
1202                 pfi_dynaddr_copyout(&pr->rule.src.addr);
1203                 pfi_dynaddr_copyout(&pr->rule.dst.addr);
1204                 pf_tbladdr_copyout(&pr->rule.src.addr);
1205                 pf_tbladdr_copyout(&pr->rule.dst.addr);
1206                 for (i = 0; i < PF_SKIP_COUNT; ++i)
1207                         if (rule->skip[i].ptr == NULL)
1208                                 pr->rule.skip[i].nr = (uint32_t)(-1);
1209                         else
1210                                 pr->rule.skip[i].nr =
1211                                     rule->skip[i].ptr->nr;
1212                 crit_exit();
1213                 break;
1214         }
1215
1216         case DIOCCHANGERULE: {
1217                 struct pfioc_rule       *pcr = (struct pfioc_rule *)addr;
1218                 struct pf_ruleset       *ruleset;
1219                 struct pf_rule          *oldrule = NULL, *newrule = NULL;
1220                 u_int32_t                nr = 0;
1221                 int                      rs_num;
1222
1223                 if (!(pcr->action == PF_CHANGE_REMOVE ||
1224                     pcr->action == PF_CHANGE_GET_TICKET) &&
1225                     pcr->pool_ticket != ticket_pabuf) {
1226                         error = EBUSY;
1227                         break;
1228                 }
1229
1230                 if (pcr->action < PF_CHANGE_ADD_HEAD ||
1231                     pcr->action > PF_CHANGE_GET_TICKET) {
1232                         error = EINVAL;
1233                         break;
1234                 }
1235                 ruleset = pf_find_ruleset(pcr->anchor, pcr->ruleset);
1236                 if (ruleset == NULL) {
1237                         error = EINVAL;
1238                         break;
1239                 }
1240                 rs_num = pf_get_ruleset_number(pcr->rule.action);
1241                 if (rs_num >= PF_RULESET_MAX) {
1242                         error = EINVAL;
1243                         break;
1244                 }
1245
1246                 if (pcr->action == PF_CHANGE_GET_TICKET) {
1247                         pcr->ticket = ++ruleset->rules[rs_num].active.ticket;
1248                         break;
1249                 } else {
1250                         if (pcr->ticket !=
1251                             ruleset->rules[rs_num].active.ticket) {
1252                                 error = EINVAL;
1253                                 break;
1254                         }
1255                         if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
1256                                 error = EINVAL;
1257                                 break;
1258                         }
1259                 }
1260
1261                 if (pcr->action != PF_CHANGE_REMOVE) {
1262                         newrule = pool_get(&pf_rule_pl, PR_NOWAIT);
1263                         if (newrule == NULL) {
1264                                 error = ENOMEM;
1265                                 break;
1266                         }
1267                         bcopy(&pcr->rule, newrule, sizeof(struct pf_rule));
1268                         TAILQ_INIT(&newrule->rpool.list);
1269                         /* initialize refcounting */
1270                         newrule->states = 0;
1271                         newrule->entries.tqe_prev = NULL;
1272 #ifndef INET
1273                         if (newrule->af == AF_INET) {
1274                                 pool_put(&pf_rule_pl, newrule);
1275                                 error = EAFNOSUPPORT;
1276                                 break;
1277                         }
1278 #endif /* INET */
1279 #ifndef INET6
1280                         if (newrule->af == AF_INET6) {
1281                                 pool_put(&pf_rule_pl, newrule);
1282                                 error = EAFNOSUPPORT;
1283                                 break;
1284                         }
1285 #endif /* INET6 */
1286                         if (newrule->ifname[0]) {
1287                                 newrule->kif = pfi_attach_rule(newrule->ifname);
1288                                 if (newrule->kif == NULL) {
1289                                         pool_put(&pf_rule_pl, newrule);
1290                                         error = EINVAL;
1291                                         break;
1292                                 }
1293                         } else
1294                                 newrule->kif = NULL;
1295
1296 #ifdef ALTQ
1297                         /* set queue IDs */
1298                         if (newrule->qname[0] != 0) {
1299                                 if ((newrule->qid =
1300                                     pf_qname2qid(newrule->qname)) == 0)
1301                                         error = EBUSY;
1302                                 else if (newrule->pqname[0] != 0) {
1303                                         if ((newrule->pqid =
1304                                             pf_qname2qid(newrule->pqname)) == 0)
1305                                                 error = EBUSY;
1306                                 } else
1307                                         newrule->pqid = newrule->qid;
1308                         }
1309 #endif
1310                         if (newrule->tagname[0])
1311                                 if ((newrule->tag =
1312                                     pf_tagname2tag(newrule->tagname)) == 0)
1313                                         error = EBUSY;
1314                         if (newrule->match_tagname[0])
1315                                 if ((newrule->match_tag = pf_tagname2tag(
1316                                     newrule->match_tagname)) == 0)
1317                                         error = EBUSY;
1318
1319                         if (newrule->rt && !newrule->direction)
1320                                 error = EINVAL;
1321                         if (pfi_dynaddr_setup(&newrule->src.addr, newrule->af))
1322                                 error = EINVAL;
1323                         if (pfi_dynaddr_setup(&newrule->dst.addr, newrule->af))
1324                                 error = EINVAL;
1325                         if (pf_tbladdr_setup(ruleset, &newrule->src.addr))
1326                                 error = EINVAL;
1327                         if (pf_tbladdr_setup(ruleset, &newrule->dst.addr))
1328                                 error = EINVAL;
1329
1330                         pf_mv_pool(&pf_pabuf, &newrule->rpool.list);
1331                         if (((((newrule->action == PF_NAT) ||
1332                             (newrule->action == PF_RDR) ||
1333                             (newrule->action == PF_BINAT) ||
1334                             (newrule->rt > PF_FASTROUTE)) &&
1335                             !newrule->anchorname[0])) &&
1336                             (TAILQ_FIRST(&newrule->rpool.list) == NULL))
1337                                 error = EINVAL;
1338
1339                         if (error) {
1340                                 pf_rm_rule(NULL, newrule);
1341                                 break;
1342                         }
1343                         newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list);
1344                         newrule->evaluations = newrule->packets = 0;
1345                         newrule->bytes = 0;
1346                 }
1347                 pf_empty_pool(&pf_pabuf);
1348
1349                 crit_enter();
1350
1351                 if (pcr->action == PF_CHANGE_ADD_HEAD)
1352                         oldrule = TAILQ_FIRST(
1353                             ruleset->rules[rs_num].active.ptr);
1354                 else if (pcr->action == PF_CHANGE_ADD_TAIL)
1355                         oldrule = TAILQ_LAST(
1356                             ruleset->rules[rs_num].active.ptr, pf_rulequeue);
1357                 else {
1358                         oldrule = TAILQ_FIRST(
1359                             ruleset->rules[rs_num].active.ptr);
1360                         while ((oldrule != NULL) && (oldrule->nr != pcr->nr))
1361                                 oldrule = TAILQ_NEXT(oldrule, entries);
1362                         if (oldrule == NULL) {
1363                                 pf_rm_rule(NULL, newrule);
1364                                 error = EINVAL;
1365                                 crit_exit();
1366                                 break;
1367                         }
1368                 }
1369
1370                 if (pcr->action == PF_CHANGE_REMOVE)
1371                         pf_rm_rule(ruleset->rules[rs_num].active.ptr, oldrule);
1372                 else {
1373                         if (oldrule == NULL)
1374                                 TAILQ_INSERT_TAIL(
1375                                     ruleset->rules[rs_num].active.ptr,
1376                                     newrule, entries);
1377                         else if (pcr->action == PF_CHANGE_ADD_HEAD ||
1378                             pcr->action == PF_CHANGE_ADD_BEFORE)
1379                                 TAILQ_INSERT_BEFORE(oldrule, newrule, entries);
1380                         else
1381                                 TAILQ_INSERT_AFTER(
1382                                     ruleset->rules[rs_num].active.ptr,
1383                                     oldrule, newrule, entries);
1384                 }
1385
1386                 nr = 0;
1387                 TAILQ_FOREACH(oldrule,
1388                     ruleset->rules[rs_num].active.ptr, entries)
1389                         oldrule->nr = nr++;
1390
1391                 pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
1392                 pf_remove_if_empty_ruleset(ruleset);
1393                 pf_update_anchor_rules();
1394
1395                 ruleset->rules[rs_num].active.ticket++;
1396                 crit_exit();
1397                 break;
1398         }
1399
1400         case DIOCCLRSTATES: {
1401                 struct pf_state         *state;
1402                 struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
1403                 int                      killed = 0;
1404
1405                 crit_enter();
1406                 RB_FOREACH(state, pf_state_tree_id, &tree_id) {
1407                         if (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
1408                             state->u.s.kif->pfik_name)) {
1409                                 state->timeout = PFTM_PURGE;
1410 #if NPFSYNC
1411                                 /* don't send out individual delete messages */
1412                                 state->sync_flags = PFSTATE_NOSYNC;
1413 #endif
1414                                 killed++;
1415                         }
1416                 }
1417                 pf_purge_expired_states();
1418                 pf_status.states = 0;
1419                 psk->psk_af = killed;
1420 #if NPFSYNC
1421                 pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
1422 #endif
1423                 crit_exit();
1424                 break;
1425         }
1426
1427         case DIOCKILLSTATES: {
1428                 struct pf_state         *state;
1429                 struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
1430                 int                      killed = 0;
1431
1432                 crit_enter();
1433                 RB_FOREACH(state, pf_state_tree_id, &tree_id) {
1434                         if ((!psk->psk_af || state->af == psk->psk_af)
1435                             && (!psk->psk_proto || psk->psk_proto ==
1436                             state->proto) &&
1437                             PF_MATCHA(psk->psk_src.not,
1438                             &psk->psk_src.addr.v.a.addr,
1439                             &psk->psk_src.addr.v.a.mask,
1440                             &state->lan.addr, state->af) &&
1441                             PF_MATCHA(psk->psk_dst.not,
1442                             &psk->psk_dst.addr.v.a.addr,
1443                             &psk->psk_dst.addr.v.a.mask,
1444                             &state->ext.addr, state->af) &&
1445                             (psk->psk_src.port_op == 0 ||
1446                             pf_match_port(psk->psk_src.port_op,
1447                             psk->psk_src.port[0], psk->psk_src.port[1],
1448                             state->lan.port)) &&
1449                             (psk->psk_dst.port_op == 0 ||
1450                             pf_match_port(psk->psk_dst.port_op,
1451                             psk->psk_dst.port[0], psk->psk_dst.port[1],
1452                             state->ext.port)) &&
1453                             (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
1454                             state->u.s.kif->pfik_name))) {
1455                                 state->timeout = PFTM_PURGE;
1456                                 killed++;
1457                         }
1458                 }
1459                 pf_purge_expired_states();
1460                 crit_exit();
1461                 psk->psk_af = killed;
1462                 break;
1463         }
1464
1465         case DIOCADDSTATE: {
1466                 struct pfioc_state      *ps = (struct pfioc_state *)addr;
1467                 struct pf_state         *state;
1468                 struct pfi_kif          *kif;
1469
1470                 if (ps->state.timeout >= PFTM_MAX &&
1471                     ps->state.timeout != PFTM_UNTIL_PACKET) {
1472                         error = EINVAL;
1473                         break;
1474                 }
1475                 state = pool_get(&pf_state_pl, PR_NOWAIT);
1476                 if (state == NULL) {
1477                         error = ENOMEM;
1478                         break;
1479                 }
1480                 crit_enter();
1481                 kif = pfi_lookup_create(ps->state.u.ifname);
1482                 if (kif == NULL) {
1483                         pool_put(&pf_state_pl, state);
1484                         error = ENOENT;
1485                         crit_exit();
1486                         break;
1487                 }
1488                 bcopy(&ps->state, state, sizeof(struct pf_state));
1489                 bzero(&state->u, sizeof(state->u));
1490                 state->rule.ptr = &pf_default_rule;
1491                 state->nat_rule.ptr = NULL;
1492                 state->anchor.ptr = NULL;
1493                 state->rt_kif = NULL;
1494                 state->creation = time_second;
1495                 state->pfsync_time = 0;
1496                 state->packets[0] = state->packets[1] = 0;
1497                 state->bytes[0] = state->bytes[1] = 0;
1498
1499                 if (pf_insert_state(kif, state)) {
1500                         pfi_maybe_destroy(kif);
1501                         pool_put(&pf_state_pl, state);
1502                         error = ENOMEM;
1503                 }
1504                 crit_exit();
1505                 break;
1506         }
1507
1508         case DIOCGETSTATE: {
1509                 struct pfioc_state      *ps = (struct pfioc_state *)addr;
1510                 struct pf_state         *state;
1511                 u_int32_t                nr;
1512
1513                 nr = 0;
1514                 crit_enter();
1515                 RB_FOREACH(state, pf_state_tree_id, &tree_id) {
1516                         if (nr >= ps->nr)
1517                                 break;
1518                         nr++;
1519                 }
1520                 if (state == NULL) {
1521                         error = EBUSY;
1522                         crit_exit();
1523                         break;
1524                 }
1525                 bcopy(state, &ps->state, sizeof(struct pf_state));
1526                 ps->state.rule.nr = state->rule.ptr->nr;
1527                 ps->state.nat_rule.nr = (state->nat_rule.ptr == NULL) ?
1528                     (uint32_t)(-1) : state->nat_rule.ptr->nr;
1529                 ps->state.anchor.nr = (state->anchor.ptr == NULL) ?
1530                     (uint32_t)(-1) : state->anchor.ptr->nr;
1531                 crit_exit();
1532                 ps->state.expire = pf_state_expires(state);
1533                 if (ps->state.expire > time_second)
1534                         ps->state.expire -= time_second;
1535                 else
1536                         ps->state.expire = 0;
1537                 break;
1538         }
1539
1540         case DIOCGETSTATES: {
1541                 struct pfioc_states     *ps = (struct pfioc_states *)addr;
1542                 struct pf_state         *state;
1543                 struct pf_state         *p, pstore;
1544                 struct pfi_kif          *kif;
1545                 u_int32_t                nr = 0;
1546                 int                      space = ps->ps_len;
1547
1548                 if (space == 0) {
1549                         crit_enter();
1550                         TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states)
1551                                 nr += kif->pfik_states;
1552                         crit_exit();
1553                         ps->ps_len = sizeof(struct pf_state) * nr;
1554                         return (0);
1555                 }
1556
1557                 crit_enter();
1558                 p = ps->ps_states;
1559                 TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states)
1560                         RB_FOREACH(state, pf_state_tree_ext_gwy,
1561                             &kif->pfik_ext_gwy) {
1562                                 int     secs = time_second;
1563
1564                                 if ((nr+1) * sizeof(*p) > (unsigned)ps->ps_len)
1565                                         break;
1566
1567                                 bcopy(state, &pstore, sizeof(pstore));
1568                                 strlcpy(pstore.u.ifname, kif->pfik_name,
1569                                     sizeof(pstore.u.ifname));
1570                                 pstore.rule.nr = state->rule.ptr->nr;
1571                                 pstore.nat_rule.nr = (state->nat_rule.ptr ==
1572                                     NULL) ? (uint32_t)(-1)
1573                                           : state->nat_rule.ptr->nr;
1574                                 pstore.anchor.nr = (state->anchor.ptr ==
1575                                     NULL) ? (uint32_t)(-1)
1576                                           : state->anchor.ptr->nr;
1577                                 pstore.creation = secs - pstore.creation;
1578                                 pstore.expire = pf_state_expires(state);
1579                                 if (pstore.expire > secs)
1580                                         pstore.expire -= secs;
1581                                 else
1582                                         pstore.expire = 0;
1583                                 error = copyout(&pstore, p, sizeof(*p));
1584                                 if (error) {
1585                                         crit_exit();
1586                                         goto fail;
1587                                 }
1588                                 p++;
1589                                 nr++;
1590                         }
1591                 ps->ps_len = sizeof(struct pf_state) * nr;
1592                 crit_exit();
1593                 break;
1594         }
1595
1596         case DIOCGETSTATUS: {
1597                 struct pf_status *s = (struct pf_status *)addr;
1598                 bcopy(&pf_status, s, sizeof(struct pf_status));
1599                 pfi_fill_oldstatus(s);
1600                 break;
1601         }
1602
1603         case DIOCSETSTATUSIF: {
1604                 struct pfioc_if *pi = (struct pfioc_if *)addr;
1605
1606                 if (pi->ifname[0] == 0) {
1607                         bzero(pf_status.ifname, IFNAMSIZ);
1608                         break;
1609                 }
1610                 if (ifunit(pi->ifname) == NULL) {
1611                         error = EINVAL;
1612                         break;
1613                 }
1614                 strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ);
1615                 break;
1616         }
1617
1618         case DIOCCLRSTATUS: {
1619                 bzero(pf_status.counters, sizeof(pf_status.counters));
1620                 bzero(pf_status.fcounters, sizeof(pf_status.fcounters));
1621                 bzero(pf_status.scounters, sizeof(pf_status.scounters));
1622                 if (*pf_status.ifname)
1623                         pfi_clr_istats(pf_status.ifname, NULL,
1624                             PFI_FLAG_INSTANCE);
1625                 break;
1626         }
1627
1628         case DIOCNATLOOK: {
1629                 struct pfioc_natlook    *pnl = (struct pfioc_natlook *)addr;
1630                 struct pf_state         *state;
1631                 struct pf_state          key;
1632                 int                      m = 0, direction = pnl->direction;
1633
1634                 key.af = pnl->af;
1635                 key.proto = pnl->proto;
1636
1637                 if (!pnl->proto ||
1638                     PF_AZERO(&pnl->saddr, pnl->af) ||
1639                     PF_AZERO(&pnl->daddr, pnl->af) ||
1640                     !pnl->dport || !pnl->sport)
1641                         error = EINVAL;
1642                 else {
1643                         crit_enter();
1644
1645                         /*
1646                          * userland gives us source and dest of connection,
1647                          * reverse the lookup so we ask for what happens with
1648                          * the return traffic, enabling us to find it in the
1649                          * state tree.
1650                          */
1651                         if (direction == PF_IN) {
1652                                 PF_ACPY(&key.ext.addr, &pnl->daddr, pnl->af);
1653                                 key.ext.port = pnl->dport;
1654                                 PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af);
1655                                 key.gwy.port = pnl->sport;
1656                                 state = pf_find_state_all(&key, PF_EXT_GWY, &m);
1657                         } else {
1658                                 PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af);
1659                                 key.lan.port = pnl->dport;
1660                                 PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af);
1661                                 key.ext.port = pnl->sport;
1662                                 state = pf_find_state_all(&key, PF_LAN_EXT, &m);
1663                         }
1664                         if (m > 1)
1665                                 error = E2BIG;  /* more than one state */
1666                         else if (state != NULL) {
1667                                 if (direction == PF_IN) {
1668                                         PF_ACPY(&pnl->rsaddr, &state->lan.addr,
1669                                             state->af);
1670                                         pnl->rsport = state->lan.port;
1671                                         PF_ACPY(&pnl->rdaddr, &pnl->daddr,
1672                                             pnl->af);
1673                                         pnl->rdport = pnl->dport;
1674                                 } else {
1675                                         PF_ACPY(&pnl->rdaddr, &state->gwy.addr,
1676                                             state->af);
1677                                         pnl->rdport = state->gwy.port;
1678                                         PF_ACPY(&pnl->rsaddr, &pnl->saddr,
1679                                             pnl->af);
1680                                         pnl->rsport = pnl->sport;
1681                                 }
1682                         } else
1683                                 error = ENOENT;
1684                         crit_exit();
1685                 }
1686                 break;
1687         }
1688
1689         case DIOCSETTIMEOUT: {
1690                 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
1691                 int              old;
1692
1693                 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
1694                     pt->seconds < 0) {
1695                         error = EINVAL;
1696                         goto fail;
1697                 }
1698                 old = pf_default_rule.timeout[pt->timeout];
1699                 pf_default_rule.timeout[pt->timeout] = pt->seconds;
1700                 pt->seconds = old;
1701                 break;
1702         }
1703
1704         case DIOCGETTIMEOUT: {
1705                 struct pfioc_tm *pt = (struct pfioc_tm *)addr;
1706
1707                 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
1708                         error = EINVAL;
1709                         goto fail;
1710                 }
1711                 pt->seconds = pf_default_rule.timeout[pt->timeout];
1712                 break;
1713         }
1714
1715         case DIOCGETLIMIT: {
1716                 struct pfioc_limit      *pl = (struct pfioc_limit *)addr;
1717
1718                 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
1719                         error = EINVAL;
1720                         goto fail;
1721                 }
1722                 pl->limit = pf_pool_limits[pl->index].limit;
1723                 break;
1724         }
1725
1726         case DIOCSETLIMIT: {
1727                 struct pfioc_limit      *pl = (struct pfioc_limit *)addr;
1728                 int                      old_limit;
1729
1730                 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
1731                     pf_pool_limits[pl->index].pp == NULL) {
1732                         error = EINVAL;
1733                         goto fail;
1734                 }
1735
1736                 /* XXX Get an API to set limits on the zone/pool */
1737                 old_limit = pf_pool_limits[pl->index].limit;
1738                 pf_pool_limits[pl->index].limit = pl->limit;
1739                 pl->limit = old_limit;
1740                 break;
1741         }
1742
1743         case DIOCSETDEBUG: {
1744                 u_int32_t       *level = (u_int32_t *)addr;
1745
1746                 pf_status.debug = *level;
1747                 break;
1748         }
1749
1750         case DIOCCLRRULECTRS: {
1751                 struct pf_ruleset       *ruleset = &pf_main_ruleset;
1752                 struct pf_rule          *rule;
1753
1754                 crit_enter();
1755                 TAILQ_FOREACH(rule,
1756                     ruleset->rules[PF_RULESET_FILTER].active.ptr, entries)
1757                         rule->evaluations = rule->packets =
1758                             rule->bytes = 0;
1759                 crit_exit();
1760                 break;
1761         }
1762
1763         case DIOCGIFSPEED: {
1764                 struct pf_ifspeed       *psp = (struct pf_ifspeed *)addr;
1765                 struct pf_ifspeed       ps;
1766                 struct ifnet            *ifp;
1767
1768                 if (psp->ifname[0] != 0) {
1769                         /* Can we completely trust user-land? */
1770                         strlcpy(ps.ifname, psp->ifname, IFNAMSIZ);
1771                         ifp = ifunit(ps.ifname);
1772                         if (ifp )
1773                                 psp->baudrate = ifp->if_baudrate;
1774                         else
1775                                 error = EINVAL;
1776                 } else
1777                         error = EINVAL;
1778                 break;
1779         }
1780 #ifdef ALTQ
1781         case DIOCSTARTALTQ: {
1782                 struct pf_altq          *altq;
1783                 struct ifnet            *ifp;
1784                 struct tb_profile        tb;
1785
1786                 /* enable all altq interfaces on active list */
1787                 crit_enter();
1788                 TAILQ_FOREACH(altq, pf_altqs_active, entries) {
1789                         if (altq->qname[0] == 0) {
1790                                 if ((ifp = ifunit(altq->ifname)) == NULL) {
1791                                         error = EINVAL;
1792                                         break;
1793                                 }
1794                                 if (ifp->if_snd.altq_type != ALTQT_NONE)
1795                                         error = altq_enable(&ifp->if_snd);
1796                                 if (error != 0)
1797                                         break;
1798                                 /* set tokenbucket regulator */
1799                                 tb.rate = altq->ifbandwidth;
1800                                 tb.depth = altq->tbrsize;
1801                                 error = tbr_set(&ifp->if_snd, &tb);
1802                                 if (error != 0)
1803                                         break;
1804                         }
1805                 }
1806                 crit_exit();
1807                 DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
1808                 break;
1809         }
1810
1811         case DIOCSTOPALTQ: {
1812                 struct pf_altq          *altq;
1813                 struct ifnet            *ifp;
1814                 struct tb_profile        tb;
1815                 int                      err;
1816
1817                 /* disable all altq interfaces on active list */
1818                 crit_enter();
1819                 TAILQ_FOREACH(altq, pf_altqs_active, entries) {
1820                         if (altq->qname[0] == 0) {
1821                                 if ((ifp = ifunit(altq->ifname)) == NULL) {
1822                                         error = EINVAL;
1823                                         break;
1824                                 }
1825                                 if (ifp->if_snd.altq_type != ALTQT_NONE) {
1826                                         err = altq_disable(&ifp->if_snd);
1827                                         if (err != 0 && error == 0)
1828                                                 error = err;
1829                                 }
1830                                 /* clear tokenbucket regulator */
1831                                 tb.rate = 0;
1832                                 err = tbr_set(&ifp->if_snd, &tb);
1833                                 if (err != 0 && error == 0)
1834                                         error = err;
1835                         }
1836                 }
1837                 crit_exit();
1838                 DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
1839                 break;
1840         }
1841
1842         case DIOCBEGINALTQS: {
1843                 u_int32_t       *ticket = (u_int32_t *)addr;
1844
1845                 error = pf_begin_altq(ticket);
1846                 break;
1847         }
1848
1849         case DIOCADDALTQ: {
1850                 struct pfioc_altq       *pa = (struct pfioc_altq *)addr;
1851                 struct pf_altq          *altq, *a;
1852
1853                 if (pa->ticket != ticket_altqs_inactive) {
1854                         error = EBUSY;
1855                         break;
1856                 }
1857                 altq = pool_get(&pf_altq_pl, PR_NOWAIT);
1858                 if (altq == NULL) {
1859                         error = ENOMEM;
1860                         break;
1861                 }
1862                 bcopy(&pa->altq, altq, sizeof(struct pf_altq));
1863
1864                 /*
1865                  * if this is for a queue, find the discipline and
1866                  * copy the necessary fields
1867                  */
1868                 if (altq->qname[0] != 0) {
1869                         if ((altq->qid = pf_qname2qid(altq->qname)) == 0) {
1870                                 error = EBUSY;
1871                                 pool_put(&pf_altq_pl, altq);
1872                                 break;
1873                         }
1874                         TAILQ_FOREACH(a, pf_altqs_inactive, entries) {
1875                                 if (strncmp(a->ifname, altq->ifname,
1876                                     IFNAMSIZ) == 0 && a->qname[0] == 0) {
1877                                         altq->altq_disc = a->altq_disc;
1878                                         break;
1879                                 }
1880                         }
1881                 }
1882
1883                 error = altq_add(altq);
1884                 if (error) {
1885                         pool_put(&pf_altq_pl, altq);
1886                         break;
1887                 }
1888
1889                 TAILQ_INSERT_TAIL(pf_altqs_inactive, altq, entries);
1890                 bcopy(altq, &pa->altq, sizeof(struct pf_altq));
1891                 break;
1892         }
1893
1894         case DIOCCOMMITALTQS: {
1895                 u_int32_t               ticket = *(u_int32_t *)addr;
1896
1897                 error = pf_commit_altq(ticket);
1898                 break;
1899         }
1900
1901         case DIOCGETALTQS: {
1902                 struct pfioc_altq       *pa = (struct pfioc_altq *)addr;
1903                 struct pf_altq          *altq;
1904
1905                 pa->nr = 0;
1906                 crit_enter();
1907                 TAILQ_FOREACH(altq, pf_altqs_active, entries)
1908                         pa->nr++;
1909                 pa->ticket = ticket_altqs_active;
1910                 crit_exit();
1911                 break;
1912         }
1913
1914         case DIOCGETALTQ: {
1915                 struct pfioc_altq       *pa = (struct pfioc_altq *)addr;
1916                 struct pf_altq          *altq;
1917                 u_int32_t                nr;
1918
1919                 if (pa->ticket != ticket_altqs_active) {
1920                         error = EBUSY;
1921                         break;
1922                 }
1923                 nr = 0;
1924                 crit_enter();
1925                 altq = TAILQ_FIRST(pf_altqs_active);
1926                 while ((altq != NULL) && (nr < pa->nr)) {
1927                         altq = TAILQ_NEXT(altq, entries);
1928                         nr++;
1929                 }
1930                 if (altq == NULL) {
1931                         error = EBUSY;
1932                         crit_exit();
1933                         break;
1934                 }
1935                 bcopy(altq, &pa->altq, sizeof(struct pf_altq));
1936                 crit_exit();
1937                 break;
1938         }
1939
1940         case DIOCCHANGEALTQ:
1941                 /* CHANGEALTQ not supported yet! */
1942                 error = ENODEV;
1943                 break;
1944
1945         case DIOCGETQSTATS: {
1946                 struct pfioc_qstats     *pq = (struct pfioc_qstats *)addr;
1947                 struct pf_altq          *altq;
1948                 u_int32_t                nr;
1949                 int                      nbytes;
1950
1951                 if (pq->ticket != ticket_altqs_active) {
1952                         error = EBUSY;
1953                         break;
1954                 }
1955                 nbytes = pq->nbytes;
1956                 nr = 0;
1957                 crit_enter();
1958                 altq = TAILQ_FIRST(pf_altqs_active);
1959                 while ((altq != NULL) && (nr < pq->nr)) {
1960                         altq = TAILQ_NEXT(altq, entries);
1961                         nr++;
1962                 }
1963                 if (altq == NULL) {
1964                         error = EBUSY;
1965                         crit_exit();
1966                         break;
1967                 }
1968                 error = altq_getqstats(altq, pq->buf, &nbytes);
1969                 crit_exit();
1970                 if (error == 0) {
1971                         pq->scheduler = altq->scheduler;
1972                         pq->nbytes = nbytes;
1973                 }
1974                 break;
1975         }
1976 #endif /* ALTQ */
1977
1978         case DIOCBEGINADDRS: {
1979                 struct pfioc_pooladdr   *pp = (struct pfioc_pooladdr *)addr;
1980
1981                 pf_empty_pool(&pf_pabuf);
1982                 pp->ticket = ++ticket_pabuf;
1983                 break;
1984         }
1985
1986         case DIOCADDADDR: {
1987                 struct pfioc_pooladdr   *pp = (struct pfioc_pooladdr *)addr;
1988
1989 #ifndef INET
1990                 if (pp->af == AF_INET) {
1991                         error = EAFNOSUPPORT;
1992                         break;
1993                 }
1994 #endif /* INET */
1995 #ifndef INET6
1996                 if (pp->af == AF_INET6) {
1997                         error = EAFNOSUPPORT;
1998                         break;
1999                 }
2000 #endif /* INET6 */
2001                 if (pp->addr.addr.type != PF_ADDR_ADDRMASK &&
2002                     pp->addr.addr.type != PF_ADDR_DYNIFTL &&
2003                     pp->addr.addr.type != PF_ADDR_TABLE) {
2004                         error = EINVAL;
2005                         break;
2006                 }
2007                 pa = pool_get(&pf_pooladdr_pl, PR_NOWAIT);
2008                 if (pa == NULL) {
2009                         error = ENOMEM;
2010                         break;
2011                 }
2012                 bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr));
2013                 if (pa->ifname[0]) {
2014                         pa->kif = pfi_attach_rule(pa->ifname);
2015                         if (pa->kif == NULL) {
2016                                 pool_put(&pf_pooladdr_pl, pa);
2017                                 error = EINVAL;
2018                                 break;
2019                         }
2020                 }
2021                 if (pfi_dynaddr_setup(&pa->addr, pp->af)) {
2022                         pfi_dynaddr_remove(&pa->addr);
2023                         pfi_detach_rule(pa->kif);
2024                         pool_put(&pf_pooladdr_pl, pa);
2025                         error = EINVAL;
2026                         break;
2027                 }
2028                 TAILQ_INSERT_TAIL(&pf_pabuf, pa, entries);
2029                 break;
2030         }
2031
2032         case DIOCGETADDRS: {
2033                 struct pfioc_pooladdr   *pp = (struct pfioc_pooladdr *)addr;
2034
2035                 pp->nr = 0;
2036                 crit_enter();
2037                 pool = pf_get_pool(pp->anchor, pp->ruleset, pp->ticket,
2038                     pp->r_action, pp->r_num, 0, 1, 0);
2039                 if (pool == NULL) {
2040                         error = EBUSY;
2041                         crit_exit();
2042                         break;
2043                 }
2044                 TAILQ_FOREACH(pa, &pool->list, entries)
2045                         pp->nr++;
2046                 crit_exit();
2047                 break;
2048         }
2049
2050         case DIOCGETADDR: {
2051                 struct pfioc_pooladdr   *pp = (struct pfioc_pooladdr *)addr;
2052                 u_int32_t                nr = 0;
2053
2054                 crit_enter();
2055                 pool = pf_get_pool(pp->anchor, pp->ruleset, pp->ticket,
2056                     pp->r_action, pp->r_num, 0, 1, 1);
2057                 if (pool == NULL) {
2058                         error = EBUSY;
2059                         crit_exit();
2060                         break;
2061                 }
2062                 pa = TAILQ_FIRST(&pool->list);
2063                 while ((pa != NULL) && (nr < pp->nr)) {
2064                         pa = TAILQ_NEXT(pa, entries);
2065                         nr++;
2066                 }
2067                 if (pa == NULL) {
2068                         error = EBUSY;
2069                         crit_exit();
2070                         break;
2071                 }
2072                 bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr));
2073                 pfi_dynaddr_copyout(&pp->addr.addr);
2074                 pf_tbladdr_copyout(&pp->addr.addr);
2075                 crit_exit();
2076                 break;
2077         }
2078
2079         case DIOCCHANGEADDR: {
2080                 struct pfioc_pooladdr   *pca = (struct pfioc_pooladdr *)addr;
2081                 struct pf_pooladdr      *oldpa = NULL, *newpa = NULL;
2082                 struct pf_ruleset       *ruleset;
2083
2084                 if (pca->action < PF_CHANGE_ADD_HEAD ||
2085                     pca->action > PF_CHANGE_REMOVE) {
2086                         error = EINVAL;
2087                         break;
2088                 }
2089                 if (pca->addr.addr.type != PF_ADDR_ADDRMASK &&
2090                     pca->addr.addr.type != PF_ADDR_DYNIFTL &&
2091                     pca->addr.addr.type != PF_ADDR_TABLE) {
2092                         error = EINVAL;
2093                         break;
2094                 }
2095
2096                 ruleset = pf_find_ruleset(pca->anchor, pca->ruleset);
2097                 if (ruleset == NULL) {
2098                         error = EBUSY;
2099                         break;
2100                 }
2101                 pool = pf_get_pool(pca->anchor, pca->ruleset, pca->ticket,
2102                     pca->r_action, pca->r_num, pca->r_last, 1, 1);
2103                 if (pool == NULL) {
2104                         error = EBUSY;
2105                         break;
2106                 }
2107                 if (pca->action != PF_CHANGE_REMOVE) {
2108                         newpa = pool_get(&pf_pooladdr_pl, PR_NOWAIT);
2109                         if (newpa == NULL) {
2110                                 error = ENOMEM;
2111                                 break;
2112                         }
2113                         bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr));
2114 #ifndef INET
2115                         if (pca->af == AF_INET) {
2116                                 pool_put(&pf_pooladdr_pl, newpa);
2117                                 error = EAFNOSUPPORT;
2118                                 break;
2119                         }
2120 #endif /* INET */
2121 #ifndef INET6
2122                         if (pca->af == AF_INET6) {
2123                                 pool_put(&pf_pooladdr_pl, newpa);
2124                                 error = EAFNOSUPPORT;
2125                                 break;
2126                         }
2127 #endif /* INET6 */
2128                         if (newpa->ifname[0]) {
2129                                 newpa->kif = pfi_attach_rule(newpa->ifname);
2130                                 if (newpa->kif == NULL) {
2131                                         pool_put(&pf_pooladdr_pl, newpa);
2132                                         error = EINVAL;
2133                                         break;
2134                                 }
2135                         } else
2136                                 newpa->kif = NULL;
2137                         if (pfi_dynaddr_setup(&newpa->addr, pca->af) ||
2138                             pf_tbladdr_setup(ruleset, &newpa->addr)) {
2139                                 pfi_dynaddr_remove(&newpa->addr);
2140                                 pfi_detach_rule(newpa->kif);
2141                                 pool_put(&pf_pooladdr_pl, newpa);
2142                                 error = EINVAL;
2143                                 break;
2144                         }
2145                 }
2146
2147                 crit_enter();
2148
2149                 if (pca->action == PF_CHANGE_ADD_HEAD)
2150                         oldpa = TAILQ_FIRST(&pool->list);
2151                 else if (pca->action == PF_CHANGE_ADD_TAIL)
2152                         oldpa = TAILQ_LAST(&pool->list, pf_palist);
2153                 else {
2154                         int     i = 0;
2155
2156                         oldpa = TAILQ_FIRST(&pool->list);
2157                         while ((oldpa != NULL) && (i < pca->nr)) {
2158                                 oldpa = TAILQ_NEXT(oldpa, entries);
2159                                 i++;
2160                         }
2161                         if (oldpa == NULL) {
2162                                 error = EINVAL;
2163                                 crit_exit();
2164                                 break;
2165                         }
2166                 }
2167
2168                 if (pca->action == PF_CHANGE_REMOVE) {
2169                         TAILQ_REMOVE(&pool->list, oldpa, entries);
2170                         pfi_dynaddr_remove(&oldpa->addr);
2171                         pf_tbladdr_remove(&oldpa->addr);
2172                         pfi_detach_rule(oldpa->kif);
2173                         pool_put(&pf_pooladdr_pl, oldpa);
2174                 } else {
2175                         if (oldpa == NULL)
2176                                 TAILQ_INSERT_TAIL(&pool->list, newpa, entries);
2177                         else if (pca->action == PF_CHANGE_ADD_HEAD ||
2178                             pca->action == PF_CHANGE_ADD_BEFORE)
2179                                 TAILQ_INSERT_BEFORE(oldpa, newpa, entries);
2180                         else
2181                                 TAILQ_INSERT_AFTER(&pool->list, oldpa,
2182                                     newpa, entries);
2183                 }
2184
2185                 pool->cur = TAILQ_FIRST(&pool->list);
2186                 PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr,
2187                     pca->af);
2188                 crit_exit();
2189                 break;
2190         }
2191
2192         case DIOCGETANCHORS: {
2193                 struct pfioc_anchor     *pa = (struct pfioc_anchor *)addr;
2194                 struct pf_anchor        *anchor;
2195
2196                 pa->nr = 0;
2197                 TAILQ_FOREACH(anchor, &pf_anchors, entries)
2198                         pa->nr++;
2199                 break;
2200         }
2201
2202         case DIOCGETANCHOR: {
2203                 struct pfioc_anchor     *pa = (struct pfioc_anchor *)addr;
2204                 struct pf_anchor        *anchor;
2205                 u_int32_t                nr = 0;
2206
2207                 anchor = TAILQ_FIRST(&pf_anchors);
2208                 while (anchor != NULL && nr < pa->nr) {
2209                         anchor = TAILQ_NEXT(anchor, entries);
2210                         nr++;
2211                 }
2212                 if (anchor == NULL)
2213                         error = EBUSY;
2214                 else
2215                         bcopy(anchor->name, pa->name, sizeof(pa->name));
2216                 break;
2217         }
2218
2219         case DIOCGETRULESETS: {
2220                 struct pfioc_ruleset    *pr = (struct pfioc_ruleset *)addr;
2221                 struct pf_anchor        *anchor;
2222                 struct pf_ruleset       *ruleset;
2223
2224                 pr->anchor[PF_ANCHOR_NAME_SIZE-1] = 0;
2225                 if ((anchor = pf_find_anchor(pr->anchor)) == NULL) {
2226                         error = EINVAL;
2227                         break;
2228                 }
2229                 pr->nr = 0;
2230                 TAILQ_FOREACH(ruleset, &anchor->rulesets, entries)
2231                         pr->nr++;
2232                 break;
2233         }
2234
2235         case DIOCGETRULESET: {
2236                 struct pfioc_ruleset    *pr = (struct pfioc_ruleset *)addr;
2237                 struct pf_anchor        *anchor;
2238                 struct pf_ruleset       *ruleset;
2239                 u_int32_t                nr = 0;
2240
2241                 if ((anchor = pf_find_anchor(pr->anchor)) == NULL) {
2242                         error = EINVAL;
2243                         break;
2244                 }
2245                 ruleset = TAILQ_FIRST(&anchor->rulesets);
2246                 while (ruleset != NULL && nr < pr->nr) {
2247                         ruleset = TAILQ_NEXT(ruleset, entries);
2248                         nr++;
2249                 }
2250                 if (ruleset == NULL)
2251                         error = EBUSY;
2252                 else
2253                         bcopy(ruleset->name, pr->name, sizeof(pr->name));
2254                 break;
2255         }
2256
2257         case DIOCRCLRTABLES: {
2258                 struct pfioc_table *io = (struct pfioc_table *)addr;
2259
2260                 if (io->pfrio_esize != 0) {
2261                         error = ENODEV;
2262                         break;
2263                 }
2264                 error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
2265                     io->pfrio_flags | PFR_FLAG_USERIOCTL);
2266                 break;
2267         }
2268
2269         case DIOCRADDTABLES: {
2270                 struct pfioc_table *io = (struct pfioc_table *)addr;
2271
2272                 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2273                         error = ENODEV;
2274                         break;
2275                 }
2276                 error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size,
2277                     &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2278                 break;
2279         }
2280
2281         case DIOCRDELTABLES: {
2282                 struct pfioc_table *io = (struct pfioc_table *)addr;
2283
2284                 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2285                         error = ENODEV;
2286                         break;
2287                 }
2288                 error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size,
2289                     &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2290                 break;
2291         }
2292
2293         case DIOCRGETTABLES: {
2294                 struct pfioc_table *io = (struct pfioc_table *)addr;
2295
2296                 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2297                         error = ENODEV;
2298                         break;
2299                 }
2300                 error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer,
2301                     &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2302                 break;
2303         }
2304
2305         case DIOCRGETTSTATS: {
2306                 struct pfioc_table *io = (struct pfioc_table *)addr;
2307
2308                 if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
2309                         error = ENODEV;
2310                         break;
2311                 }
2312                 error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer,
2313                     &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2314                 break;
2315         }
2316
2317         case DIOCRCLRTSTATS: {
2318                 struct pfioc_table *io = (struct pfioc_table *)addr;
2319
2320                 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2321                         error = ENODEV;
2322                         break;
2323                 }
2324                 error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size,
2325                     &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2326                 break;
2327         }
2328
2329         case DIOCRSETTFLAGS: {
2330                 struct pfioc_table *io = (struct pfioc_table *)addr;
2331
2332                 if (io->pfrio_esize != sizeof(struct pfr_table)) {
2333                         error = ENODEV;
2334                         break;
2335                 }
2336                 error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size,
2337                     io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
2338                     &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2339                 break;
2340         }
2341
2342         case DIOCRCLRADDRS: {
2343                 struct pfioc_table *io = (struct pfioc_table *)addr;
2344
2345                 if (io->pfrio_esize != 0) {
2346                         error = ENODEV;
2347                         break;
2348                 }
2349                 error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
2350                     io->pfrio_flags | PFR_FLAG_USERIOCTL);
2351                 break;
2352         }
2353
2354         case DIOCRADDADDRS: {
2355                 struct pfioc_table *io = (struct pfioc_table *)addr;
2356
2357                 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2358                         error = ENODEV;
2359                         break;
2360                 }
2361                 error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer,
2362                     io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
2363                     PFR_FLAG_USERIOCTL);
2364                 break;
2365         }
2366
2367         case DIOCRDELADDRS: {
2368                 struct pfioc_table *io = (struct pfioc_table *)addr;
2369
2370                 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2371                         error = ENODEV;
2372                         break;
2373                 }
2374                 error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer,
2375                     io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
2376                     PFR_FLAG_USERIOCTL);
2377                 break;
2378         }
2379
2380         case DIOCRSETADDRS: {
2381                 struct pfioc_table *io = (struct pfioc_table *)addr;
2382
2383                 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2384                         error = ENODEV;
2385                         break;
2386                 }
2387                 error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer,
2388                     io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
2389                     &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
2390                     PFR_FLAG_USERIOCTL);
2391                 break;
2392         }
2393
2394         case DIOCRGETADDRS: {
2395                 struct pfioc_table *io = (struct pfioc_table *)addr;
2396
2397                 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2398                         error = ENODEV;
2399                         break;
2400                 }
2401                 error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer,
2402                     &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2403                 break;
2404         }
2405
2406         case DIOCRGETASTATS: {
2407                 struct pfioc_table *io = (struct pfioc_table *)addr;
2408
2409                 if (io->pfrio_esize != sizeof(struct pfr_astats)) {
2410                         error = ENODEV;
2411                         break;
2412                 }
2413                 error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer,
2414                     &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2415                 break;
2416         }
2417
2418         case DIOCRCLRASTATS: {
2419                 struct pfioc_table *io = (struct pfioc_table *)addr;
2420
2421                 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2422                         error = ENODEV;
2423                         break;
2424                 }
2425                 error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer,
2426                     io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
2427                     PFR_FLAG_USERIOCTL);
2428                 break;
2429         }
2430
2431         case DIOCRTSTADDRS: {
2432                 struct pfioc_table *io = (struct pfioc_table *)addr;
2433
2434                 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2435                         error = ENODEV;
2436                         break;
2437                 }
2438                 error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer,
2439                     io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
2440                     PFR_FLAG_USERIOCTL);
2441                 break;
2442         }
2443
2444         case DIOCRINABEGIN: {
2445                 struct pfioc_table *io = (struct pfioc_table *)addr;
2446
2447                 if (io->pfrio_esize != 0) {
2448                         error = ENODEV;
2449                         break;
2450                 }
2451                 error = pfr_ina_begin(&io->pfrio_table, &io->pfrio_ticket,
2452                     &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2453                 break;
2454         }
2455
2456         case DIOCRINACOMMIT: {
2457                 struct pfioc_table *io = (struct pfioc_table *)addr;
2458
2459                 if (io->pfrio_esize != 0) {
2460                         error = ENODEV;
2461                         break;
2462                 }
2463                 error = pfr_ina_commit(&io->pfrio_table, io->pfrio_ticket,
2464                     &io->pfrio_nadd, &io->pfrio_nchange, io->pfrio_flags |
2465                     PFR_FLAG_USERIOCTL);
2466                 break;
2467         }
2468
2469         case DIOCRINADEFINE: {
2470                 struct pfioc_table *io = (struct pfioc_table *)addr;
2471
2472                 if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2473                         error = ENODEV;
2474                         break;
2475                 }
2476                 error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer,
2477                     io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
2478                     io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2479                 break;
2480         }
2481
2482         case DIOCOSFPADD: {
2483                 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
2484                 crit_enter();
2485                 error = pf_osfp_add(io);
2486                 crit_exit();
2487                 break;
2488         }
2489
2490         case DIOCOSFPGET: {
2491                 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
2492                 crit_enter();
2493                 error = pf_osfp_get(io);
2494                 crit_exit();
2495                 break;
2496         }
2497
2498         case DIOCXBEGIN: {
2499                 struct pfioc_trans      *io = (struct pfioc_trans *)addr;
2500                 struct pfioc_trans_e     ioe;
2501                 struct pfr_table         table;
2502                 int                      i;
2503
2504                 if (io->esize != sizeof(ioe)) {
2505                         error = ENODEV;
2506                         goto fail;
2507                 }
2508                 for (i = 0; i < io->size; i++) {
2509                         if (copyin(io->array+i, &ioe, sizeof(ioe))) {
2510                                 error = EFAULT;
2511                                 goto fail;
2512                         }
2513                         switch (ioe.rs_num) {
2514 #ifdef ALTQ
2515                         case PF_RULESET_ALTQ:
2516                                 if (ioe.anchor[0] || ioe.ruleset[0]) {
2517                                         error = EINVAL;
2518                                         goto fail;
2519                                 }
2520                                 if ((error = pf_begin_altq(&ioe.ticket)))
2521                                         goto fail;
2522                                 break;
2523 #endif /* ALTQ */
2524                         case PF_RULESET_TABLE:
2525                                 bzero(&table, sizeof(table));
2526                                 strlcpy(table.pfrt_anchor, ioe.anchor,
2527                                     sizeof(table.pfrt_anchor));
2528                                 strlcpy(table.pfrt_ruleset, ioe.ruleset,
2529                                     sizeof(table.pfrt_ruleset));
2530                                 if ((error = pfr_ina_begin(&table,
2531                                     &ioe.ticket, NULL, 0)))
2532                                         goto fail;
2533                                 break;
2534                         default:
2535                                 if ((error = pf_begin_rules(&ioe.ticket,
2536                                     ioe.rs_num, ioe.anchor, ioe.ruleset)))
2537                                         goto fail;
2538                                 break;
2539                         }
2540                         if (copyout(&ioe, io->array+i, sizeof(io->array[i]))) {
2541                                 error = EFAULT;
2542                                 goto fail;
2543                         }
2544                 }
2545                 break;
2546         }
2547
2548         case DIOCXROLLBACK: {
2549                 struct pfioc_trans      *io = (struct pfioc_trans *)addr;
2550                 struct pfioc_trans_e     ioe;
2551                 struct pfr_table         table;
2552                 int                      i;
2553
2554                 if (io->esize != sizeof(ioe)) {
2555                         error = ENODEV;
2556                         goto fail;
2557                 }
2558                 for (i = 0; i < io->size; i++) {
2559                         if (copyin(io->array+i, &ioe, sizeof(ioe))) {
2560                                 error = EFAULT;
2561                                 goto fail;
2562                         }
2563                         switch (ioe.rs_num) {
2564 #ifdef ALTQ
2565                         case PF_RULESET_ALTQ:
2566                                 if (ioe.anchor[0] || ioe.ruleset[0]) {
2567                                         error = EINVAL;
2568                                         goto fail;
2569                                 }
2570                                 if ((error = pf_rollback_altq(ioe.ticket)))
2571                                         goto fail; /* really bad */
2572                                 break;
2573 #endif /* ALTQ */
2574                         case PF_RULESET_TABLE:
2575                                 bzero(&table, sizeof(table));
2576                                 strlcpy(table.pfrt_anchor, ioe.anchor,
2577                                     sizeof(table.pfrt_anchor));
2578                                 strlcpy(table.pfrt_ruleset, ioe.ruleset,
2579                                     sizeof(table.pfrt_ruleset));
2580                                 if ((error = pfr_ina_rollback(&table,
2581                                     ioe.ticket, NULL, 0)))
2582                                         goto fail; /* really bad */
2583                                 break;
2584                         default:
2585                                 if ((error = pf_rollback_rules(ioe.ticket,
2586                                     ioe.rs_num, ioe.anchor, ioe.ruleset)))
2587                                         goto fail; /* really bad */
2588                                 break;
2589                         }
2590                 }
2591                 break;
2592         }
2593
2594         case DIOCXCOMMIT: {
2595                 struct pfioc_trans      *io = (struct pfioc_trans *)addr;
2596                 struct pfioc_trans_e     ioe;
2597                 struct pfr_table         table;
2598                 struct pf_ruleset       *rs;
2599                 int                      i;
2600
2601                 if (io->esize != sizeof(ioe)) {
2602                         error = ENODEV;
2603                         goto fail;
2604                 }
2605                 /* first makes sure everything will succeed */
2606                 for (i = 0; i < io->size; i++) {
2607                         if (copyin(io->array+i, &ioe, sizeof(ioe))) {
2608                                 error = EFAULT;
2609                                 goto fail;
2610                         }
2611                         switch (ioe.rs_num) {
2612 #ifdef ALTQ
2613                         case PF_RULESET_ALTQ:
2614                                 if (ioe.anchor[0] || ioe.ruleset[0]) {
2615                                         error = EINVAL;
2616                                         goto fail;
2617                                 }
2618                                 if (!altqs_inactive_open || ioe.ticket !=
2619                                     ticket_altqs_inactive) {
2620                                         error = EBUSY;
2621                                         goto fail;
2622                                 }
2623                                 break;
2624 #endif /* ALTQ */
2625                         case PF_RULESET_TABLE:
2626                                 rs = pf_find_ruleset(ioe.anchor, ioe.ruleset);
2627                                 if (rs == NULL || !rs->topen || ioe.ticket !=
2628                                      rs->tticket) {
2629                                         error = EBUSY;
2630                                         goto fail;
2631                                 }
2632                                 break;
2633                         default:
2634                                 if (ioe.rs_num < 0 || ioe.rs_num >=
2635                                     PF_RULESET_MAX) {
2636                                         error = EINVAL;
2637                                         goto fail;
2638                                 }
2639                                 rs = pf_find_ruleset(ioe.anchor, ioe.ruleset);
2640                                 if (rs == NULL ||
2641                                     !rs->rules[ioe.rs_num].inactive.open ||
2642                                     rs->rules[ioe.rs_num].inactive.ticket !=
2643                                     ioe.ticket) {
2644                                         error = EBUSY;
2645                                         goto fail;
2646                                 }
2647                                 break;
2648                         }
2649                 }
2650                 /* now do the commit - no errors should happen here */
2651                 for (i = 0; i < io->size; i++) {
2652                         if (copyin(io->array+i, &ioe, sizeof(ioe))) {
2653                                 error = EFAULT;
2654                                 goto fail;
2655                         }
2656                         switch (ioe.rs_num) {
2657 #ifdef ALTQ
2658                         case PF_RULESET_ALTQ:
2659                                 if ((error = pf_commit_altq(ioe.ticket)))
2660                                         goto fail; /* really bad */
2661                                 break;
2662 #endif /* ALTQ */
2663                         case PF_RULESET_TABLE:
2664                                 bzero(&table, sizeof(table));
2665                                 strlcpy(table.pfrt_anchor, ioe.anchor,
2666                                     sizeof(table.pfrt_anchor));
2667                                 strlcpy(table.pfrt_ruleset, ioe.ruleset,
2668                                     sizeof(table.pfrt_ruleset));
2669                                 if ((error = pfr_ina_commit(&table, ioe.ticket,
2670                                     NULL, NULL, 0)))
2671                                         goto fail; /* really bad */
2672                                 break;
2673                         default:
2674                                 if ((error = pf_commit_rules(ioe.ticket,
2675                                     ioe.rs_num, ioe.anchor, ioe.ruleset)))
2676                                         goto fail; /* really bad */
2677                                 break;
2678                         }
2679                 }
2680                 break;
2681         }
2682
2683         case DIOCGETSRCNODES: {
2684                 struct pfioc_src_nodes  *psn = (struct pfioc_src_nodes *)addr;
2685                 struct pf_src_node      *n;
2686                 struct pf_src_node *p, pstore;
2687                 u_int32_t                nr = 0;
2688                 int                      space = psn->psn_len;
2689
2690                 if (space == 0) {
2691                         crit_enter();
2692                         RB_FOREACH(n, pf_src_tree, &tree_src_tracking)
2693                                 nr++;
2694                         crit_exit();
2695                         psn->psn_len = sizeof(struct pf_src_node) * nr;
2696                         return (0);
2697                 }
2698
2699                 crit_enter();
2700                 p = psn->psn_src_nodes;
2701                 RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
2702                         int     secs = time_second;
2703
2704                         if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
2705                                 break;
2706
2707                         bcopy(n, &pstore, sizeof(pstore));
2708                         if (n->rule.ptr != NULL)
2709                                 pstore.rule.nr = n->rule.ptr->nr;
2710                         pstore.creation = secs - pstore.creation;
2711                         if (pstore.expire > secs)
2712                                 pstore.expire -= secs;
2713                         else
2714                                 pstore.expire = 0;
2715                         error = copyout(&pstore, p, sizeof(*p));
2716                         if (error) {
2717                                 crit_exit();
2718                                 goto fail;
2719                         }
2720                         p++;
2721                         nr++;
2722                 }
2723                 psn->psn_len = sizeof(struct pf_src_node) * nr;
2724                 crit_exit();
2725                 break;
2726         }
2727
2728         case DIOCCLRSRCNODES: {
2729                 struct pf_src_node      *n;
2730                 struct pf_state         *state;
2731
2732                 crit_enter();
2733                 RB_FOREACH(state, pf_state_tree_id, &tree_id) {
2734                         state->src_node = NULL;
2735                         state->nat_src_node = NULL;
2736                 }
2737                 RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
2738                         n->expire = 1;
2739                         n->states = 0;
2740                 }
2741                 pf_purge_expired_src_nodes();
2742                 pf_status.src_nodes = 0;
2743                 crit_exit();
2744                 break;
2745         }
2746
2747         case DIOCSETHOSTID: {
2748                 u_int32_t       *hostid = (u_int32_t *)addr;
2749
2750                 if (*hostid == 0) {
2751                         error = EINVAL;
2752                         goto fail;
2753                 }
2754                 pf_status.hostid = *hostid;
2755                 break;
2756         }
2757
2758         case DIOCOSFPFLUSH:
2759                 crit_enter();
2760                 pf_osfp_flush();
2761                 crit_exit();
2762                 break;
2763
2764         case DIOCIGETIFACES: {
2765                 struct pfioc_iface *io = (struct pfioc_iface *)addr;
2766
2767                 if (io->pfiio_esize != sizeof(struct pfi_if)) {
2768                         error = ENODEV;
2769                         break;
2770                 }
2771                 error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer,
2772                     &io->pfiio_size, io->pfiio_flags);
2773                 break;
2774         }
2775
2776         case DIOCICLRISTATS: {
2777                 struct pfioc_iface *io = (struct pfioc_iface *)addr;
2778
2779                 error = pfi_clr_istats(io->pfiio_name, &io->pfiio_nzero,
2780                     io->pfiio_flags);
2781                 break;
2782         }
2783
2784         default:
2785                 error = ENODEV;
2786                 break;
2787         }
2788 fail:
2789         return (error);
2790 }
2791
2792 /*
2793  * XXX - Check for version missmatch!!!
2794  */
2795 static void
2796 pf_clear_states(void)
2797 {
2798         struct pf_state         *state;
2799
2800         RB_FOREACH(state, pf_state_tree_id, &tree_id) {
2801                 state->timeout = PFTM_PURGE;
2802 #if NPFSYNC
2803                 /* don't send out individual delete messages */
2804                 state->sync_flags = PFSTATE_NOSYNC;
2805 #endif
2806         }
2807         pf_purge_expired_states();
2808         pf_status.states = 0;
2809 #if 0 /* NPFSYNC */
2810 /*
2811  * XXX This is called on module unload, we do not want to sync that over? */
2812  */
2813         pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
2814 #endif
2815 }
2816
2817 static int
2818 pf_clear_tables(void)
2819 {
2820         struct pfioc_table io;
2821         int error;
2822
2823         bzero(&io, sizeof(io));
2824
2825         error = pfr_clr_tables(&io.pfrio_table, &io.pfrio_ndel,
2826             io.pfrio_flags);
2827
2828         return (error);
2829 }
2830
2831 static void
2832 pf_clear_srcnodes(void)
2833 {
2834         struct pf_src_node      *n;
2835         struct pf_state         *state;
2836
2837         RB_FOREACH(state, pf_state_tree_id, &tree_id) {
2838                 state->src_node = NULL;
2839                 state->nat_src_node = NULL;
2840         }
2841         RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
2842                 n->expire = 1;
2843                 n->states = 0;
2844         }
2845         pf_purge_expired_src_nodes();
2846         pf_status.src_nodes = 0;
2847 }
2848 /*
2849  * XXX - Check for version missmatch!!!
2850  */
2851
2852 /*
2853  * Duplicate pfctl -Fa operation to get rid of as much as we can.
2854  */
2855 static int
2856 shutdown_pf(void)
2857 {
2858         int error = 0;
2859         u_int32_t t[5];
2860         char nn = '\0';
2861
2862         callout_stop(&pf_expire_to);
2863
2864         pf_status.running = 0;
2865         do {
2866                 if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn,
2867                     &nn)) != 0) {
2868                         DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: SCRUB\n"));
2869                         break;
2870                 }
2871                 if ((error = pf_begin_rules(&t[1], PF_RULESET_FILTER, &nn,
2872                     &nn)) != 0) {
2873                         DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: FILTER\n"));
2874                         break;          /* XXX: rollback? */
2875                 }
2876                 if ((error = pf_begin_rules(&t[2], PF_RULESET_NAT, &nn, &nn))
2877                     != 0) {
2878                         DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: NAT\n"));
2879                         break;          /* XXX: rollback? */
2880                 }
2881                 if ((error = pf_begin_rules(&t[3], PF_RULESET_BINAT, &nn, &nn))
2882                     != 0) {
2883                         DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: BINAT\n"));
2884                         break;          /* XXX: rollback? */
2885                 }
2886                 if ((error = pf_begin_rules(&t[4], PF_RULESET_RDR, &nn, &nn))
2887                     != 0) {
2888                         DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: RDR\n"));
2889                         break;          /* XXX: rollback? */
2890                 }
2891
2892                 /* XXX: these should always succeed here */
2893                 pf_commit_rules(t[0], PF_RULESET_SCRUB, &nn, &nn);
2894                 pf_commit_rules(t[1], PF_RULESET_FILTER, &nn, &nn);
2895                 pf_commit_rules(t[2], PF_RULESET_NAT, &nn, &nn);
2896                 pf_commit_rules(t[3], PF_RULESET_BINAT, &nn, &nn);
2897                 pf_commit_rules(t[4], PF_RULESET_RDR, &nn, &nn);
2898
2899                 if ((error = pf_clear_tables()) != 0)
2900                         break;
2901
2902 #ifdef ALTQ
2903                 if ((error = pf_begin_altq(&t[0])) != 0) {
2904                         DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: ALTQ\n"));
2905                         break;
2906                 }
2907                 pf_commit_altq(t[0]);
2908 #endif
2909
2910                 pf_clear_states();
2911
2912                 pf_clear_srcnodes();
2913
2914                 /* status does not use malloced mem so no need to cleanup */
2915                 /* fingerprints and interfaces have their own cleanup code */
2916         } while(0);
2917
2918         return (error);
2919 }
2920
2921 static int
2922 pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
2923 {
2924         /*
2925          * DragonFly's version of pf uses FreeBSD's native host byte ordering
2926          * for ip_len/ip_off. This is why we don't have to change byte order
2927          * like the FreeBSD-5 version does.
2928          */
2929         int chk;
2930
2931         chk = pf_test(PF_IN, ifp, m);
2932         if (chk && *m) {
2933                 m_freem(*m);
2934                 *m = NULL;
2935         }
2936         return chk;
2937 }
2938
2939 static int
2940 pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
2941 {
2942         /*
2943          * DragonFly's version of pf uses FreeBSD's native host byte ordering
2944          * for ip_len/ip_off. This is why we don't have to change byte order
2945          * like the FreeBSD-5 version does.
2946          */
2947         int chk;
2948
2949         /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
2950         if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
2951                 in_delayed_cksum(*m);
2952                 (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
2953         }
2954         chk = pf_test(PF_OUT, ifp, m);
2955         if (chk && *m) {
2956                 m_freem(*m);
2957                 *m = NULL;
2958         }
2959         return chk;
2960 }
2961
2962 #ifdef INET6
2963 static int
2964 pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
2965 {
2966         /*
2967          * IPv6 is not affected by ip_len/ip_off byte order changes.
2968          */
2969         int chk;
2970
2971         chk = pf_test6(PF_IN, ifp, m);
2972         if (chk && *m) {
2973                 m_freem(*m);
2974                 *m = NULL;
2975         }
2976         return chk;
2977 }
2978
2979 static int
2980 pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)
2981 {
2982         /*
2983          * IPv6 is not affected by ip_len/ip_off byte order changes.
2984          */
2985         int chk;
2986
2987         /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
2988         if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
2989                 in_delayed_cksum(*m);
2990                 (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
2991         }
2992         chk = pf_test6(PF_OUT, ifp, m);
2993         if (chk && *m) {
2994                 m_freem(*m);
2995                 *m = NULL;
2996         }
2997         return chk;
2998 }
2999 #endif /* INET6 */
3000
3001 static int
3002 hook_pf(void)
3003 {
3004         struct pfil_head *pfh_inet;
3005 #ifdef INET6
3006         struct pfil_head *pfh_inet6;
3007 #endif
3008         
3009         if (pf_pfil_hooked)
3010                 return (0); 
3011         
3012         pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
3013         if (pfh_inet == NULL)
3014                 return (ENODEV);
3015         pfil_add_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
3016         pfil_add_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
3017 #ifdef INET6
3018         pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
3019         if (pfh_inet6 == NULL) {
3020                 pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
3021                     pfh_inet);
3022                 pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
3023                     pfh_inet);
3024                 return (ENODEV);
3025         }
3026         pfil_add_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
3027         pfil_add_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
3028 #endif
3029
3030         pf_pfil_hooked = 1;
3031         return (0);
3032 }
3033
3034 static int
3035 dehook_pf(void)
3036 {
3037         struct pfil_head *pfh_inet;
3038 #ifdef INET6
3039         struct pfil_head *pfh_inet6;
3040 #endif
3041
3042         if (pf_pfil_hooked == 0)
3043                 return (0);
3044
3045         pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
3046         if (pfh_inet == NULL)
3047                 return (ENODEV);
3048         pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
3049             pfh_inet);
3050         pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
3051             pfh_inet);
3052 #ifdef INET6
3053         pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
3054         if (pfh_inet6 == NULL)
3055                 return (ENODEV);
3056         pfil_remove_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK,
3057             pfh_inet6);
3058         pfil_remove_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK,
3059             pfh_inet6);
3060 #endif
3061
3062         pf_pfil_hooked = 0;
3063         return (0);
3064 }
3065
3066 static int
3067 pf_load(void)
3068 {
3069         int error;
3070
3071         init_zone_var();
3072         error = dev_ops_add(&pf_ops, 0, 0);
3073         if (error)
3074                 return (error);
3075         pf_dev = make_dev(&pf_ops, 0, 0, 0, 0600, PF_NAME);
3076         error = pfattach();
3077         if (error) {
3078                 dev_ops_remove(&pf_ops, 0, 0);
3079                 return (error);
3080         }
3081         return (0);
3082 }
3083
3084 static int
3085 pf_unload(void)
3086 {
3087         int error;
3088
3089         pf_status.running = 0;
3090         error = dehook_pf();
3091         if (error) {
3092                 /*
3093                  * Should not happen!
3094                  * XXX Due to error code ESRCH, kldunload will show
3095                  * a message like 'No such process'.
3096                  */
3097                 printf("pfil unregisteration fail\n");
3098                 return error;
3099         }
3100         shutdown_pf();
3101         pfi_cleanup();
3102         pf_osfp_flush();
3103         pf_osfp_cleanup();
3104         cleanup_pf_zone();
3105         dev_ops_remove(&pf_ops, 0, 0);
3106         return 0;
3107 }
3108
3109 static int
3110 pf_modevent(module_t mod, int type, void *data)
3111 {
3112         int error = 0;
3113
3114         switch(type) {
3115         case MOD_LOAD:
3116                 error = pf_load();
3117                 break;
3118
3119         case MOD_UNLOAD:
3120                 error = pf_unload();
3121                 break;
3122         default:
3123                 error = EINVAL;
3124                 break;
3125         }
3126         return error;
3127 }
3128
3129 static moduledata_t pf_mod = {
3130         "pf",
3131         pf_modevent,
3132         0
3133 };
3134
3135 DECLARE_MODULE(pf, pf_mod, SI_SUB_PSEUDO, SI_ORDER_FIRST);
3136 MODULE_VERSION(pf, PF_MODVER);