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