1 /* $OpenBSD: pf_ioctl.c,v 1.209 2008/06/29 08:42:15 mcbride Exp $ */
2 /*add $OpenBSD: pf_ioctl.c,v 1.212 2009/02/15 20:42:33 mbalmer Exp $ */
5 * Copyright (c) 2010 The DragonFly Project. All rights reserved.
7 * Copyright (c) 2001 Daniel Hartmeier
8 * Copyright (c) 2002,2003 Henning Brauer
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
15 * - Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above
18 * copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided
20 * with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
35 * Effort sponsored in part by the Defense Advanced Research Projects
36 * Agency (DARPA) and Air Force Research Laboratory, Air Force
37 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
42 #include "opt_inet6.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
47 #include <sys/device.h>
49 #include <sys/filio.h>
50 #include <sys/fcntl.h>
51 #include <sys/socket.h>
52 #include <sys/socketvar.h>
53 #include <sys/kernel.h>
54 #include <sys/kthread.h>
57 #include <sys/malloc.h>
58 #include <sys/module.h>
61 #include <sys/thread2.h>
64 #include <net/if_types.h>
65 #include <net/route.h>
67 #include <netinet/in.h>
68 #include <netinet/in_var.h>
69 #include <netinet/in_systm.h>
70 #include <netinet/ip.h>
71 #include <netinet/ip_var.h>
72 #include <netinet/ip_icmp.h>
74 #include <net/pf/pfvar.h>
77 #include <net/pf/if_pflog.h>
78 #include <net/pf/if_pfsync.h>
81 #include <netinet/ip6.h>
82 #include <netinet/in_pcb.h>
86 #include <net/altq/altq.h>
89 #include <machine/limits.h>
92 u_int rt_numfibs
= RT_NUMFIBS
;
95 struct pf_pool
*pf_get_pool(char *, u_int32_t
, u_int8_t
, u_int32_t
,
96 u_int8_t
, u_int8_t
, u_int8_t
);
98 void pf_mv_pool(struct pf_palist
*, struct pf_palist
*);
99 void pf_empty_pool(struct pf_palist
*);
101 int pf_begin_altq(u_int32_t
*);
102 int pf_rollback_altq(u_int32_t
);
103 int pf_commit_altq(u_int32_t
);
104 int pf_enable_altq(struct pf_altq
*);
105 int pf_disable_altq(struct pf_altq
*);
107 int pf_begin_rules(u_int32_t
*, int, const char *);
108 int pf_rollback_rules(u_int32_t
, int, char *);
109 int pf_setup_pfsync_matching(struct pf_ruleset
*);
110 void pf_hash_rule(MD5_CTX
*, struct pf_rule
*);
111 void pf_hash_rule_addr(MD5_CTX
*, struct pf_rule_addr
*);
112 int pf_commit_rules(u_int32_t
, int, char *);
113 int pf_addr_setup(struct pf_ruleset
*,
114 struct pf_addr_wrap
*, sa_family_t
);
115 void pf_addr_copyout(struct pf_addr_wrap
*);
117 struct pf_rule pf_default_rule
;
118 struct lock pf_consistency_lock
;
119 struct lock pf_global_statetbl_lock
;
121 static int pf_altq_running
;
124 #define TAGID_MAX 50000
125 TAILQ_HEAD(pf_tags
, pf_tagname
) pf_tags
= TAILQ_HEAD_INITIALIZER(pf_tags
),
126 pf_qids
= TAILQ_HEAD_INITIALIZER(pf_qids
);
128 #if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
129 #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
131 u_int16_t
tagname2tag(struct pf_tags
*, char *);
132 void tag2tagname(struct pf_tags
*, u_int16_t
, char *);
133 void tag_unref(struct pf_tags
*, u_int16_t
);
134 int pf_rtlabel_add(struct pf_addr_wrap
*);
135 void pf_rtlabel_remove(struct pf_addr_wrap
*);
136 void pf_rtlabel_copyout(struct pf_addr_wrap
*);
138 #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) kprintf x
140 static cdev_t pf_dev
;
142 static MALLOC_DEFINE(M_PFRULEPL
, "pfrulepl", "pf rule pool list");
143 static MALLOC_DEFINE(M_PFALTQPL
, "pfaltqpl", "pf altq pool list");
144 static MALLOC_DEFINE(M_PFPOOLADDRPL
, "pfpooladdrpl", "pf pool address pool list");
145 static MALLOC_DEFINE(M_PFFRENTPL
, "pffrent", "pf frent pool list");
147 MALLOC_DEFINE(M_PF
, "pf", "pf general");
151 * XXX - These are new and need to be checked when moveing to a new version
153 static void pf_clear_states(void);
154 static int pf_clear_tables(void);
155 static void pf_clear_srcnodes(void);
157 * XXX - These are new and need to be checked when moveing to a new version
161 * Wrapper functions for pfil(9) hooks
163 static int pf_check_in(void *arg
, struct mbuf
**m
, struct ifnet
*ifp
,
165 static int pf_check_out(void *arg
, struct mbuf
**m
, struct ifnet
*ifp
,
168 static int pf_check6_in(void *arg
, struct mbuf
**m
, struct ifnet
*ifp
,
170 static int pf_check6_out(void *arg
, struct mbuf
**m
, struct ifnet
*ifp
,
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);
184 static struct dev_ops pf_ops
= { /* XXX convert to port model */
191 static volatile int pf_pfil_hooked
= 0;
192 int pf_end_threads
= 0;
194 int debug_pfugidhack
= 0;
195 SYSCTL_INT(_debug
, OID_AUTO
, pfugidhack
, CTLFLAG_RW
, &debug_pfugidhack
, 0,
196 "Enable/disable pf user/group rules mpsafe hack");
201 u_int32_t
*my_timeout
= pf_default_rule
.timeout
;
204 if (!rn_inithead(&pf_maskhead
, NULL
, 0)) {
205 kprintf("pf mask radix tree create failed\n");
208 kmalloc_create(&pf_state_pl
, "pf state pool list");
209 kmalloc_raise_limit(pf_state_pl
, 0);
210 kmalloc_create(&pf_frent_pl
, "pf fragment pool list");
211 kmalloc_raise_limit(pf_frent_pl
, 0);
212 kmalloc_create(&pf_cent_pl
, "pf cent pool list");
213 kmalloc_raise_limit(pf_cent_pl
, 0);
216 * Allocate pcpu array.
218 * NOTE: The state table also has a global element which we index
219 * at [ncpus], so it needs one extra slot.
221 tree_src_tracking
= kmalloc(sizeof(*tree_src_tracking
) * ncpus
,
222 M_PF
, M_WAITOK
| M_ZERO
);
223 tree_id
= kmalloc(sizeof(*tree_id
) * ncpus
,
224 M_PF
, M_WAITOK
| M_ZERO
);
225 state_list
= kmalloc(sizeof(*state_list
) * ncpus
,
226 M_PF
, M_WAITOK
| M_ZERO
);
227 pf_counters
= kmalloc(sizeof(*pf_counters
) * ncpus
,
228 M_PF
, M_WAITOK
| M_ZERO
);
229 pf_statetbl
= kmalloc(sizeof(*pf_statetbl
) * (ncpus
+ 1),
230 M_PF
, M_WAITOK
| M_ZERO
);
231 purge_cur
= kmalloc(sizeof(*purge_cur
) * ncpus
,
232 M_PF
, M_WAITOK
| M_ZERO
);
236 pf_osfp_initialize();
238 pf_pool_limits
[PF_LIMIT_STATES
].pp
= pf_state_pl
;
239 pf_pool_limits
[PF_LIMIT_STATES
].limit
= PFSTATE_HIWAT
;
240 pf_pool_limits
[PF_LIMIT_FRAGS
].pp
= pf_frent_pl
;
241 pf_pool_limits
[PF_LIMIT_FRAGS
].limit
= PFFRAG_FRENT_HIWAT
;
242 if (ctob(physmem
) <= 100*1024*1024)
243 pf_pool_limits
[PF_LIMIT_TABLE_ENTRIES
].limit
=
244 PFR_KENTRY_HIWAT_SMALL
;
246 for (nn
= 0; nn
< ncpus
; ++nn
) {
247 RB_INIT(&tree_src_tracking
[nn
]);
248 RB_INIT(&tree_id
[nn
]);
250 RB_INIT(&pf_anchors
);
251 pf_init_ruleset(&pf_main_ruleset
);
252 TAILQ_INIT(&pf_altqs
[0]);
253 TAILQ_INIT(&pf_altqs
[1]);
254 TAILQ_INIT(&pf_pabuf
);
255 pf_altqs_active
= &pf_altqs
[0];
256 pf_altqs_inactive
= &pf_altqs
[1];
257 for (nn
= 0; nn
< ncpus
; ++nn
)
258 TAILQ_INIT(&state_list
[nn
]);
260 /* default rule should never be garbage collected */
261 pf_default_rule
.entries
.tqe_prev
= &pf_default_rule
.entries
.tqe_next
;
262 pf_default_rule
.action
= PF_PASS
;
263 pf_default_rule
.nr
= (uint32_t)(-1);
264 pf_default_rule
.rtableid
= -1;
266 /* initialize default timeouts */
267 my_timeout
[PFTM_TCP_FIRST_PACKET
] = 120; /* First TCP packet */
268 my_timeout
[PFTM_TCP_OPENING
] = 30; /* No response yet */
269 my_timeout
[PFTM_TCP_ESTABLISHED
] = 24*60*60; /* Established */
270 my_timeout
[PFTM_TCP_CLOSING
] = 15 * 60; /* Half closed */
271 my_timeout
[PFTM_TCP_FIN_WAIT
] = 45; /* Got both FINs */
272 my_timeout
[PFTM_TCP_CLOSED
] = 90; /* Got a RST */
273 my_timeout
[PFTM_UDP_FIRST_PACKET
] = 60; /* First UDP packet */
274 my_timeout
[PFTM_UDP_SINGLE
] = 30; /* Unidirectional */
275 my_timeout
[PFTM_UDP_MULTIPLE
] = 60; /* Bidirectional */
276 my_timeout
[PFTM_ICMP_FIRST_PACKET
] = 20; /* First ICMP packet */
277 my_timeout
[PFTM_ICMP_ERROR_REPLY
] = 10; /* Got error response */
278 my_timeout
[PFTM_OTHER_FIRST_PACKET
] = 60; /* First packet */
279 my_timeout
[PFTM_OTHER_SINGLE
] = 30; /* Unidirectional */
280 my_timeout
[PFTM_OTHER_MULTIPLE
] = 60; /* Bidirectional */
281 my_timeout
[PFTM_FRAG
] = 30; /* Fragment expire */
282 my_timeout
[PFTM_INTERVAL
] = 10; /* Expire interval */
283 my_timeout
[PFTM_SRC_NODE
] = 0; /* Source Tracking */
284 my_timeout
[PFTM_TS_DIFF
] = 30; /* Allowed TS diff */
285 my_timeout
[PFTM_ADAPTIVE_START
] = PFSTATE_ADAPT_START
;
286 my_timeout
[PFTM_ADAPTIVE_END
] = PFSTATE_ADAPT_END
;
289 bzero(&pf_status
, sizeof(pf_status
));
290 pf_status
.debug
= PF_DEBUG_URGENT
;
291 /* XXX do our best to avoid a conflict */
292 pf_status
.hostid
= karc4random();
294 if (kthread_create(pf_purge_thread
, NULL
, NULL
, "pfpurge"))
295 panic("pfpurge thread");
299 pfopen(struct dev_open_args
*ap
)
301 lwkt_gettoken(&pf_token
);
302 cdev_t dev
= ap
->a_head
.a_dev
;
303 if (minor(dev
) >= 1) {
304 lwkt_reltoken(&pf_token
);
307 lwkt_reltoken(&pf_token
);
312 pfclose(struct dev_close_args
*ap
)
314 lwkt_gettoken(&pf_token
);
315 cdev_t dev
= ap
->a_head
.a_dev
;
316 if (minor(dev
) >= 1) {
317 lwkt_reltoken(&pf_token
);
320 lwkt_reltoken(&pf_token
);
325 pf_get_pool(char *anchor
, u_int32_t ticket
, u_int8_t rule_action
,
326 u_int32_t rule_number
, u_int8_t r_last
, u_int8_t active
,
327 u_int8_t check_ticket
)
329 struct pf_ruleset
*ruleset
;
330 struct pf_rule
*rule
;
333 ruleset
= pf_find_ruleset(anchor
);
336 rs_num
= pf_get_ruleset_number(rule_action
);
337 if (rs_num
>= PF_RULESET_MAX
)
340 if (check_ticket
&& ticket
!=
341 ruleset
->rules
[rs_num
].active
.ticket
)
344 rule
= TAILQ_LAST(ruleset
->rules
[rs_num
].active
.ptr
,
347 rule
= TAILQ_FIRST(ruleset
->rules
[rs_num
].active
.ptr
);
349 if (check_ticket
&& ticket
!=
350 ruleset
->rules
[rs_num
].inactive
.ticket
)
353 rule
= TAILQ_LAST(ruleset
->rules
[rs_num
].inactive
.ptr
,
356 rule
= TAILQ_FIRST(ruleset
->rules
[rs_num
].inactive
.ptr
);
359 while ((rule
!= NULL
) && (rule
->nr
!= rule_number
))
360 rule
= TAILQ_NEXT(rule
, entries
);
365 return (&rule
->rpool
);
369 pf_mv_pool(struct pf_palist
*poola
, struct pf_palist
*poolb
)
371 struct pf_pooladdr
*mv_pool_pa
;
373 while ((mv_pool_pa
= TAILQ_FIRST(poola
)) != NULL
) {
374 TAILQ_REMOVE(poola
, mv_pool_pa
, entries
);
375 TAILQ_INSERT_TAIL(poolb
, mv_pool_pa
, entries
);
380 pf_empty_pool(struct pf_palist
*poola
)
382 struct pf_pooladdr
*empty_pool_pa
;
384 while ((empty_pool_pa
= TAILQ_FIRST(poola
)) != NULL
) {
385 pfi_dynaddr_remove(&empty_pool_pa
->addr
);
386 pf_tbladdr_remove(&empty_pool_pa
->addr
);
387 pfi_kif_unref(empty_pool_pa
->kif
, PFI_KIF_REF_RULE
);
388 TAILQ_REMOVE(poola
, empty_pool_pa
, entries
);
389 kfree(empty_pool_pa
, M_PFPOOLADDRPL
);
394 pf_rm_rule(struct pf_rulequeue
*rulequeue
, struct pf_rule
*rule
)
396 if (rulequeue
!= NULL
) {
397 if (rule
->states_cur
<= 0) {
399 * XXX - we need to remove the table *before* detaching
400 * the rule to make sure the table code does not delete
401 * the anchor under our feet.
403 pf_tbladdr_remove(&rule
->src
.addr
);
404 pf_tbladdr_remove(&rule
->dst
.addr
);
405 if (rule
->overload_tbl
)
406 pfr_detach_table(rule
->overload_tbl
);
408 TAILQ_REMOVE(rulequeue
, rule
, entries
);
409 rule
->entries
.tqe_prev
= NULL
;
413 if (rule
->states_cur
> 0 || rule
->src_nodes
> 0 ||
414 rule
->entries
.tqe_prev
!= NULL
)
416 pf_tag_unref(rule
->tag
);
417 pf_tag_unref(rule
->match_tag
);
419 if (rule
->pqid
!= rule
->qid
)
420 pf_qid_unref(rule
->pqid
);
421 pf_qid_unref(rule
->qid
);
423 pf_rtlabel_remove(&rule
->src
.addr
);
424 pf_rtlabel_remove(&rule
->dst
.addr
);
425 pfi_dynaddr_remove(&rule
->src
.addr
);
426 pfi_dynaddr_remove(&rule
->dst
.addr
);
427 if (rulequeue
== NULL
) {
428 pf_tbladdr_remove(&rule
->src
.addr
);
429 pf_tbladdr_remove(&rule
->dst
.addr
);
430 if (rule
->overload_tbl
)
431 pfr_detach_table(rule
->overload_tbl
);
433 pfi_kif_unref(rule
->kif
, PFI_KIF_REF_RULE
);
434 pf_anchor_remove(rule
);
435 pf_empty_pool(&rule
->rpool
.list
);
436 kfree(rule
, M_PFRULEPL
);
440 tagname2tag(struct pf_tags
*head
, char *tagname
)
442 struct pf_tagname
*tag
, *p
= NULL
;
443 u_int16_t new_tagid
= 1;
445 TAILQ_FOREACH(tag
, head
, entries
)
446 if (strcmp(tagname
, tag
->name
) == 0) {
452 * to avoid fragmentation, we do a linear search from the beginning
453 * and take the first free slot we find. if there is none or the list
454 * is empty, append a new entry at the end.
458 if (!TAILQ_EMPTY(head
))
459 for (p
= TAILQ_FIRST(head
); p
!= NULL
&&
460 p
->tag
== new_tagid
; p
= TAILQ_NEXT(p
, entries
))
461 new_tagid
= p
->tag
+ 1;
463 if (new_tagid
> TAGID_MAX
)
466 /* allocate and fill new struct pf_tagname */
467 tag
= kmalloc(sizeof(*tag
), M_TEMP
, M_WAITOK
);
468 strlcpy(tag
->name
, tagname
, sizeof(tag
->name
));
469 tag
->tag
= new_tagid
;
472 if (p
!= NULL
) /* insert new entry before p */
473 TAILQ_INSERT_BEFORE(p
, tag
, entries
);
474 else /* either list empty or no free slot in between */
475 TAILQ_INSERT_TAIL(head
, tag
, entries
);
481 tag2tagname(struct pf_tags
*head
, u_int16_t tagid
, char *p
)
483 struct pf_tagname
*tag
;
485 TAILQ_FOREACH(tag
, head
, entries
)
486 if (tag
->tag
== tagid
) {
487 strlcpy(p
, tag
->name
, PF_TAG_NAME_SIZE
);
493 tag_unref(struct pf_tags
*head
, u_int16_t tag
)
495 struct pf_tagname
*p
, *next
;
500 for (p
= TAILQ_FIRST(head
); p
!= NULL
; p
= next
) {
501 next
= TAILQ_NEXT(p
, entries
);
504 TAILQ_REMOVE(head
, p
, entries
);
513 pf_tagname2tag(char *tagname
)
515 return (tagname2tag(&pf_tags
, tagname
));
519 pf_tag2tagname(u_int16_t tagid
, char *p
)
521 tag2tagname(&pf_tags
, tagid
, p
);
525 pf_tag_ref(u_int16_t tag
)
527 struct pf_tagname
*t
;
529 TAILQ_FOREACH(t
, &pf_tags
, entries
)
537 pf_tag_unref(u_int16_t tag
)
539 tag_unref(&pf_tags
, tag
);
543 pf_rtlabel_add(struct pf_addr_wrap
*a
)
549 pf_rtlabel_remove(struct pf_addr_wrap
*a
)
554 pf_rtlabel_copyout(struct pf_addr_wrap
*a
)
556 if (a
->type
== PF_ADDR_RTLABEL
&& a
->v
.rtlabel
)
557 strlcpy(a
->v
.rtlabelname
, "?", sizeof(a
->v
.rtlabelname
));
562 pf_qname2qid(char *qname
)
564 return ((u_int32_t
)tagname2tag(&pf_qids
, qname
));
568 pf_qid2qname(u_int32_t qid
, char *p
)
570 tag2tagname(&pf_qids
, (u_int16_t
)qid
, p
);
574 pf_qid_unref(u_int32_t qid
)
576 tag_unref(&pf_qids
, (u_int16_t
)qid
);
580 pf_begin_altq(u_int32_t
*ticket
)
582 struct pf_altq
*altq
;
585 /* Purge the old altq list */
586 while ((altq
= TAILQ_FIRST(pf_altqs_inactive
)) != NULL
) {
587 TAILQ_REMOVE(pf_altqs_inactive
, altq
, entries
);
588 if (altq
->qname
[0] == 0) {
589 /* detach and destroy the discipline */
590 error
= altq_remove(altq
);
592 pf_qid_unref(altq
->qid
);
593 kfree(altq
, M_PFALTQPL
);
597 *ticket
= ++ticket_altqs_inactive
;
598 altqs_inactive_open
= 1;
603 pf_rollback_altq(u_int32_t ticket
)
605 struct pf_altq
*altq
;
608 if (!altqs_inactive_open
|| ticket
!= ticket_altqs_inactive
)
610 /* Purge the old altq list */
611 while ((altq
= TAILQ_FIRST(pf_altqs_inactive
)) != NULL
) {
612 TAILQ_REMOVE(pf_altqs_inactive
, altq
, entries
);
613 if (altq
->qname
[0] == 0) {
614 /* detach and destroy the discipline */
615 error
= altq_remove(altq
);
617 pf_qid_unref(altq
->qid
);
618 kfree(altq
, M_PFALTQPL
);
620 altqs_inactive_open
= 0;
625 pf_commit_altq(u_int32_t ticket
)
627 struct pf_altqqueue
*old_altqs
;
628 struct pf_altq
*altq
;
631 if (!altqs_inactive_open
|| ticket
!= ticket_altqs_inactive
)
634 /* swap altqs, keep the old. */
636 old_altqs
= pf_altqs_active
;
637 pf_altqs_active
= pf_altqs_inactive
;
638 pf_altqs_inactive
= old_altqs
;
639 ticket_altqs_active
= ticket_altqs_inactive
;
641 /* Attach new disciplines */
642 TAILQ_FOREACH(altq
, pf_altqs_active
, entries
) {
643 if (altq
->qname
[0] == 0) {
644 /* attach the discipline */
645 error
= altq_pfattach(altq
);
653 /* Purge the old altq list */
654 while ((altq
= TAILQ_FIRST(pf_altqs_inactive
)) != NULL
) {
655 TAILQ_REMOVE(pf_altqs_inactive
, altq
, entries
);
656 if (altq
->qname
[0] == 0) {
657 /* detach and destroy the discipline */
659 error
= pf_disable_altq(altq
);
660 err
= altq_pfdetach(altq
);
661 if (err
!= 0 && error
== 0)
663 err
= altq_remove(altq
);
664 if (err
!= 0 && error
== 0)
667 pf_qid_unref(altq
->qid
);
668 kfree(altq
, M_PFALTQPL
);
672 altqs_inactive_open
= 0;
677 pf_enable_altq(struct pf_altq
*altq
)
680 struct tb_profile tb
;
685 if ((ifp
= ifunit(altq
->ifname
)) == NULL
) {
690 if (ifp
->if_snd
.altq_type
!= ALTQT_NONE
)
691 error
= altq_enable(&ifp
->if_snd
);
693 /* set tokenbucket regulator */
694 if (error
== 0 && ifp
!= NULL
&& ALTQ_IS_ENABLED(&ifp
->if_snd
)) {
695 tb
.rate
= altq
->ifbandwidth
;
696 tb
.depth
= altq
->tbrsize
;
698 error
= tbr_set(&ifp
->if_snd
, &tb
);
707 pf_disable_altq(struct pf_altq
*altq
)
710 struct tb_profile tb
;
715 if ((ifp
= ifunit(altq
->ifname
)) == NULL
) {
721 * when the discipline is no longer referenced, it was overridden
722 * by a new one. if so, just return.
724 if (altq
->altq_disc
!= ifp
->if_snd
.altq_disc
) {
729 error
= altq_disable(&ifp
->if_snd
);
732 /* clear tokenbucket regulator */
735 error
= tbr_set(&ifp
->if_snd
, &tb
);
745 pf_begin_rules(u_int32_t
*ticket
, int rs_num
, const char *anchor
)
747 struct pf_ruleset
*rs
;
748 struct pf_rule
*rule
;
750 if (rs_num
< 0 || rs_num
>= PF_RULESET_MAX
)
752 rs
= pf_find_or_create_ruleset(anchor
);
755 while ((rule
= TAILQ_FIRST(rs
->rules
[rs_num
].inactive
.ptr
)) != NULL
) {
756 pf_rm_rule(rs
->rules
[rs_num
].inactive
.ptr
, rule
);
757 rs
->rules
[rs_num
].inactive
.rcount
--;
759 *ticket
= ++rs
->rules
[rs_num
].inactive
.ticket
;
760 rs
->rules
[rs_num
].inactive
.open
= 1;
765 pf_rollback_rules(u_int32_t ticket
, int rs_num
, char *anchor
)
767 struct pf_ruleset
*rs
;
768 struct pf_rule
*rule
;
770 if (rs_num
< 0 || rs_num
>= PF_RULESET_MAX
)
772 rs
= pf_find_ruleset(anchor
);
773 if (rs
== NULL
|| !rs
->rules
[rs_num
].inactive
.open
||
774 rs
->rules
[rs_num
].inactive
.ticket
!= ticket
)
776 while ((rule
= TAILQ_FIRST(rs
->rules
[rs_num
].inactive
.ptr
)) != NULL
) {
777 pf_rm_rule(rs
->rules
[rs_num
].inactive
.ptr
, rule
);
778 rs
->rules
[rs_num
].inactive
.rcount
--;
780 rs
->rules
[rs_num
].inactive
.open
= 0;
784 #define PF_MD5_UPD(st, elm) \
785 MD5Update(ctx, (u_int8_t *) &(st)->elm, sizeof((st)->elm))
787 #define PF_MD5_UPD_STR(st, elm) \
788 MD5Update(ctx, (u_int8_t *) (st)->elm, strlen((st)->elm))
790 #define PF_MD5_UPD_HTONL(st, elm, stor) do { \
791 (stor) = htonl((st)->elm); \
792 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int32_t));\
795 #define PF_MD5_UPD_HTONS(st, elm, stor) do { \
796 (stor) = htons((st)->elm); \
797 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int16_t));\
801 pf_hash_rule_addr(MD5_CTX
*ctx
, struct pf_rule_addr
*pfr
)
803 PF_MD5_UPD(pfr
, addr
.type
);
804 switch (pfr
->addr
.type
) {
805 case PF_ADDR_DYNIFTL
:
806 PF_MD5_UPD(pfr
, addr
.v
.ifname
);
807 PF_MD5_UPD(pfr
, addr
.iflags
);
810 PF_MD5_UPD(pfr
, addr
.v
.tblname
);
812 case PF_ADDR_ADDRMASK
:
814 PF_MD5_UPD(pfr
, addr
.v
.a
.addr
.addr32
);
815 PF_MD5_UPD(pfr
, addr
.v
.a
.mask
.addr32
);
817 case PF_ADDR_RTLABEL
:
818 PF_MD5_UPD(pfr
, addr
.v
.rtlabelname
);
822 PF_MD5_UPD(pfr
, port
[0]);
823 PF_MD5_UPD(pfr
, port
[1]);
824 PF_MD5_UPD(pfr
, neg
);
825 PF_MD5_UPD(pfr
, port_op
);
829 pf_hash_rule(MD5_CTX
*ctx
, struct pf_rule
*rule
)
834 pf_hash_rule_addr(ctx
, &rule
->src
);
835 pf_hash_rule_addr(ctx
, &rule
->dst
);
836 PF_MD5_UPD_STR(rule
, label
);
837 PF_MD5_UPD_STR(rule
, ifname
);
838 PF_MD5_UPD_STR(rule
, match_tagname
);
839 PF_MD5_UPD_HTONS(rule
, match_tag
, x
); /* dup? */
840 PF_MD5_UPD_HTONL(rule
, os_fingerprint
, y
);
841 PF_MD5_UPD_HTONL(rule
, prob
, y
);
842 PF_MD5_UPD_HTONL(rule
, uid
.uid
[0], y
);
843 PF_MD5_UPD_HTONL(rule
, uid
.uid
[1], y
);
844 PF_MD5_UPD(rule
, uid
.op
);
845 PF_MD5_UPD_HTONL(rule
, gid
.gid
[0], y
);
846 PF_MD5_UPD_HTONL(rule
, gid
.gid
[1], y
);
847 PF_MD5_UPD(rule
, gid
.op
);
848 PF_MD5_UPD_HTONL(rule
, rule_flag
, y
);
849 PF_MD5_UPD(rule
, action
);
850 PF_MD5_UPD(rule
, direction
);
851 PF_MD5_UPD(rule
, af
);
852 PF_MD5_UPD(rule
, quick
);
853 PF_MD5_UPD(rule
, ifnot
);
854 PF_MD5_UPD(rule
, match_tag_not
);
855 PF_MD5_UPD(rule
, natpass
);
856 PF_MD5_UPD(rule
, keep_state
);
857 PF_MD5_UPD(rule
, proto
);
858 PF_MD5_UPD(rule
, type
);
859 PF_MD5_UPD(rule
, code
);
860 PF_MD5_UPD(rule
, flags
);
861 PF_MD5_UPD(rule
, flagset
);
862 PF_MD5_UPD(rule
, allow_opts
);
863 PF_MD5_UPD(rule
, rt
);
864 PF_MD5_UPD(rule
, tos
);
868 pf_commit_rules(u_int32_t ticket
, int rs_num
, char *anchor
)
870 struct pf_ruleset
*rs
;
871 struct pf_rule
*rule
, **old_array
;
872 struct pf_rulequeue
*old_rules
;
874 u_int32_t old_rcount
;
876 if (rs_num
< 0 || rs_num
>= PF_RULESET_MAX
)
878 rs
= pf_find_ruleset(anchor
);
879 if (rs
== NULL
|| !rs
->rules
[rs_num
].inactive
.open
||
880 ticket
!= rs
->rules
[rs_num
].inactive
.ticket
)
883 /* Calculate checksum for the main ruleset */
884 if (rs
== &pf_main_ruleset
) {
885 error
= pf_setup_pfsync_matching(rs
);
890 /* Swap rules, keep the old. */
892 old_rules
= rs
->rules
[rs_num
].active
.ptr
;
893 old_rcount
= rs
->rules
[rs_num
].active
.rcount
;
894 old_array
= rs
->rules
[rs_num
].active
.ptr_array
;
896 rs
->rules
[rs_num
].active
.ptr
=
897 rs
->rules
[rs_num
].inactive
.ptr
;
898 rs
->rules
[rs_num
].active
.ptr_array
=
899 rs
->rules
[rs_num
].inactive
.ptr_array
;
900 rs
->rules
[rs_num
].active
.rcount
=
901 rs
->rules
[rs_num
].inactive
.rcount
;
902 rs
->rules
[rs_num
].inactive
.ptr
= old_rules
;
903 rs
->rules
[rs_num
].inactive
.ptr_array
= old_array
;
904 rs
->rules
[rs_num
].inactive
.rcount
= old_rcount
;
906 rs
->rules
[rs_num
].active
.ticket
=
907 rs
->rules
[rs_num
].inactive
.ticket
;
908 pf_calc_skip_steps(rs
->rules
[rs_num
].active
.ptr
);
911 /* Purge the old rule list. */
912 while ((rule
= TAILQ_FIRST(old_rules
)) != NULL
)
913 pf_rm_rule(old_rules
, rule
);
914 if (rs
->rules
[rs_num
].inactive
.ptr_array
)
915 kfree(rs
->rules
[rs_num
].inactive
.ptr_array
, M_TEMP
);
916 rs
->rules
[rs_num
].inactive
.ptr_array
= NULL
;
917 rs
->rules
[rs_num
].inactive
.rcount
= 0;
918 rs
->rules
[rs_num
].inactive
.open
= 0;
919 pf_remove_if_empty_ruleset(rs
);
925 pf_setup_pfsync_matching(struct pf_ruleset
*rs
)
928 struct pf_rule
*rule
;
930 u_int8_t digest
[PF_MD5_DIGEST_LENGTH
];
933 for (rs_cnt
= 0; rs_cnt
< PF_RULESET_MAX
; rs_cnt
++) {
934 /* XXX PF_RULESET_SCRUB as well? */
935 if (rs_cnt
== PF_RULESET_SCRUB
)
938 if (rs
->rules
[rs_cnt
].inactive
.ptr_array
)
939 kfree(rs
->rules
[rs_cnt
].inactive
.ptr_array
, M_TEMP
);
940 rs
->rules
[rs_cnt
].inactive
.ptr_array
= NULL
;
942 if (rs
->rules
[rs_cnt
].inactive
.rcount
) {
943 rs
->rules
[rs_cnt
].inactive
.ptr_array
=
944 kmalloc(sizeof(caddr_t
) *
945 rs
->rules
[rs_cnt
].inactive
.rcount
,
949 TAILQ_FOREACH(rule
, rs
->rules
[rs_cnt
].inactive
.ptr
,
951 pf_hash_rule(&ctx
, rule
);
952 (rs
->rules
[rs_cnt
].inactive
.ptr_array
)[rule
->nr
] = rule
;
956 MD5Final(digest
, &ctx
);
957 memcpy(pf_status
.pf_chksum
, digest
, sizeof(pf_status
.pf_chksum
));
962 pf_addr_setup(struct pf_ruleset
*ruleset
, struct pf_addr_wrap
*addr
,
965 if (pfi_dynaddr_setup(addr
, af
) ||
966 pf_tbladdr_setup(ruleset
, addr
))
973 pf_addr_copyout(struct pf_addr_wrap
*addr
)
975 pfi_dynaddr_copyout(addr
);
976 pf_tbladdr_copyout(addr
);
977 pf_rtlabel_copyout(addr
);
981 pfioctl(struct dev_ioctl_args
*ap
)
983 u_long cmd
= ap
->a_cmd
;
984 caddr_t addr
= ap
->a_data
;
985 struct pf_pooladdr
*pa
= NULL
;
986 struct pf_pool
*pool
= NULL
;
989 lwkt_gettoken(&pf_token
);
991 /* XXX keep in sync with switch() below */
992 if (securelevel
> 1) {
999 case DIOCSETSTATUSIF
:
1005 case DIOCGETTIMEOUT
:
1006 case DIOCCLRRULECTRS
:
1011 case DIOCGETRULESETS
:
1012 case DIOCGETRULESET
:
1013 case DIOCRGETTABLES
:
1014 case DIOCRGETTSTATS
:
1015 case DIOCRCLRTSTATS
:
1021 case DIOCRGETASTATS
:
1022 case DIOCRCLRASTATS
:
1025 case DIOCGETSRCNODES
:
1026 case DIOCCLRSRCNODES
:
1027 case DIOCIGETIFACES
:
1032 case DIOCRCLRTABLES
:
1033 case DIOCRADDTABLES
:
1034 case DIOCRDELTABLES
:
1035 case DIOCRSETTFLAGS
:
1036 if (((struct pfioc_table
*)addr
)->pfrio_flags
&
1038 break; /* dummy operation ok */
1039 lwkt_reltoken(&pf_token
);
1042 lwkt_reltoken(&pf_token
);
1047 if (!(ap
->a_fflag
& FWRITE
)) {
1055 case DIOCGETTIMEOUT
:
1060 case DIOCGETRULESETS
:
1061 case DIOCGETRULESET
:
1063 case DIOCRGETTABLES
:
1064 case DIOCRGETTSTATS
:
1066 case DIOCRGETASTATS
:
1069 case DIOCGETSRCNODES
:
1070 case DIOCIGETIFACES
:
1073 case DIOCRCLRTABLES
:
1074 case DIOCRADDTABLES
:
1075 case DIOCRDELTABLES
:
1076 case DIOCRCLRTSTATS
:
1081 case DIOCRSETTFLAGS
:
1082 if (((struct pfioc_table
*)addr
)->pfrio_flags
&
1084 break; /* dummy operation ok */
1085 lwkt_reltoken(&pf_token
);
1088 if (((struct pfioc_rule
*)addr
)->action
==
1090 lwkt_reltoken(&pf_token
);
1095 lwkt_reltoken(&pf_token
);
1102 if (pf_status
.running
)
1107 DPFPRINTF(PF_DEBUG_MISC
,
1108 ("pf: pfil registration fail\n"));
1111 pf_status
.running
= 1;
1112 pf_status
.since
= time_second
;
1113 if (pf_status
.stateid
== 0) {
1114 pf_status
.stateid
= time_second
;
1115 pf_status
.stateid
= pf_status
.stateid
<< 32;
1117 DPFPRINTF(PF_DEBUG_MISC
, ("pf: started\n"));
1122 if (!pf_status
.running
)
1125 pf_status
.running
= 0;
1126 error
= dehook_pf();
1128 pf_status
.running
= 1;
1129 DPFPRINTF(PF_DEBUG_MISC
,
1130 ("pf: pfil unregistration failed\n"));
1132 pf_status
.since
= time_second
;
1133 DPFPRINTF(PF_DEBUG_MISC
, ("pf: stopped\n"));
1138 struct pfioc_rule
*pr
= (struct pfioc_rule
*)addr
;
1139 struct pf_ruleset
*ruleset
;
1140 struct pf_rule
*rule
, *tail
;
1141 struct pf_pooladdr
*pa
;
1144 pr
->anchor
[sizeof(pr
->anchor
) - 1] = 0;
1145 ruleset
= pf_find_ruleset(pr
->anchor
);
1146 if (ruleset
== NULL
) {
1150 rs_num
= pf_get_ruleset_number(pr
->rule
.action
);
1151 if (rs_num
>= PF_RULESET_MAX
) {
1155 if (pr
->rule
.return_icmp
>> 8 > ICMP_MAXTYPE
) {
1159 if (pr
->ticket
!= ruleset
->rules
[rs_num
].inactive
.ticket
) {
1163 if (pr
->pool_ticket
!= ticket_pabuf
) {
1167 rule
= kmalloc(sizeof(struct pf_rule
), M_PFRULEPL
, M_WAITOK
);
1168 bcopy(&pr
->rule
, rule
, sizeof(struct pf_rule
));
1169 rule
->cuid
= ap
->a_cred
->cr_ruid
;
1171 rule
->anchor
= NULL
;
1173 TAILQ_INIT(&rule
->rpool
.list
);
1174 /* initialize refcounting */
1175 rule
->states_cur
= 0;
1176 rule
->src_nodes
= 0;
1177 rule
->entries
.tqe_prev
= NULL
;
1179 if (rule
->af
== AF_INET
) {
1180 kfree(rule
, M_PFRULEPL
);
1181 error
= EAFNOSUPPORT
;
1186 if (rule
->af
== AF_INET6
) {
1187 kfree(rule
, M_PFRULEPL
);
1188 error
= EAFNOSUPPORT
;
1192 tail
= TAILQ_LAST(ruleset
->rules
[rs_num
].inactive
.ptr
,
1195 rule
->nr
= tail
->nr
+ 1;
1198 if (rule
->ifname
[0]) {
1199 rule
->kif
= pfi_kif_get(rule
->ifname
);
1200 if (rule
->kif
== NULL
) {
1201 kfree(rule
, M_PFRULEPL
);
1205 pfi_kif_ref(rule
->kif
, PFI_KIF_REF_RULE
);
1208 if (rule
->rtableid
> 0 && rule
->rtableid
> rt_numfibs
)
1213 if (rule
->qname
[0] != 0) {
1214 if ((rule
->qid
= pf_qname2qid(rule
->qname
)) == 0)
1216 else if (rule
->pqname
[0] != 0) {
1218 pf_qname2qid(rule
->pqname
)) == 0)
1221 rule
->pqid
= rule
->qid
;
1224 if (rule
->tagname
[0])
1225 if ((rule
->tag
= pf_tagname2tag(rule
->tagname
)) == 0)
1227 if (rule
->match_tagname
[0])
1228 if ((rule
->match_tag
=
1229 pf_tagname2tag(rule
->match_tagname
)) == 0)
1231 if (rule
->rt
&& !rule
->direction
)
1236 if (rule
->logif
>= PFLOGIFS_MAX
)
1239 if (pf_rtlabel_add(&rule
->src
.addr
) ||
1240 pf_rtlabel_add(&rule
->dst
.addr
))
1242 if (pf_addr_setup(ruleset
, &rule
->src
.addr
, rule
->af
))
1244 if (pf_addr_setup(ruleset
, &rule
->dst
.addr
, rule
->af
))
1246 if (pf_anchor_setup(rule
, ruleset
, pr
->anchor_call
))
1248 TAILQ_FOREACH(pa
, &pf_pabuf
, entries
)
1249 if (pf_tbladdr_setup(ruleset
, &pa
->addr
))
1252 if (rule
->overload_tblname
[0]) {
1253 if ((rule
->overload_tbl
= pfr_attach_table(ruleset
,
1254 rule
->overload_tblname
)) == NULL
)
1257 rule
->overload_tbl
->pfrkt_flags
|=
1261 pf_mv_pool(&pf_pabuf
, &rule
->rpool
.list
);
1262 if (((((rule
->action
== PF_NAT
) || (rule
->action
== PF_RDR
) ||
1263 (rule
->action
== PF_BINAT
)) && rule
->anchor
== NULL
) ||
1264 (rule
->rt
> PF_FASTROUTE
)) &&
1265 (TAILQ_FIRST(&rule
->rpool
.list
) == NULL
))
1269 pf_rm_rule(NULL
, rule
);
1272 rule
->rpool
.cur
= TAILQ_FIRST(&rule
->rpool
.list
);
1273 rule
->evaluations
= rule
->packets
[0] = rule
->packets
[1] =
1274 rule
->bytes
[0] = rule
->bytes
[1] = 0;
1275 TAILQ_INSERT_TAIL(ruleset
->rules
[rs_num
].inactive
.ptr
,
1277 ruleset
->rules
[rs_num
].inactive
.rcount
++;
1281 case DIOCGETRULES
: {
1282 struct pfioc_rule
*pr
= (struct pfioc_rule
*)addr
;
1283 struct pf_ruleset
*ruleset
;
1284 struct pf_rule
*tail
;
1287 pr
->anchor
[sizeof(pr
->anchor
) - 1] = 0;
1288 ruleset
= pf_find_ruleset(pr
->anchor
);
1289 if (ruleset
== NULL
) {
1293 rs_num
= pf_get_ruleset_number(pr
->rule
.action
);
1294 if (rs_num
>= PF_RULESET_MAX
) {
1298 tail
= TAILQ_LAST(ruleset
->rules
[rs_num
].active
.ptr
,
1301 pr
->nr
= tail
->nr
+ 1;
1304 pr
->ticket
= ruleset
->rules
[rs_num
].active
.ticket
;
1309 struct pfioc_rule
*pr
= (struct pfioc_rule
*)addr
;
1310 struct pf_ruleset
*ruleset
;
1311 struct pf_rule
*rule
;
1314 pr
->anchor
[sizeof(pr
->anchor
) - 1] = 0;
1315 ruleset
= pf_find_ruleset(pr
->anchor
);
1316 if (ruleset
== NULL
) {
1320 rs_num
= pf_get_ruleset_number(pr
->rule
.action
);
1321 if (rs_num
>= PF_RULESET_MAX
) {
1325 if (pr
->ticket
!= ruleset
->rules
[rs_num
].active
.ticket
) {
1329 rule
= TAILQ_FIRST(ruleset
->rules
[rs_num
].active
.ptr
);
1330 while ((rule
!= NULL
) && (rule
->nr
!= pr
->nr
))
1331 rule
= TAILQ_NEXT(rule
, entries
);
1336 bcopy(rule
, &pr
->rule
, sizeof(struct pf_rule
));
1337 if (pf_anchor_copyout(ruleset
, rule
, pr
)) {
1341 pf_addr_copyout(&pr
->rule
.src
.addr
);
1342 pf_addr_copyout(&pr
->rule
.dst
.addr
);
1343 for (i
= 0; i
< PF_SKIP_COUNT
; ++i
)
1344 if (rule
->skip
[i
].ptr
== NULL
)
1345 pr
->rule
.skip
[i
].nr
= (uint32_t)(-1);
1347 pr
->rule
.skip
[i
].nr
=
1348 rule
->skip
[i
].ptr
->nr
;
1350 if (pr
->action
== PF_GET_CLR_CNTR
) {
1351 rule
->evaluations
= 0;
1352 rule
->packets
[0] = rule
->packets
[1] = 0;
1353 rule
->bytes
[0] = rule
->bytes
[1] = 0;
1354 rule
->states_tot
= 0;
1359 case DIOCCHANGERULE
: {
1360 struct pfioc_rule
*pcr
= (struct pfioc_rule
*)addr
;
1361 struct pf_ruleset
*ruleset
;
1362 struct pf_rule
*oldrule
= NULL
, *newrule
= NULL
;
1366 if (!(pcr
->action
== PF_CHANGE_REMOVE
||
1367 pcr
->action
== PF_CHANGE_GET_TICKET
) &&
1368 pcr
->pool_ticket
!= ticket_pabuf
) {
1373 if (pcr
->action
< PF_CHANGE_ADD_HEAD
||
1374 pcr
->action
> PF_CHANGE_GET_TICKET
) {
1378 ruleset
= pf_find_ruleset(pcr
->anchor
);
1379 if (ruleset
== NULL
) {
1383 rs_num
= pf_get_ruleset_number(pcr
->rule
.action
);
1384 if (rs_num
>= PF_RULESET_MAX
) {
1389 if (pcr
->action
== PF_CHANGE_GET_TICKET
) {
1390 pcr
->ticket
= ++ruleset
->rules
[rs_num
].active
.ticket
;
1394 ruleset
->rules
[rs_num
].active
.ticket
) {
1398 if (pcr
->rule
.return_icmp
>> 8 > ICMP_MAXTYPE
) {
1404 if (pcr
->action
!= PF_CHANGE_REMOVE
) {
1405 newrule
= kmalloc(sizeof(struct pf_rule
), M_PFRULEPL
, M_WAITOK
|M_NULLOK
);
1406 if (newrule
== NULL
) {
1410 bcopy(&pcr
->rule
, newrule
, sizeof(struct pf_rule
));
1411 newrule
->cuid
= ap
->a_cred
->cr_ruid
;
1413 TAILQ_INIT(&newrule
->rpool
.list
);
1414 /* initialize refcounting */
1415 newrule
->states_cur
= 0;
1416 newrule
->entries
.tqe_prev
= NULL
;
1418 if (newrule
->af
== AF_INET
) {
1419 kfree(newrule
, M_PFRULEPL
);
1420 error
= EAFNOSUPPORT
;
1425 if (newrule
->af
== AF_INET6
) {
1426 kfree(newrule
, M_PFRULEPL
);
1427 error
= EAFNOSUPPORT
;
1431 if (newrule
->ifname
[0]) {
1432 newrule
->kif
= pfi_kif_get(newrule
->ifname
);
1433 if (newrule
->kif
== NULL
) {
1434 kfree(newrule
, M_PFRULEPL
);
1438 pfi_kif_ref(newrule
->kif
, PFI_KIF_REF_RULE
);
1440 newrule
->kif
= NULL
;
1442 if (newrule
->rtableid
> 0 &&
1443 newrule
->rtableid
> rt_numfibs
)
1448 if (newrule
->qname
[0] != 0) {
1450 pf_qname2qid(newrule
->qname
)) == 0)
1452 else if (newrule
->pqname
[0] != 0) {
1453 if ((newrule
->pqid
=
1454 pf_qname2qid(newrule
->pqname
)) == 0)
1457 newrule
->pqid
= newrule
->qid
;
1460 if (newrule
->tagname
[0])
1462 pf_tagname2tag(newrule
->tagname
)) == 0)
1464 if (newrule
->match_tagname
[0])
1465 if ((newrule
->match_tag
= pf_tagname2tag(
1466 newrule
->match_tagname
)) == 0)
1468 if (newrule
->rt
&& !newrule
->direction
)
1473 if (newrule
->logif
>= PFLOGIFS_MAX
)
1476 if (pf_rtlabel_add(&newrule
->src
.addr
) ||
1477 pf_rtlabel_add(&newrule
->dst
.addr
))
1479 if (pf_addr_setup(ruleset
, &newrule
->src
.addr
, newrule
->af
))
1481 if (pf_addr_setup(ruleset
, &newrule
->dst
.addr
, newrule
->af
))
1483 if (pf_anchor_setup(newrule
, ruleset
, pcr
->anchor_call
))
1485 TAILQ_FOREACH(pa
, &pf_pabuf
, entries
)
1486 if (pf_tbladdr_setup(ruleset
, &pa
->addr
))
1489 if (newrule
->overload_tblname
[0]) {
1490 if ((newrule
->overload_tbl
= pfr_attach_table(
1491 ruleset
, newrule
->overload_tblname
)) ==
1495 newrule
->overload_tbl
->pfrkt_flags
|=
1499 pf_mv_pool(&pf_pabuf
, &newrule
->rpool
.list
);
1500 if (((((newrule
->action
== PF_NAT
) ||
1501 (newrule
->action
== PF_RDR
) ||
1502 (newrule
->action
== PF_BINAT
) ||
1503 (newrule
->rt
> PF_FASTROUTE
)) &&
1504 !newrule
->anchor
)) &&
1505 (TAILQ_FIRST(&newrule
->rpool
.list
) == NULL
))
1509 pf_rm_rule(NULL
, newrule
);
1512 newrule
->rpool
.cur
= TAILQ_FIRST(&newrule
->rpool
.list
);
1513 newrule
->evaluations
= 0;
1514 newrule
->packets
[0] = newrule
->packets
[1] = 0;
1515 newrule
->bytes
[0] = newrule
->bytes
[1] = 0;
1517 pf_empty_pool(&pf_pabuf
);
1519 if (pcr
->action
== PF_CHANGE_ADD_HEAD
)
1520 oldrule
= TAILQ_FIRST(
1521 ruleset
->rules
[rs_num
].active
.ptr
);
1522 else if (pcr
->action
== PF_CHANGE_ADD_TAIL
)
1523 oldrule
= TAILQ_LAST(
1524 ruleset
->rules
[rs_num
].active
.ptr
, pf_rulequeue
);
1526 oldrule
= TAILQ_FIRST(
1527 ruleset
->rules
[rs_num
].active
.ptr
);
1528 while ((oldrule
!= NULL
) && (oldrule
->nr
!= pcr
->nr
))
1529 oldrule
= TAILQ_NEXT(oldrule
, entries
);
1530 if (oldrule
== NULL
) {
1531 if (newrule
!= NULL
)
1532 pf_rm_rule(NULL
, newrule
);
1538 if (pcr
->action
== PF_CHANGE_REMOVE
) {
1539 pf_rm_rule(ruleset
->rules
[rs_num
].active
.ptr
, oldrule
);
1540 ruleset
->rules
[rs_num
].active
.rcount
--;
1542 if (oldrule
== NULL
)
1544 ruleset
->rules
[rs_num
].active
.ptr
,
1546 else if (pcr
->action
== PF_CHANGE_ADD_HEAD
||
1547 pcr
->action
== PF_CHANGE_ADD_BEFORE
)
1548 TAILQ_INSERT_BEFORE(oldrule
, newrule
, entries
);
1551 ruleset
->rules
[rs_num
].active
.ptr
,
1552 oldrule
, newrule
, entries
);
1553 ruleset
->rules
[rs_num
].active
.rcount
++;
1557 TAILQ_FOREACH(oldrule
,
1558 ruleset
->rules
[rs_num
].active
.ptr
, entries
)
1561 ruleset
->rules
[rs_num
].active
.ticket
++;
1563 pf_calc_skip_steps(ruleset
->rules
[rs_num
].active
.ptr
);
1564 pf_remove_if_empty_ruleset(ruleset
);
1569 case DIOCCLRSTATES
: {
1570 struct pf_state
*s
, *nexts
;
1571 struct pfioc_state_kill
*psk
= (struct pfioc_state_kill
*)addr
;
1573 globaldata_t save_gd
= mycpu
;
1576 for (nn
= 0; nn
< ncpus
; ++nn
) {
1577 lwkt_setcpu_self(globaldata_find(nn
));
1578 for (s
= RB_MIN(pf_state_tree_id
, &tree_id
[nn
]);
1580 nexts
= RB_NEXT(pf_state_tree_id
,
1583 if (!psk
->psk_ifname
[0] ||
1584 !strcmp(psk
->psk_ifname
,
1585 s
->kif
->pfik_name
)) {
1587 * don't send out individual
1590 s
->sync_flags
= PFSTATE_NOSYNC
;
1596 lwkt_setcpu_self(save_gd
);
1597 psk
->psk_killed
= killed
;
1598 pfsync_clear_states(pf_status
.hostid
, psk
->psk_ifname
);
1602 case DIOCKILLSTATES
: {
1603 struct pf_state
*s
, *nexts
;
1604 struct pf_state_key
*sk
;
1605 struct pf_addr
*srcaddr
, *dstaddr
;
1606 u_int16_t srcport
, dstport
;
1607 struct pfioc_state_kill
*psk
= (struct pfioc_state_kill
*)addr
;
1609 globaldata_t save_gd
= mycpu
;
1612 if (psk
->psk_pfcmp
.id
) {
1613 if (psk
->psk_pfcmp
.creatorid
== 0)
1614 psk
->psk_pfcmp
.creatorid
= pf_status
.hostid
;
1615 for (nn
= 0; nn
< ncpus
; ++nn
) {
1616 lwkt_setcpu_self(globaldata_find(nn
));
1617 if ((s
= pf_find_state_byid(&psk
->psk_pfcmp
))) {
1618 /* send immediate delete of state */
1619 pfsync_delete_state(s
);
1620 s
->sync_flags
|= PFSTATE_NOSYNC
;
1625 lwkt_setcpu_self(save_gd
);
1629 for (nn
= 0; nn
< ncpus
; ++nn
) {
1630 lwkt_setcpu_self(globaldata_find(nn
));
1631 for (s
= RB_MIN(pf_state_tree_id
, &tree_id
[nn
]);
1633 nexts
= RB_NEXT(pf_state_tree_id
, &tree_id
[nn
], s
);
1634 sk
= s
->key
[PF_SK_WIRE
];
1636 if (s
->direction
== PF_OUT
) {
1637 srcaddr
= &sk
->addr
[1];
1638 dstaddr
= &sk
->addr
[0];
1639 srcport
= sk
->port
[0];
1640 dstport
= sk
->port
[0];
1642 srcaddr
= &sk
->addr
[0];
1643 dstaddr
= &sk
->addr
[1];
1644 srcport
= sk
->port
[0];
1645 dstport
= sk
->port
[0];
1647 if ((!psk
->psk_af
|| sk
->af
== psk
->psk_af
)
1648 && (!psk
->psk_proto
|| psk
->psk_proto
==
1650 PF_MATCHA(psk
->psk_src
.neg
,
1651 &psk
->psk_src
.addr
.v
.a
.addr
,
1652 &psk
->psk_src
.addr
.v
.a
.mask
,
1654 PF_MATCHA(psk
->psk_dst
.neg
,
1655 &psk
->psk_dst
.addr
.v
.a
.addr
,
1656 &psk
->psk_dst
.addr
.v
.a
.mask
,
1658 (psk
->psk_src
.port_op
== 0 ||
1659 pf_match_port(psk
->psk_src
.port_op
,
1660 psk
->psk_src
.port
[0],
1661 psk
->psk_src
.port
[1],
1663 (psk
->psk_dst
.port_op
== 0 ||
1664 pf_match_port(psk
->psk_dst
.port_op
,
1665 psk
->psk_dst
.port
[0],
1666 psk
->psk_dst
.port
[1],
1668 (!psk
->psk_label
[0] ||
1669 (s
->rule
.ptr
->label
[0] &&
1670 !strcmp(psk
->psk_label
, s
->rule
.ptr
->label
))) &&
1671 (!psk
->psk_ifname
[0] ||
1672 !strcmp(psk
->psk_ifname
, s
->kif
->pfik_name
))) {
1673 /* send immediate delete of state */
1674 pfsync_delete_state(s
);
1675 s
->sync_flags
|= PFSTATE_NOSYNC
;
1681 lwkt_setcpu_self(save_gd
);
1682 psk
->psk_killed
= killed
;
1686 case DIOCADDSTATE
: {
1687 struct pfioc_state
*ps
= (struct pfioc_state
*)addr
;
1688 struct pfsync_state
*sp
= &ps
->state
;
1690 if (sp
->timeout
>= PFTM_MAX
&&
1691 sp
->timeout
!= PFTM_UNTIL_PACKET
) {
1695 error
= pfsync_state_import(sp
, PFSYNC_SI_IOCTL
);
1699 case DIOCGETSTATE
: {
1700 struct pfioc_state
*ps
= (struct pfioc_state
*)addr
;
1702 struct pf_state_cmp id_key
;
1703 globaldata_t save_gd
= mycpu
;
1706 bcopy(ps
->state
.id
, &id_key
.id
, sizeof(id_key
.id
));
1707 id_key
.creatorid
= ps
->state
.creatorid
;
1709 for (nn
= 0; nn
< ncpus
; ++nn
) {
1710 lwkt_setcpu_self(globaldata_find(nn
));
1711 s
= pf_find_state_byid(&id_key
);
1716 pfsync_state_export(&ps
->state
, s
);
1720 lwkt_setcpu_self(save_gd
);
1724 case DIOCGETSTATES
: {
1725 struct pfioc_states
*ps
= (struct pfioc_states
*)addr
;
1726 struct pf_state
*state
;
1727 struct pfsync_state
*p
, *pstore
;
1729 globaldata_t save_gd
= mycpu
;
1732 if (ps
->ps_len
== 0) {
1733 nr
= pf_status
.states
;
1734 ps
->ps_len
= sizeof(struct pfsync_state
) * nr
;
1738 pstore
= kmalloc(sizeof(*pstore
), M_TEMP
, M_WAITOK
);
1742 for (nn
= 0; nn
< ncpus
; ++nn
) {
1743 lwkt_setcpu_self(globaldata_find(nn
));
1744 state
= TAILQ_FIRST(&state_list
[nn
]);
1746 if (state
->timeout
!= PFTM_UNLINKED
) {
1747 if ((nr
+ 1) * sizeof(*p
) >
1748 (unsigned)ps
->ps_len
) {
1751 pfsync_state_export(pstore
, state
);
1752 error
= copyout(pstore
, p
, sizeof(*p
));
1754 kfree(pstore
, M_TEMP
);
1755 lwkt_setcpu_self(save_gd
);
1761 state
= TAILQ_NEXT(state
, entry_list
);
1764 lwkt_setcpu_self(save_gd
);
1765 ps
->ps_len
= sizeof(struct pfsync_state
) * nr
;
1766 kfree(pstore
, M_TEMP
);
1770 case DIOCGETSTATUS
: {
1772 * Retrieve pf_status, merge pcpu counters into pf_status
1773 * for user consumption.
1775 struct pf_status
*s
= (struct pf_status
*)addr
;
1776 struct pf_counters
*pfc
;
1780 bcopy(&pf_status
, s
, sizeof(struct pf_status
));
1781 for (n
= 0; n
< ncpus
; ++n
) {
1782 pfc
= &pf_counters
[n
];
1783 for (i
= 0; i
< PFRES_MAX
; ++i
)
1784 s
->counters
[i
] += pfc
->counters
[i
];
1785 for (i
= 0; i
< LCNT_MAX
; ++i
)
1786 s
->lcounters
[i
] += pfc
->lcounters
[i
];
1787 for (i
= 0; i
< FCNT_MAX
; ++i
)
1788 s
->fcounters
[i
] += pfc
->fcounters
[i
];
1789 for (i
= 0; i
< SCNT_MAX
; ++i
)
1790 s
->scounters
[i
] += pfc
->scounters
[i
];
1792 pfi_update_status(s
->ifname
, s
);
1796 case DIOCSETSTATUSIF
: {
1797 struct pfioc_if
*pi
= (struct pfioc_if
*)addr
;
1799 if (pi
->ifname
[0] == 0) {
1800 bzero(pf_status
.ifname
, IFNAMSIZ
);
1803 strlcpy(pf_status
.ifname
, pi
->ifname
, IFNAMSIZ
);
1807 case DIOCCLRSTATUS
: {
1810 bzero(pf_status
.counters
, sizeof(pf_status
.counters
));
1811 bzero(pf_status
.fcounters
, sizeof(pf_status
.fcounters
));
1812 bzero(pf_status
.scounters
, sizeof(pf_status
.scounters
));
1813 for (i
= 0; i
< ncpus
; ++i
) {
1814 bzero(pf_counters
[i
].counters
, sizeof(pf_counters
[0].counters
));
1815 bzero(pf_counters
[i
].fcounters
, sizeof(pf_counters
[0].fcounters
));
1816 bzero(pf_counters
[i
].scounters
, sizeof(pf_counters
[0].scounters
));
1819 pf_status
.since
= time_second
;
1820 if (*pf_status
.ifname
)
1821 pfi_update_status(pf_status
.ifname
, NULL
);
1826 struct pfioc_natlook
*pnl
= (struct pfioc_natlook
*)addr
;
1827 struct pf_state_key
*sk
;
1828 struct pf_state
*state
;
1829 struct pf_state_key_cmp key
;
1830 int m
= 0, direction
= pnl
->direction
;
1832 globaldata_t save_gd
= mycpu
;
1835 /* NATLOOK src and dst are reversed, so reverse sidx/didx */
1836 sidx
= (direction
== PF_IN
) ? 1 : 0;
1837 didx
= (direction
== PF_IN
) ? 0 : 1;
1840 PF_AZERO(&pnl
->saddr
, pnl
->af
) ||
1841 PF_AZERO(&pnl
->daddr
, pnl
->af
) ||
1842 ((pnl
->proto
== IPPROTO_TCP
||
1843 pnl
->proto
== IPPROTO_UDP
) &&
1844 (!pnl
->dport
|| !pnl
->sport
)))
1848 key
.proto
= pnl
->proto
;
1849 PF_ACPY(&key
.addr
[sidx
], &pnl
->saddr
, pnl
->af
);
1850 key
.port
[sidx
] = pnl
->sport
;
1851 PF_ACPY(&key
.addr
[didx
], &pnl
->daddr
, pnl
->af
);
1852 key
.port
[didx
] = pnl
->dport
;
1855 for (nn
= 0; nn
< ncpus
; ++nn
) {
1856 lwkt_setcpu_self(globaldata_find(nn
));
1857 state
= pf_find_state_all(&key
, direction
, &m
);
1864 error
= E2BIG
; /* more than one state */
1865 } else if (state
!= NULL
) {
1866 sk
= state
->key
[sidx
];
1867 PF_ACPY(&pnl
->rsaddr
, &sk
->addr
[sidx
], sk
->af
);
1868 pnl
->rsport
= sk
->port
[sidx
];
1869 PF_ACPY(&pnl
->rdaddr
, &sk
->addr
[didx
], sk
->af
);
1870 pnl
->rdport
= sk
->port
[didx
];
1874 lwkt_setcpu_self(save_gd
);
1879 case DIOCSETTIMEOUT
: {
1880 struct pfioc_tm
*pt
= (struct pfioc_tm
*)addr
;
1883 if (pt
->timeout
< 0 || pt
->timeout
>= PFTM_MAX
||
1888 old
= pf_default_rule
.timeout
[pt
->timeout
];
1889 if (pt
->timeout
== PFTM_INTERVAL
&& pt
->seconds
== 0)
1891 pf_default_rule
.timeout
[pt
->timeout
] = pt
->seconds
;
1892 if (pt
->timeout
== PFTM_INTERVAL
&& pt
->seconds
< old
)
1893 wakeup(pf_purge_thread
);
1898 case DIOCGETTIMEOUT
: {
1899 struct pfioc_tm
*pt
= (struct pfioc_tm
*)addr
;
1901 if (pt
->timeout
< 0 || pt
->timeout
>= PFTM_MAX
) {
1905 pt
->seconds
= pf_default_rule
.timeout
[pt
->timeout
];
1909 case DIOCGETLIMIT
: {
1910 struct pfioc_limit
*pl
= (struct pfioc_limit
*)addr
;
1912 if (pl
->index
< 0 || pl
->index
>= PF_LIMIT_MAX
) {
1916 pl
->limit
= pf_pool_limits
[pl
->index
].limit
;
1920 case DIOCSETLIMIT
: {
1921 struct pfioc_limit
*pl
= (struct pfioc_limit
*)addr
;
1924 if (pl
->index
< 0 || pl
->index
>= PF_LIMIT_MAX
||
1925 pf_pool_limits
[pl
->index
].pp
== NULL
) {
1930 /* XXX Get an API to set limits on the zone/pool */
1931 old_limit
= pf_pool_limits
[pl
->index
].limit
;
1932 pf_pool_limits
[pl
->index
].limit
= pl
->limit
;
1933 pl
->limit
= old_limit
;
1937 case DIOCSETDEBUG
: {
1938 u_int32_t
*level
= (u_int32_t
*)addr
;
1940 pf_status
.debug
= *level
;
1944 case DIOCCLRRULECTRS
: {
1945 /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */
1946 struct pf_ruleset
*ruleset
= &pf_main_ruleset
;
1947 struct pf_rule
*rule
;
1950 ruleset
->rules
[PF_RULESET_FILTER
].active
.ptr
, entries
) {
1951 rule
->evaluations
= 0;
1952 rule
->packets
[0] = rule
->packets
[1] = 0;
1953 rule
->bytes
[0] = rule
->bytes
[1] = 0;
1958 case DIOCGIFSPEED
: {
1959 struct pf_ifspeed
*psp
= (struct pf_ifspeed
*)addr
;
1960 struct pf_ifspeed ps
;
1963 if (psp
->ifname
[0] != 0) {
1964 /* Can we completely trust user-land? */
1965 strlcpy(ps
.ifname
, psp
->ifname
, IFNAMSIZ
);
1967 ifp
= ifunit(ps
.ifname
);
1969 psp
->baudrate
= ifp
->if_baudrate
;
1978 case DIOCSTARTALTQ
: {
1979 struct pf_altq
*altq
;
1981 /* enable all altq interfaces on active list */
1982 TAILQ_FOREACH(altq
, pf_altqs_active
, entries
) {
1983 if (altq
->qname
[0] == 0) {
1984 error
= pf_enable_altq(altq
);
1990 pf_altq_running
= 1;
1991 DPFPRINTF(PF_DEBUG_MISC
, ("altq: started\n"));
1995 case DIOCSTOPALTQ
: {
1996 struct pf_altq
*altq
;
1998 /* disable all altq interfaces on active list */
1999 TAILQ_FOREACH(altq
, pf_altqs_active
, entries
) {
2000 if (altq
->qname
[0] == 0) {
2001 error
= pf_disable_altq(altq
);
2007 pf_altq_running
= 0;
2008 DPFPRINTF(PF_DEBUG_MISC
, ("altq: stopped\n"));
2013 struct pfioc_altq
*pa
= (struct pfioc_altq
*)addr
;
2014 struct pf_altq
*altq
, *a
;
2016 if (pa
->ticket
!= ticket_altqs_inactive
) {
2020 altq
= kmalloc(sizeof(struct pf_altq
), M_PFALTQPL
, M_WAITOK
|M_NULLOK
);
2025 bcopy(&pa
->altq
, altq
, sizeof(struct pf_altq
));
2028 * if this is for a queue, find the discipline and
2029 * copy the necessary fields
2031 if (altq
->qname
[0] != 0) {
2032 if ((altq
->qid
= pf_qname2qid(altq
->qname
)) == 0) {
2034 kfree(altq
, M_PFALTQPL
);
2037 altq
->altq_disc
= NULL
;
2038 TAILQ_FOREACH(a
, pf_altqs_inactive
, entries
) {
2039 if (strncmp(a
->ifname
, altq
->ifname
,
2040 IFNAMSIZ
) == 0 && a
->qname
[0] == 0) {
2041 altq
->altq_disc
= a
->altq_disc
;
2047 error
= altq_add(altq
);
2049 kfree(altq
, M_PFALTQPL
);
2053 TAILQ_INSERT_TAIL(pf_altqs_inactive
, altq
, entries
);
2054 bcopy(altq
, &pa
->altq
, sizeof(struct pf_altq
));
2058 case DIOCGETALTQS
: {
2059 struct pfioc_altq
*pa
= (struct pfioc_altq
*)addr
;
2060 struct pf_altq
*altq
;
2063 TAILQ_FOREACH(altq
, pf_altqs_active
, entries
)
2065 pa
->ticket
= ticket_altqs_active
;
2070 struct pfioc_altq
*pa
= (struct pfioc_altq
*)addr
;
2071 struct pf_altq
*altq
;
2074 if (pa
->ticket
!= ticket_altqs_active
) {
2079 altq
= TAILQ_FIRST(pf_altqs_active
);
2080 while ((altq
!= NULL
) && (nr
< pa
->nr
)) {
2081 altq
= TAILQ_NEXT(altq
, entries
);
2088 bcopy(altq
, &pa
->altq
, sizeof(struct pf_altq
));
2092 case DIOCCHANGEALTQ
:
2093 /* CHANGEALTQ not supported yet! */
2097 case DIOCGETQSTATS
: {
2098 struct pfioc_qstats
*pq
= (struct pfioc_qstats
*)addr
;
2099 struct pf_altq
*altq
;
2103 if (pq
->ticket
!= ticket_altqs_active
) {
2107 nbytes
= pq
->nbytes
;
2109 altq
= TAILQ_FIRST(pf_altqs_active
);
2110 while ((altq
!= NULL
) && (nr
< pq
->nr
)) {
2111 altq
= TAILQ_NEXT(altq
, entries
);
2118 error
= altq_getqstats(altq
, pq
->buf
, &nbytes
);
2120 pq
->scheduler
= altq
->scheduler
;
2121 pq
->nbytes
= nbytes
;
2127 case DIOCBEGINADDRS
: {
2128 struct pfioc_pooladdr
*pp
= (struct pfioc_pooladdr
*)addr
;
2130 pf_empty_pool(&pf_pabuf
);
2131 pp
->ticket
= ++ticket_pabuf
;
2136 struct pfioc_pooladdr
*pp
= (struct pfioc_pooladdr
*)addr
;
2138 if (pp
->ticket
!= ticket_pabuf
) {
2143 if (pp
->af
== AF_INET
) {
2144 error
= EAFNOSUPPORT
;
2149 if (pp
->af
== AF_INET6
) {
2150 error
= EAFNOSUPPORT
;
2154 if (pp
->addr
.addr
.type
!= PF_ADDR_ADDRMASK
&&
2155 pp
->addr
.addr
.type
!= PF_ADDR_DYNIFTL
&&
2156 pp
->addr
.addr
.type
!= PF_ADDR_TABLE
) {
2160 pa
= kmalloc(sizeof(struct pf_altq
), M_PFPOOLADDRPL
, M_WAITOK
|M_NULLOK
);
2165 bcopy(&pp
->addr
, pa
, sizeof(struct pf_pooladdr
));
2166 if (pa
->ifname
[0]) {
2167 pa
->kif
= pfi_kif_get(pa
->ifname
);
2168 if (pa
->kif
== NULL
) {
2169 kfree(ap
, M_PFPOOLADDRPL
);
2173 pfi_kif_ref(pa
->kif
, PFI_KIF_REF_RULE
);
2175 if (pfi_dynaddr_setup(&pa
->addr
, pp
->af
)) {
2176 pfi_dynaddr_remove(&pa
->addr
);
2177 pfi_kif_unref(pa
->kif
, PFI_KIF_REF_RULE
);
2178 kfree(pa
, M_PFPOOLADDRPL
);
2182 TAILQ_INSERT_TAIL(&pf_pabuf
, pa
, entries
);
2186 case DIOCGETADDRS
: {
2187 struct pfioc_pooladdr
*pp
= (struct pfioc_pooladdr
*)addr
;
2190 pool
= pf_get_pool(pp
->anchor
, pp
->ticket
, pp
->r_action
,
2191 pp
->r_num
, 0, 1, 0);
2196 TAILQ_FOREACH(pa
, &pool
->list
, entries
)
2202 struct pfioc_pooladdr
*pp
= (struct pfioc_pooladdr
*)addr
;
2205 pool
= pf_get_pool(pp
->anchor
, pp
->ticket
, pp
->r_action
,
2206 pp
->r_num
, 0, 1, 1);
2211 pa
= TAILQ_FIRST(&pool
->list
);
2212 while ((pa
!= NULL
) && (nr
< pp
->nr
)) {
2213 pa
= TAILQ_NEXT(pa
, entries
);
2220 bcopy(pa
, &pp
->addr
, sizeof(struct pf_pooladdr
));
2221 pf_addr_copyout(&pp
->addr
.addr
);
2225 case DIOCCHANGEADDR
: {
2226 struct pfioc_pooladdr
*pca
= (struct pfioc_pooladdr
*)addr
;
2227 struct pf_pooladdr
*oldpa
= NULL
, *newpa
= NULL
;
2228 struct pf_ruleset
*ruleset
;
2230 if (pca
->action
< PF_CHANGE_ADD_HEAD
||
2231 pca
->action
> PF_CHANGE_REMOVE
) {
2235 if (pca
->addr
.addr
.type
!= PF_ADDR_ADDRMASK
&&
2236 pca
->addr
.addr
.type
!= PF_ADDR_DYNIFTL
&&
2237 pca
->addr
.addr
.type
!= PF_ADDR_TABLE
) {
2242 ruleset
= pf_find_ruleset(pca
->anchor
);
2243 if (ruleset
== NULL
) {
2247 pool
= pf_get_pool(pca
->anchor
, pca
->ticket
, pca
->r_action
,
2248 pca
->r_num
, pca
->r_last
, 1, 1);
2253 if (pca
->action
!= PF_CHANGE_REMOVE
) {
2254 newpa
= kmalloc(sizeof(struct pf_pooladdr
),
2255 M_PFPOOLADDRPL
, M_WAITOK
|M_NULLOK
);
2256 if (newpa
== NULL
) {
2260 bcopy(&pca
->addr
, newpa
, sizeof(struct pf_pooladdr
));
2262 if (pca
->af
== AF_INET
) {
2263 kfree(newpa
, M_PFPOOLADDRPL
);
2264 error
= EAFNOSUPPORT
;
2269 if (pca
->af
== AF_INET6
) {
2270 kfree(newpa
, M_PFPOOLADDRPL
);
2271 error
= EAFNOSUPPORT
;
2275 if (newpa
->ifname
[0]) {
2276 newpa
->kif
= pfi_kif_get(newpa
->ifname
);
2277 if (newpa
->kif
== NULL
) {
2278 kfree(newpa
, M_PFPOOLADDRPL
);
2282 pfi_kif_ref(newpa
->kif
, PFI_KIF_REF_RULE
);
2285 if (pfi_dynaddr_setup(&newpa
->addr
, pca
->af
) ||
2286 pf_tbladdr_setup(ruleset
, &newpa
->addr
)) {
2287 pfi_dynaddr_remove(&newpa
->addr
);
2288 pfi_kif_unref(newpa
->kif
, PFI_KIF_REF_RULE
);
2289 kfree(newpa
, M_PFPOOLADDRPL
);
2295 if (pca
->action
== PF_CHANGE_ADD_HEAD
)
2296 oldpa
= TAILQ_FIRST(&pool
->list
);
2297 else if (pca
->action
== PF_CHANGE_ADD_TAIL
)
2298 oldpa
= TAILQ_LAST(&pool
->list
, pf_palist
);
2302 oldpa
= TAILQ_FIRST(&pool
->list
);
2303 while ((oldpa
!= NULL
) && (i
< pca
->nr
)) {
2304 oldpa
= TAILQ_NEXT(oldpa
, entries
);
2307 if (oldpa
== NULL
) {
2313 if (pca
->action
== PF_CHANGE_REMOVE
) {
2314 TAILQ_REMOVE(&pool
->list
, oldpa
, entries
);
2315 pfi_dynaddr_remove(&oldpa
->addr
);
2316 pf_tbladdr_remove(&oldpa
->addr
);
2317 pfi_kif_unref(oldpa
->kif
, PFI_KIF_REF_RULE
);
2318 kfree(oldpa
, M_PFPOOLADDRPL
);
2321 TAILQ_INSERT_TAIL(&pool
->list
, newpa
, entries
);
2322 else if (pca
->action
== PF_CHANGE_ADD_HEAD
||
2323 pca
->action
== PF_CHANGE_ADD_BEFORE
)
2324 TAILQ_INSERT_BEFORE(oldpa
, newpa
, entries
);
2326 TAILQ_INSERT_AFTER(&pool
->list
, oldpa
,
2330 pool
->cur
= TAILQ_FIRST(&pool
->list
);
2331 PF_ACPY(&pool
->counter
, &pool
->cur
->addr
.v
.a
.addr
,
2336 case DIOCGETRULESETS
: {
2337 struct pfioc_ruleset
*pr
= (struct pfioc_ruleset
*)addr
;
2338 struct pf_ruleset
*ruleset
;
2339 struct pf_anchor
*anchor
;
2341 pr
->path
[sizeof(pr
->path
) - 1] = 0;
2342 if ((ruleset
= pf_find_ruleset(pr
->path
)) == NULL
) {
2347 if (ruleset
->anchor
== NULL
) {
2348 /* XXX kludge for pf_main_ruleset */
2349 RB_FOREACH(anchor
, pf_anchor_global
, &pf_anchors
)
2350 if (anchor
->parent
== NULL
)
2353 RB_FOREACH(anchor
, pf_anchor_node
,
2354 &ruleset
->anchor
->children
)
2360 case DIOCGETRULESET
: {
2361 struct pfioc_ruleset
*pr
= (struct pfioc_ruleset
*)addr
;
2362 struct pf_ruleset
*ruleset
;
2363 struct pf_anchor
*anchor
;
2366 pr
->path
[sizeof(pr
->path
) - 1] = 0;
2367 if ((ruleset
= pf_find_ruleset(pr
->path
)) == NULL
) {
2372 if (ruleset
->anchor
== NULL
) {
2373 /* XXX kludge for pf_main_ruleset */
2374 RB_FOREACH(anchor
, pf_anchor_global
, &pf_anchors
)
2375 if (anchor
->parent
== NULL
&& nr
++ == pr
->nr
) {
2376 strlcpy(pr
->name
, anchor
->name
,
2381 RB_FOREACH(anchor
, pf_anchor_node
,
2382 &ruleset
->anchor
->children
)
2383 if (nr
++ == pr
->nr
) {
2384 strlcpy(pr
->name
, anchor
->name
,
2394 case DIOCRCLRTABLES
: {
2395 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2397 if (io
->pfrio_esize
!= 0) {
2401 error
= pfr_clr_tables(&io
->pfrio_table
, &io
->pfrio_ndel
,
2402 io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2406 case DIOCRADDTABLES
: {
2407 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2409 if (io
->pfrio_esize
!= sizeof(struct pfr_table
)) {
2413 error
= pfr_add_tables(io
->pfrio_buffer
, io
->pfrio_size
,
2414 &io
->pfrio_nadd
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2418 case DIOCRDELTABLES
: {
2419 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2421 if (io
->pfrio_esize
!= sizeof(struct pfr_table
)) {
2425 error
= pfr_del_tables(io
->pfrio_buffer
, io
->pfrio_size
,
2426 &io
->pfrio_ndel
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2430 case DIOCRGETTABLES
: {
2431 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2433 if (io
->pfrio_esize
!= sizeof(struct pfr_table
)) {
2437 error
= pfr_get_tables(&io
->pfrio_table
, io
->pfrio_buffer
,
2438 &io
->pfrio_size
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2442 case DIOCRGETTSTATS
: {
2443 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2445 if (io
->pfrio_esize
!= sizeof(struct pfr_tstats
)) {
2449 error
= pfr_get_tstats(&io
->pfrio_table
, io
->pfrio_buffer
,
2450 &io
->pfrio_size
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2454 case DIOCRCLRTSTATS
: {
2455 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2457 if (io
->pfrio_esize
!= sizeof(struct pfr_table
)) {
2461 error
= pfr_clr_tstats(io
->pfrio_buffer
, io
->pfrio_size
,
2462 &io
->pfrio_nzero
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2466 case DIOCRSETTFLAGS
: {
2467 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2469 if (io
->pfrio_esize
!= sizeof(struct pfr_table
)) {
2473 error
= pfr_set_tflags(io
->pfrio_buffer
, io
->pfrio_size
,
2474 io
->pfrio_setflag
, io
->pfrio_clrflag
, &io
->pfrio_nchange
,
2475 &io
->pfrio_ndel
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2479 case DIOCRCLRADDRS
: {
2480 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2482 if (io
->pfrio_esize
!= 0) {
2486 error
= pfr_clr_addrs(&io
->pfrio_table
, &io
->pfrio_ndel
,
2487 io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2491 case DIOCRADDADDRS
: {
2492 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2494 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2498 error
= pfr_add_addrs(&io
->pfrio_table
, io
->pfrio_buffer
,
2499 io
->pfrio_size
, &io
->pfrio_nadd
, io
->pfrio_flags
|
2500 PFR_FLAG_USERIOCTL
);
2504 case DIOCRDELADDRS
: {
2505 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2507 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2511 error
= pfr_del_addrs(&io
->pfrio_table
, io
->pfrio_buffer
,
2512 io
->pfrio_size
, &io
->pfrio_ndel
, io
->pfrio_flags
|
2513 PFR_FLAG_USERIOCTL
);
2517 case DIOCRSETADDRS
: {
2518 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2520 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2524 error
= pfr_set_addrs(&io
->pfrio_table
, io
->pfrio_buffer
,
2525 io
->pfrio_size
, &io
->pfrio_size2
, &io
->pfrio_nadd
,
2526 &io
->pfrio_ndel
, &io
->pfrio_nchange
, io
->pfrio_flags
|
2527 PFR_FLAG_USERIOCTL
, 0);
2531 case DIOCRGETADDRS
: {
2532 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2534 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2538 error
= pfr_get_addrs(&io
->pfrio_table
, io
->pfrio_buffer
,
2539 &io
->pfrio_size
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2543 case DIOCRGETASTATS
: {
2544 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2546 if (io
->pfrio_esize
!= sizeof(struct pfr_astats
)) {
2550 error
= pfr_get_astats(&io
->pfrio_table
, io
->pfrio_buffer
,
2551 &io
->pfrio_size
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2555 case DIOCRCLRASTATS
: {
2556 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2558 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2562 error
= pfr_clr_astats(&io
->pfrio_table
, io
->pfrio_buffer
,
2563 io
->pfrio_size
, &io
->pfrio_nzero
, io
->pfrio_flags
|
2564 PFR_FLAG_USERIOCTL
);
2568 case DIOCRTSTADDRS
: {
2569 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2571 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2575 error
= pfr_tst_addrs(&io
->pfrio_table
, io
->pfrio_buffer
,
2576 io
->pfrio_size
, &io
->pfrio_nmatch
, io
->pfrio_flags
|
2577 PFR_FLAG_USERIOCTL
);
2581 case DIOCRINADEFINE
: {
2582 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2584 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2588 error
= pfr_ina_define(&io
->pfrio_table
, io
->pfrio_buffer
,
2589 io
->pfrio_size
, &io
->pfrio_nadd
, &io
->pfrio_naddr
,
2590 io
->pfrio_ticket
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2595 struct pf_osfp_ioctl
*io
= (struct pf_osfp_ioctl
*)addr
;
2596 error
= pf_osfp_add(io
);
2601 struct pf_osfp_ioctl
*io
= (struct pf_osfp_ioctl
*)addr
;
2602 error
= pf_osfp_get(io
);
2607 struct pfioc_trans
*io
= (struct pfioc_trans
*)addr
;
2608 struct pfioc_trans_e
*ioe
;
2609 struct pfr_table
*table
;
2612 if (io
->esize
!= sizeof(*ioe
)) {
2616 ioe
= kmalloc(sizeof(*ioe
), M_TEMP
, M_WAITOK
);
2617 table
= kmalloc(sizeof(*table
), M_TEMP
, M_WAITOK
);
2618 for (i
= 0; i
< io
->size
; i
++) {
2619 if (copyin(io
->array
+i
, ioe
, sizeof(*ioe
))) {
2620 kfree(table
, M_TEMP
);
2625 switch (ioe
->rs_num
) {
2627 case PF_RULESET_ALTQ
:
2628 if (ioe
->anchor
[0]) {
2629 kfree(table
, M_TEMP
);
2634 if ((error
= pf_begin_altq(&ioe
->ticket
))) {
2635 kfree(table
, M_TEMP
);
2641 case PF_RULESET_TABLE
:
2642 bzero(table
, sizeof(*table
));
2643 strlcpy(table
->pfrt_anchor
, ioe
->anchor
,
2644 sizeof(table
->pfrt_anchor
));
2645 if ((error
= pfr_ina_begin(table
,
2646 &ioe
->ticket
, NULL
, 0))) {
2647 kfree(table
, M_TEMP
);
2653 if ((error
= pf_begin_rules(&ioe
->ticket
,
2654 ioe
->rs_num
, ioe
->anchor
))) {
2655 kfree(table
, M_TEMP
);
2661 if (copyout(ioe
, io
->array
+i
, sizeof(io
->array
[i
]))) {
2662 kfree(table
, M_TEMP
);
2668 kfree(table
, M_TEMP
);
2673 case DIOCXROLLBACK
: {
2674 struct pfioc_trans
*io
= (struct pfioc_trans
*)addr
;
2675 struct pfioc_trans_e
*ioe
;
2676 struct pfr_table
*table
;
2679 if (io
->esize
!= sizeof(*ioe
)) {
2683 ioe
= kmalloc(sizeof(*ioe
), M_TEMP
, M_WAITOK
);
2684 table
= kmalloc(sizeof(*table
), M_TEMP
, M_WAITOK
);
2685 for (i
= 0; i
< io
->size
; i
++) {
2686 if (copyin(io
->array
+i
, ioe
, sizeof(*ioe
))) {
2687 kfree(table
, M_TEMP
);
2692 switch (ioe
->rs_num
) {
2694 case PF_RULESET_ALTQ
:
2695 if (ioe
->anchor
[0]) {
2696 kfree(table
, M_TEMP
);
2701 if ((error
= pf_rollback_altq(ioe
->ticket
))) {
2702 kfree(table
, M_TEMP
);
2704 goto fail
; /* really bad */
2708 case PF_RULESET_TABLE
:
2709 bzero(table
, sizeof(*table
));
2710 strlcpy(table
->pfrt_anchor
, ioe
->anchor
,
2711 sizeof(table
->pfrt_anchor
));
2712 if ((error
= pfr_ina_rollback(table
,
2713 ioe
->ticket
, NULL
, 0))) {
2714 kfree(table
, M_TEMP
);
2716 goto fail
; /* really bad */
2720 if ((error
= pf_rollback_rules(ioe
->ticket
,
2721 ioe
->rs_num
, ioe
->anchor
))) {
2722 kfree(table
, M_TEMP
);
2724 goto fail
; /* really bad */
2729 kfree(table
, M_TEMP
);
2735 struct pfioc_trans
*io
= (struct pfioc_trans
*)addr
;
2736 struct pfioc_trans_e
*ioe
;
2737 struct pfr_table
*table
;
2738 struct pf_ruleset
*rs
;
2741 if (io
->esize
!= sizeof(*ioe
)) {
2745 ioe
= kmalloc(sizeof(*ioe
), M_TEMP
, M_WAITOK
);
2746 table
= kmalloc(sizeof(*table
), M_TEMP
, M_WAITOK
);
2747 /* first makes sure everything will succeed */
2748 for (i
= 0; i
< io
->size
; i
++) {
2749 if (copyin(io
->array
+i
, ioe
, sizeof(*ioe
))) {
2750 kfree(table
, M_TEMP
);
2755 switch (ioe
->rs_num
) {
2757 case PF_RULESET_ALTQ
:
2758 if (ioe
->anchor
[0]) {
2759 kfree(table
, M_TEMP
);
2764 if (!altqs_inactive_open
|| ioe
->ticket
!=
2765 ticket_altqs_inactive
) {
2766 kfree(table
, M_TEMP
);
2773 case PF_RULESET_TABLE
:
2774 rs
= pf_find_ruleset(ioe
->anchor
);
2775 if (rs
== NULL
|| !rs
->topen
|| ioe
->ticket
!=
2777 kfree(table
, M_TEMP
);
2784 if (ioe
->rs_num
< 0 || ioe
->rs_num
>=
2786 kfree(table
, M_TEMP
);
2791 rs
= pf_find_ruleset(ioe
->anchor
);
2793 !rs
->rules
[ioe
->rs_num
].inactive
.open
||
2794 rs
->rules
[ioe
->rs_num
].inactive
.ticket
!=
2796 kfree(table
, M_TEMP
);
2804 /* now do the commit - no errors should happen here */
2805 for (i
= 0; i
< io
->size
; i
++) {
2806 if (copyin(io
->array
+i
, ioe
, sizeof(*ioe
))) {
2807 kfree(table
, M_TEMP
);
2812 switch (ioe
->rs_num
) {
2814 case PF_RULESET_ALTQ
:
2815 if ((error
= pf_commit_altq(ioe
->ticket
))) {
2816 kfree(table
, M_TEMP
);
2818 goto fail
; /* really bad */
2822 case PF_RULESET_TABLE
:
2823 bzero(table
, sizeof(*table
));
2824 strlcpy(table
->pfrt_anchor
, ioe
->anchor
,
2825 sizeof(table
->pfrt_anchor
));
2826 if ((error
= pfr_ina_commit(table
, ioe
->ticket
,
2828 kfree(table
, M_TEMP
);
2830 goto fail
; /* really bad */
2834 if ((error
= pf_commit_rules(ioe
->ticket
,
2835 ioe
->rs_num
, ioe
->anchor
))) {
2836 kfree(table
, M_TEMP
);
2838 goto fail
; /* really bad */
2843 kfree(table
, M_TEMP
);
2848 case DIOCGETSRCNODES
: {
2849 struct pfioc_src_nodes
*psn
= (struct pfioc_src_nodes
*)addr
;
2850 struct pf_src_node
*n
, *p
, *pstore
;
2852 int space
= psn
->psn_len
;
2856 for (nn
= 0; nn
< ncpus
; ++nn
) {
2857 RB_FOREACH(n
, pf_src_tree
,
2858 &tree_src_tracking
[nn
]) {
2862 psn
->psn_len
= sizeof(struct pf_src_node
) * nr
;
2866 pstore
= kmalloc(sizeof(*pstore
), M_TEMP
, M_WAITOK
);
2868 p
= psn
->psn_src_nodes
;
2871 * WARNING: We are not switching cpus so we cannot call
2872 * nominal pf.c support routines for cpu-specific
2875 for (nn
= 0; nn
< ncpus
; ++nn
) {
2876 RB_FOREACH(n
, pf_src_tree
, &tree_src_tracking
[nn
]) {
2877 int secs
= time_second
, diff
;
2879 if ((nr
+ 1) * sizeof(*p
) >
2880 (unsigned)psn
->psn_len
) {
2884 bcopy(n
, pstore
, sizeof(*pstore
));
2885 if (n
->rule
.ptr
!= NULL
)
2886 pstore
->rule
.nr
= n
->rule
.ptr
->nr
;
2887 pstore
->creation
= secs
- pstore
->creation
;
2888 if (pstore
->expire
> secs
)
2889 pstore
->expire
-= secs
;
2893 /* adjust the connection rate estimate */
2894 diff
= secs
- n
->conn_rate
.last
;
2895 if (diff
>= n
->conn_rate
.seconds
)
2896 pstore
->conn_rate
.count
= 0;
2898 pstore
->conn_rate
.count
-=
2899 n
->conn_rate
.count
* diff
/
2900 n
->conn_rate
.seconds
;
2902 error
= copyout(pstore
, p
, sizeof(*p
));
2904 kfree(pstore
, M_TEMP
);
2911 psn
->psn_len
= sizeof(struct pf_src_node
) * nr
;
2912 kfree(pstore
, M_TEMP
);
2916 case DIOCCLRSRCNODES
: {
2917 struct pf_src_node
*n
;
2918 struct pf_state
*state
;
2919 globaldata_t save_gd
= mycpu
;
2923 * WARNING: We are not switching cpus so we cannot call
2924 * nominal pf.c support routines for cpu-specific
2927 for (nn
= 0; nn
< ncpus
; ++nn
) {
2928 RB_FOREACH(state
, pf_state_tree_id
, &tree_id
[nn
]) {
2929 state
->src_node
= NULL
;
2930 state
->nat_src_node
= NULL
;
2932 RB_FOREACH(n
, pf_src_tree
, &tree_src_tracking
[nn
]) {
2939 * WARNING: Must move to the target cpu for nominal calls
2942 for (nn
= 0; nn
< ncpus
; ++nn
) {
2943 lwkt_setcpu_self(globaldata_find(nn
));
2944 pf_purge_expired_src_nodes(1);
2946 lwkt_setcpu_self(save_gd
);
2947 pf_status
.src_nodes
= 0;
2951 case DIOCKILLSRCNODES
: {
2952 struct pf_src_node
*sn
;
2954 struct pfioc_src_node_kill
*psnk
=
2955 (struct pfioc_src_node_kill
*)addr
;
2957 globaldata_t save_gd
= mycpu
;
2961 * WARNING: We are not switching cpus so we cannot call
2962 * nominal pf.c support routines for cpu-specific
2965 for (nn
= 0; nn
< ncpus
; ++nn
) {
2966 RB_FOREACH(sn
, pf_src_tree
, &tree_src_tracking
[nn
]) {
2967 if (PF_MATCHA(psnk
->psnk_src
.neg
,
2968 &psnk
->psnk_src
.addr
.v
.a
.addr
,
2969 &psnk
->psnk_src
.addr
.v
.a
.mask
,
2970 &sn
->addr
, sn
->af
) &&
2971 PF_MATCHA(psnk
->psnk_dst
.neg
,
2972 &psnk
->psnk_dst
.addr
.v
.a
.addr
,
2973 &psnk
->psnk_dst
.addr
.v
.a
.mask
,
2974 &sn
->raddr
, sn
->af
)) {
2975 /* Handle state to src_node linkage */
2976 if (sn
->states
!= 0) {
2977 RB_FOREACH(s
, pf_state_tree_id
,
2979 if (s
->src_node
== sn
)
2981 if (s
->nat_src_node
== sn
)
2982 s
->nat_src_node
= NULL
;
2992 for (nn
= 0; nn
< ncpus
; ++nn
) {
2993 lwkt_setcpu_self(globaldata_find(nn
));
2994 pf_purge_expired_src_nodes(1);
2996 lwkt_setcpu_self(save_gd
);
2999 psnk
->psnk_killed
= killed
;
3003 case DIOCSETHOSTID
: {
3004 u_int32_t
*hostid
= (u_int32_t
*)addr
;
3007 pf_status
.hostid
= karc4random();
3009 pf_status
.hostid
= *hostid
;
3019 case DIOCIGETIFACES
: {
3020 struct pfioc_iface
*io
= (struct pfioc_iface
*)addr
;
3022 if (io
->pfiio_esize
!= sizeof(struct pfi_kif
)) {
3026 error
= pfi_get_ifaces(io
->pfiio_name
, io
->pfiio_buffer
,
3031 case DIOCSETIFFLAG
: {
3032 struct pfioc_iface
*io
= (struct pfioc_iface
*)addr
;
3034 error
= pfi_set_flags(io
->pfiio_name
, io
->pfiio_flags
);
3038 case DIOCCLRIFFLAG
: {
3039 struct pfioc_iface
*io
= (struct pfioc_iface
*)addr
;
3041 error
= pfi_clear_flags(io
->pfiio_name
, io
->pfiio_flags
);
3050 lwkt_reltoken(&pf_token
);
3055 * XXX - Check for version missmatch!!!
3058 pf_clear_states(void)
3060 struct pf_state
*s
, *nexts
;
3061 globaldata_t save_gd
= mycpu
;
3064 for (nn
= 0; nn
< ncpus
; ++nn
) {
3065 lwkt_setcpu_self(globaldata_find(nn
));
3066 for (s
= RB_MIN(pf_state_tree_id
, &tree_id
[nn
]); s
; s
= nexts
) {
3067 nexts
= RB_NEXT(pf_state_tree_id
, &tree_id
[nn
], s
);
3069 /* don't send out individual delete messages */
3070 s
->sync_flags
= PFSTATE_NOSYNC
;
3075 lwkt_setcpu_self(save_gd
);
3079 * XXX This is called on module unload, we do not want to sync that over? */
3081 pfsync_clear_states(pf_status
.hostid
, psk
->psk_ifname
);
3086 pf_clear_tables(void)
3088 struct pfioc_table io
;
3091 bzero(&io
, sizeof(io
));
3093 error
= pfr_clr_tables(&io
.pfrio_table
, &io
.pfrio_ndel
,
3100 pf_clear_srcnodes(void)
3102 struct pf_src_node
*n
;
3103 struct pf_state
*state
;
3104 globaldata_t save_gd
= mycpu
;
3107 for (nn
= 0; nn
< ncpus
; ++nn
) {
3108 lwkt_setcpu_self(globaldata_find(nn
));
3109 RB_FOREACH(state
, pf_state_tree_id
, &tree_id
[nn
]) {
3110 state
->src_node
= NULL
;
3111 state
->nat_src_node
= NULL
;
3113 RB_FOREACH(n
, pf_src_tree
, &tree_src_tracking
[nn
]) {
3117 pf_purge_expired_src_nodes(0);
3119 lwkt_setcpu_self(save_gd
);
3121 pf_status
.src_nodes
= 0;
3125 * XXX - Check for version missmatch!!!
3129 * Duplicate pfctl -Fa operation to get rid of as much as we can.
3139 pf_status
.running
= 0;
3140 error
= dehook_pf();
3142 pf_status
.running
= 1;
3143 DPFPRINTF(PF_DEBUG_MISC
,
3144 ("pf: pfil unregistration failed\n"));
3148 if ((error
= pf_begin_rules(&t
[0], PF_RULESET_SCRUB
, &nn
)) != 0) {
3149 DPFPRINTF(PF_DEBUG_MISC
, ("shutdown_pf: SCRUB\n"));
3152 if ((error
= pf_begin_rules(&t
[1], PF_RULESET_FILTER
, &nn
)) != 0) {
3153 DPFPRINTF(PF_DEBUG_MISC
, ("shutdown_pf: FILTER\n"));
3154 break; /* XXX: rollback? */
3156 if ((error
= pf_begin_rules(&t
[2], PF_RULESET_NAT
, &nn
)) != 0) {
3157 DPFPRINTF(PF_DEBUG_MISC
, ("shutdown_pf: NAT\n"));
3158 break; /* XXX: rollback? */
3160 if ((error
= pf_begin_rules(&t
[3], PF_RULESET_BINAT
, &nn
))
3162 DPFPRINTF(PF_DEBUG_MISC
, ("shutdown_pf: BINAT\n"));
3163 break; /* XXX: rollback? */
3165 if ((error
= pf_begin_rules(&t
[4], PF_RULESET_RDR
, &nn
))
3167 DPFPRINTF(PF_DEBUG_MISC
, ("shutdown_pf: RDR\n"));
3168 break; /* XXX: rollback? */
3171 /* XXX: these should always succeed here */
3172 pf_commit_rules(t
[0], PF_RULESET_SCRUB
, &nn
);
3173 pf_commit_rules(t
[1], PF_RULESET_FILTER
, &nn
);
3174 pf_commit_rules(t
[2], PF_RULESET_NAT
, &nn
);
3175 pf_commit_rules(t
[3], PF_RULESET_BINAT
, &nn
);
3176 pf_commit_rules(t
[4], PF_RULESET_RDR
, &nn
);
3178 if ((error
= pf_clear_tables()) != 0)
3181 if ((error
= pf_begin_altq(&t
[0])) != 0) {
3182 DPFPRINTF(PF_DEBUG_MISC
, ("shutdown_pf: ALTQ\n"));
3185 pf_commit_altq(t
[0]);
3188 pf_clear_srcnodes();
3190 /* status does not use malloced mem so no need to cleanup */
3191 /* fingerprints and interfaces have their own cleanup code */
3198 pf_check_in(void *arg
, struct mbuf
**m
, struct ifnet
*ifp
, int dir
)
3201 * NOTE: ip_len and ip_off are left in network byte order
3205 lwkt_gettoken_shared(&pf_token
);
3207 chk
= pf_test(PF_IN
, ifp
, m
, NULL
, NULL
);
3212 lwkt_reltoken(&pf_token
);
3217 pf_check_out(void *arg
, struct mbuf
**m
, struct ifnet
*ifp
, int dir
)
3220 * NOTE: ip_len and ip_off are left in network byte order
3224 lwkt_gettoken_shared(&pf_token
);
3226 /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
3227 if ((*m
)->m_pkthdr
.csum_flags
& CSUM_DELAY_DATA
) {
3228 in_delayed_cksum(*m
);
3229 (*m
)->m_pkthdr
.csum_flags
&= ~CSUM_DELAY_DATA
;
3231 chk
= pf_test(PF_OUT
, ifp
, m
, NULL
, NULL
);
3236 lwkt_reltoken(&pf_token
);
3242 pf_check6_in(void *arg
, struct mbuf
**m
, struct ifnet
*ifp
, int dir
)
3246 lwkt_gettoken_shared(&pf_token
);
3248 chk
= pf_test6(PF_IN
, ifp
, m
, NULL
, NULL
);
3253 lwkt_reltoken(&pf_token
);
3258 pf_check6_out(void *arg
, struct mbuf
**m
, struct ifnet
*ifp
, int dir
)
3262 lwkt_gettoken_shared(&pf_token
);
3264 /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
3265 if ((*m
)->m_pkthdr
.csum_flags
& CSUM_DELAY_DATA
) {
3266 in_delayed_cksum(*m
);
3267 (*m
)->m_pkthdr
.csum_flags
&= ~CSUM_DELAY_DATA
;
3269 chk
= pf_test6(PF_OUT
, ifp
, m
, NULL
, NULL
);
3274 lwkt_reltoken(&pf_token
);
3282 struct pfil_head
*pfh_inet
;
3284 struct pfil_head
*pfh_inet6
;
3287 lwkt_gettoken(&pf_token
);
3289 if (pf_pfil_hooked
) {
3290 lwkt_reltoken(&pf_token
);
3294 pfh_inet
= pfil_head_get(PFIL_TYPE_AF
, AF_INET
);
3295 if (pfh_inet
== NULL
) {
3296 lwkt_reltoken(&pf_token
);
3299 pfil_add_hook(pf_check_in
, NULL
, PFIL_IN
, pfh_inet
);
3300 pfil_add_hook(pf_check_out
, NULL
, PFIL_OUT
, pfh_inet
);
3302 pfh_inet6
= pfil_head_get(PFIL_TYPE_AF
, AF_INET6
);
3303 if (pfh_inet6
== NULL
) {
3304 pfil_remove_hook(pf_check_in
, NULL
, PFIL_IN
, pfh_inet
);
3305 pfil_remove_hook(pf_check_out
, NULL
, PFIL_OUT
, pfh_inet
);
3306 lwkt_reltoken(&pf_token
);
3309 pfil_add_hook(pf_check6_in
, NULL
, PFIL_IN
, pfh_inet6
);
3310 pfil_add_hook(pf_check6_out
, NULL
, PFIL_OUT
, pfh_inet6
);
3314 lwkt_reltoken(&pf_token
);
3321 struct pfil_head
*pfh_inet
;
3323 struct pfil_head
*pfh_inet6
;
3326 lwkt_gettoken(&pf_token
);
3328 if (pf_pfil_hooked
== 0) {
3329 lwkt_reltoken(&pf_token
);
3333 pfh_inet
= pfil_head_get(PFIL_TYPE_AF
, AF_INET
);
3334 if (pfh_inet
== NULL
) {
3335 lwkt_reltoken(&pf_token
);
3338 pfil_remove_hook(pf_check_in
, NULL
, PFIL_IN
, pfh_inet
);
3339 pfil_remove_hook(pf_check_out
, NULL
, PFIL_OUT
, pfh_inet
);
3341 pfh_inet6
= pfil_head_get(PFIL_TYPE_AF
, AF_INET6
);
3342 if (pfh_inet6
== NULL
) {
3343 lwkt_reltoken(&pf_token
);
3346 pfil_remove_hook(pf_check6_in
, NULL
, PFIL_IN
, pfh_inet6
);
3347 pfil_remove_hook(pf_check6_out
, NULL
, PFIL_OUT
, pfh_inet6
);
3351 lwkt_reltoken(&pf_token
);
3358 lwkt_gettoken(&pf_token
);
3360 pf_dev
= make_dev(&pf_ops
, 0, UID_ROOT
, GID_WHEEL
, 0600, PF_NAME
);
3362 lockinit(&pf_consistency_lock
, "pfconslck", 0, LK_CANRECURSE
);
3363 lockinit(&pf_global_statetbl_lock
, "pfglstlk", 0, 0);
3364 lwkt_reltoken(&pf_token
);
3372 pf_status
.running
= 0;
3374 lwkt_gettoken(&pf_token
);
3376 error
= dehook_pf();
3379 * Should not happen!
3380 * XXX Due to error code ESRCH, kldunload will show
3381 * a message like 'No such process'.
3383 kprintf("pfil unregistration fail\n");
3384 lwkt_reltoken(&pf_token
);
3387 kprintf("PF shutdown\n");
3390 while (pf_end_threads
< 2) {
3391 wakeup_one(pf_purge_thread
);
3392 tsleep(pf_purge_thread
, 0, "pftmo", hz
/ 10);
3396 dev_ops_remove_all(&pf_ops
);
3397 lockuninit(&pf_consistency_lock
);
3398 lwkt_reltoken(&pf_token
);
3400 pf_normalize_unload();
3401 if (pf_maskhead
!= NULL
) {
3402 rn_flush(pf_maskhead
, rn_freemask
);
3403 rn_freehead(pf_maskhead
);
3406 kmalloc_destroy(&pf_state_pl
);
3407 kmalloc_destroy(&pf_frent_pl
);
3408 kmalloc_destroy(&pf_cent_pl
);
3410 kfree(tree_src_tracking
, M_PF
);
3411 kfree(tree_id
, M_PF
);
3412 kfree(state_list
, M_PF
);
3413 kfree(pf_counters
, M_PF
);
3414 kfree(pf_statetbl
, M_PF
);
3415 kfree(purge_cur
, M_PF
);
3421 pf_modevent(module_t mod
, int type
, void *data __unused
)
3425 lwkt_gettoken(&pf_token
);
3433 error
= pf_unload();
3439 lwkt_reltoken(&pf_token
);
3443 static moduledata_t pf_mod
= {
3449 DECLARE_MODULE(pf
, pf_mod
, SI_SUB_PSEUDO
, SI_ORDER_FIRST
);
3450 MODULE_VERSION(pf
, PF_MODVER
);