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