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