1 /* $NetBSD: pf_ioctl.c,v 1.36 2009/09/14 10:36:50 degroote Exp $ */
2 /* $OpenBSD: pf_ioctl.c,v 1.182 2007/06/24 11:17:13 mcbride Exp $ */
5 * Copyright (c) 2001 Daniel Hartmeier
6 * Copyright (c) 2002,2003 Henning Brauer
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
33 * Effort sponsored in part by the Defense Advanced Research Projects
34 * Agency (DARPA) and Air Force Research Laboratory, Air Force
35 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: pf_ioctl.c,v 1.36 2009/09/14 10:36:50 degroote Exp $");
44 #include "opt_pfil_hooks.h"
49 #include <sys/param.h>
50 #include <sys/systm.h>
52 #include <sys/filio.h>
53 #include <sys/fcntl.h>
54 #include <sys/socket.h>
55 #include <sys/socketvar.h>
56 #include <sys/kernel.h>
60 #include <sys/malloc.h>
61 #include <sys/kthread.h>
62 #include <sys/rwlock.h>
63 #include <uvm/uvm_extern.h>
67 #include <sys/kauth.h>
68 #endif /* __NetBSD__ */
71 #include <net/if_types.h>
72 #include <net/route.h>
74 #include <netinet/in.h>
75 #include <netinet/in_var.h>
76 #include <netinet/in_systm.h>
77 #include <netinet/ip.h>
78 #include <netinet/ip_var.h>
79 #include <netinet/ip_icmp.h>
82 #include <dev/rndvar.h>
83 #include <crypto/md5.h>
86 #endif /* __NetBSD__ */
87 #include <net/pfvar.h>
90 #include <net/if_pfsync.h>
91 #endif /* NPFSYNC > 0 */
94 #include <net/if_pflog.h>
95 #endif /* NPFLOG > 0 */
98 #include <netinet/ip6.h>
99 #include <netinet/in_pcb.h>
103 #include <altq/altq.h>
108 void pf_thread_create(void *);
109 #endif /* !__NetBSD__ */
110 int pfopen(dev_t
, int, int, struct lwp
*);
111 int pfclose(dev_t
, int, int, struct lwp
*);
112 struct pf_pool
*pf_get_pool(char *, u_int32_t
, u_int8_t
, u_int32_t
,
113 u_int8_t
, u_int8_t
, u_int8_t
);
115 void pf_mv_pool(struct pf_palist
*, struct pf_palist
*);
116 void pf_empty_pool(struct pf_palist
*);
117 int pfioctl(dev_t
, u_long
, void *, int, struct lwp
*);
119 int pf_begin_altq(u_int32_t
*);
120 int pf_rollback_altq(u_int32_t
);
121 int pf_commit_altq(u_int32_t
);
122 int pf_enable_altq(struct pf_altq
*);
123 int pf_disable_altq(struct pf_altq
*);
125 int pf_begin_rules(u_int32_t
*, int, const char *);
126 int pf_rollback_rules(u_int32_t
, int, char *);
127 int pf_setup_pfsync_matching(struct pf_ruleset
*);
128 void pf_hash_rule(MD5_CTX
*, struct pf_rule
*);
129 void pf_hash_rule_addr(MD5_CTX
*, struct pf_rule_addr
*);
130 int pf_commit_rules(u_int32_t
, int, char *);
131 void pf_state_export(struct pfsync_state
*,
132 struct pf_state_key
*, struct pf_state
*);
133 void pf_state_import(struct pfsync_state
*,
134 struct pf_state_key
*, struct pf_state
*);
136 struct pf_rule pf_default_rule
;
138 krwlock_t pf_consistency_lock
;
140 struct rwlock pf_consistency_lock
= RWLOCK_INITIALIZER("pfcnslk");
141 #endif /* __NetBSD__ */
143 static int pf_altq_running
;
146 #define TAGID_MAX 50000
147 TAILQ_HEAD(pf_tags
, pf_tagname
) pf_tags
= TAILQ_HEAD_INITIALIZER(pf_tags
),
148 pf_qids
= TAILQ_HEAD_INITIALIZER(pf_qids
);
150 #if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
151 #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
153 u_int16_t
tagname2tag(struct pf_tags
*, char *);
154 void tag2tagname(struct pf_tags
*, u_int16_t
, char *);
155 void tag_unref(struct pf_tags
*, u_int16_t
);
156 int pf_rtlabel_add(struct pf_addr_wrap
*);
157 void pf_rtlabel_remove(struct pf_addr_wrap
*);
158 void pf_rtlabel_copyout(struct pf_addr_wrap
*);
160 #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
163 const struct cdevsw pf_cdevsw
= {
164 pfopen
, pfclose
, noread
, nowrite
, pfioctl
,
165 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_OTHER
168 static int pfil4_wrapper(void *, struct mbuf
**, struct ifnet
*, int);
170 static int pfil6_wrapper(void *, struct mbuf
**, struct ifnet
*, int);
173 static int pf_pfil_attach(void);
174 static int pf_pfil_detach(void);
176 static int pf_pfil_attached
;
178 static kauth_listener_t pf_listener
;
179 #endif /* __NetBSD__ */
183 pf_listener_cb(kauth_cred_t cred
, kauth_action_t action
, void *cookie
,
184 void *arg0
, void *arg1
, void *arg2
, void *arg3
)
187 enum kauth_network_req req
;
189 result
= KAUTH_RESULT_DEFER
;
190 req
= (enum kauth_network_req
)arg0
;
192 if (action
!= KAUTH_NETWORK_FIREWALL
)
195 /* These must have came from device context. */
196 if ((req
== KAUTH_REQ_NETWORK_FIREWALL_FW
) ||
197 (req
== KAUTH_REQ_NETWORK_FIREWALL_NAT
))
198 result
= KAUTH_RESULT_ALLOW
;
202 #endif /* __NetBSD__ */
207 u_int32_t
*timeout
= pf_default_rule
.timeout
;
210 pool_init(&pf_rule_pl
, sizeof(struct pf_rule
), 0, 0, 0, "pfrulepl",
211 &pool_allocator_nointr
, IPL_NONE
);
212 pool_init(&pf_src_tree_pl
, sizeof(struct pf_src_node
), 0, 0, 0,
213 "pfsrctrpl", NULL
, IPL_SOFTNET
);
214 pool_init(&pf_state_pl
, sizeof(struct pf_state
), 0, 0, 0, "pfstatepl",
216 pool_init(&pf_state_key_pl
, sizeof(struct pf_state_key
), 0, 0, 0,
217 "pfstatekeypl", NULL
, IPL_SOFTNET
);
218 pool_init(&pf_altq_pl
, sizeof(struct pf_altq
), 0, 0, 0, "pfaltqpl",
219 &pool_allocator_nointr
, IPL_NONE
);
220 pool_init(&pf_pooladdr_pl
, sizeof(struct pf_pooladdr
), 0, 0, 0,
221 "pfpooladdrpl", &pool_allocator_nointr
, IPL_NONE
);
223 pool_init(&pf_rule_pl
, sizeof(struct pf_rule
), 0, 0, 0, "pfrulepl",
224 &pool_allocator_nointr
);
225 pool_init(&pf_src_tree_pl
, sizeof(struct pf_src_node
), 0, 0, 0,
227 pool_init(&pf_state_pl
, sizeof(struct pf_state
), 0, 0, 0, "pfstatepl",
229 pool_init(&pf_state_key_pl
, sizeof(struct pf_state_key
), 0, 0, 0,
230 "pfstatekeypl", NULL
);
231 pool_init(&pf_altq_pl
, sizeof(struct pf_altq
), 0, 0, 0, "pfaltqpl",
232 &pool_allocator_nointr
);
233 pool_init(&pf_pooladdr_pl
, sizeof(struct pf_pooladdr
), 0, 0, 0,
234 "pfpooladdrpl", &pool_allocator_nointr
);
235 #endif /* !__NetBSD__ */
239 pf_osfp_initialize();
241 pool_sethardlimit(pf_pool_limits
[PF_LIMIT_STATES
].pp
,
242 pf_pool_limits
[PF_LIMIT_STATES
].limit
, NULL
, 0);
244 if (ctob(physmem
) <= 100*1024*1024)
245 pf_pool_limits
[PF_LIMIT_TABLE_ENTRIES
].limit
=
246 PFR_KENTRY_HIWAT_SMALL
;
248 RB_INIT(&tree_src_tracking
);
249 RB_INIT(&pf_anchors
);
250 pf_init_ruleset(&pf_main_ruleset
);
251 TAILQ_INIT(&pf_altqs
[0]);
252 TAILQ_INIT(&pf_altqs
[1]);
253 TAILQ_INIT(&pf_pabuf
);
254 pf_altqs_active
= &pf_altqs
[0];
255 pf_altqs_inactive
= &pf_altqs
[1];
256 TAILQ_INIT(&state_list
);
259 rw_init(&pf_consistency_lock
);
260 #endif /* __NetBSD__ */
262 /* default rule should never be garbage collected */
263 pf_default_rule
.entries
.tqe_prev
= &pf_default_rule
.entries
.tqe_next
;
264 pf_default_rule
.action
= PF_PASS
;
265 pf_default_rule
.nr
= -1;
266 pf_default_rule
.rtableid
= -1;
268 /* initialize default timeouts */
269 timeout
[PFTM_TCP_FIRST_PACKET
] = PFTM_TCP_FIRST_PACKET_VAL
;
270 timeout
[PFTM_TCP_OPENING
] = PFTM_TCP_OPENING_VAL
;
271 timeout
[PFTM_TCP_ESTABLISHED
] = PFTM_TCP_ESTABLISHED_VAL
;
272 timeout
[PFTM_TCP_CLOSING
] = PFTM_TCP_CLOSING_VAL
;
273 timeout
[PFTM_TCP_FIN_WAIT
] = PFTM_TCP_FIN_WAIT_VAL
;
274 timeout
[PFTM_TCP_CLOSED
] = PFTM_TCP_CLOSED_VAL
;
275 timeout
[PFTM_UDP_FIRST_PACKET
] = PFTM_UDP_FIRST_PACKET_VAL
;
276 timeout
[PFTM_UDP_SINGLE
] = PFTM_UDP_SINGLE_VAL
;
277 timeout
[PFTM_UDP_MULTIPLE
] = PFTM_UDP_MULTIPLE_VAL
;
278 timeout
[PFTM_ICMP_FIRST_PACKET
] = PFTM_ICMP_FIRST_PACKET_VAL
;
279 timeout
[PFTM_ICMP_ERROR_REPLY
] = PFTM_ICMP_ERROR_REPLY_VAL
;
280 timeout
[PFTM_OTHER_FIRST_PACKET
] = PFTM_OTHER_FIRST_PACKET_VAL
;
281 timeout
[PFTM_OTHER_SINGLE
] = PFTM_OTHER_SINGLE_VAL
;
282 timeout
[PFTM_OTHER_MULTIPLE
] = PFTM_OTHER_MULTIPLE_VAL
;
283 timeout
[PFTM_FRAG
] = PFTM_FRAG_VAL
;
284 timeout
[PFTM_INTERVAL
] = PFTM_INTERVAL_VAL
;
285 timeout
[PFTM_SRC_NODE
] = PFTM_SRC_NODE_VAL
;
286 timeout
[PFTM_TS_DIFF
] = PFTM_TS_DIFF_VAL
;
287 timeout
[PFTM_ADAPTIVE_START
] = PFSTATE_ADAPT_START
;
288 timeout
[PFTM_ADAPTIVE_END
] = PFSTATE_ADAPT_END
;
291 bzero(&pf_status
, sizeof(pf_status
));
292 pf_status
.debug
= PF_DEBUG_URGENT
;
294 /* XXX do our best to avoid a conflict */
295 pf_status
.hostid
= arc4random();
297 /* require process context to purge states, so perform in a thread */
299 if (kthread_create(PRI_NONE
, 0, NULL
, pf_purge_thread
, NULL
, NULL
,
301 panic("pfpurge thread");
303 kthread_create_deferred(pf_thread_create
, NULL
);
304 #endif /* !__NetBSD__ */
307 pf_listener
= kauth_listen_scope(KAUTH_SCOPE_NETWORK
,
308 pf_listener_cb
, NULL
);
309 #endif /* __NetBSD__ */
314 pf_thread_create(void *v
)
316 if (kthread_create(pf_purge_thread
, NULL
, NULL
, "pfpurge"))
317 panic("pfpurge thread");
319 #endif /* !__NetBSD__ */
322 pfopen(dev_t dev
, int flags
, int fmt
, struct lwp
*l
)
330 pfclose(dev_t dev
, int flags
, int fmt
, struct lwp
*l
)
338 pf_get_pool(char *anchor
, u_int32_t ticket
, u_int8_t rule_action
,
339 u_int32_t rule_number
, u_int8_t r_last
, u_int8_t active
,
340 u_int8_t check_ticket
)
342 struct pf_ruleset
*ruleset
;
343 struct pf_rule
*rule
;
346 ruleset
= pf_find_ruleset(anchor
);
349 rs_num
= pf_get_ruleset_number(rule_action
);
350 if (rs_num
>= PF_RULESET_MAX
)
353 if (check_ticket
&& ticket
!=
354 ruleset
->rules
[rs_num
].active
.ticket
)
357 rule
= TAILQ_LAST(ruleset
->rules
[rs_num
].active
.ptr
,
360 rule
= TAILQ_FIRST(ruleset
->rules
[rs_num
].active
.ptr
);
362 if (check_ticket
&& ticket
!=
363 ruleset
->rules
[rs_num
].inactive
.ticket
)
366 rule
= TAILQ_LAST(ruleset
->rules
[rs_num
].inactive
.ptr
,
369 rule
= TAILQ_FIRST(ruleset
->rules
[rs_num
].inactive
.ptr
);
372 while ((rule
!= NULL
) && (rule
->nr
!= rule_number
))
373 rule
= TAILQ_NEXT(rule
, entries
);
378 return (&rule
->rpool
);
382 pf_mv_pool(struct pf_palist
*poola
, struct pf_palist
*poolb
)
384 struct pf_pooladdr
*mv_pool_pa
;
386 while ((mv_pool_pa
= TAILQ_FIRST(poola
)) != NULL
) {
387 TAILQ_REMOVE(poola
, mv_pool_pa
, entries
);
388 TAILQ_INSERT_TAIL(poolb
, mv_pool_pa
, entries
);
393 pf_empty_pool(struct pf_palist
*poola
)
395 struct pf_pooladdr
*empty_pool_pa
;
397 while ((empty_pool_pa
= TAILQ_FIRST(poola
)) != NULL
) {
398 pfi_dynaddr_remove(&empty_pool_pa
->addr
);
399 pf_tbladdr_remove(&empty_pool_pa
->addr
);
400 pfi_kif_unref(empty_pool_pa
->kif
, PFI_KIF_REF_RULE
);
401 TAILQ_REMOVE(poola
, empty_pool_pa
, entries
);
402 pool_put(&pf_pooladdr_pl
, empty_pool_pa
);
407 pf_rm_rule(struct pf_rulequeue
*rulequeue
, struct pf_rule
*rule
)
409 if (rulequeue
!= NULL
) {
410 if (rule
->states
<= 0) {
412 * XXX - we need to remove the table *before* detaching
413 * the rule to make sure the table code does not delete
414 * the anchor under our feet.
416 pf_tbladdr_remove(&rule
->src
.addr
);
417 pf_tbladdr_remove(&rule
->dst
.addr
);
418 if (rule
->overload_tbl
)
419 pfr_detach_table(rule
->overload_tbl
);
421 TAILQ_REMOVE(rulequeue
, rule
, entries
);
422 rule
->entries
.tqe_prev
= NULL
;
426 if (rule
->states
> 0 || rule
->src_nodes
> 0 ||
427 rule
->entries
.tqe_prev
!= NULL
)
429 pf_tag_unref(rule
->tag
);
430 pf_tag_unref(rule
->match_tag
);
432 if (rule
->pqid
!= rule
->qid
)
433 pf_qid_unref(rule
->pqid
);
434 pf_qid_unref(rule
->qid
);
436 pf_rtlabel_remove(&rule
->src
.addr
);
437 pf_rtlabel_remove(&rule
->dst
.addr
);
438 pfi_dynaddr_remove(&rule
->src
.addr
);
439 pfi_dynaddr_remove(&rule
->dst
.addr
);
440 if (rulequeue
== NULL
) {
441 pf_tbladdr_remove(&rule
->src
.addr
);
442 pf_tbladdr_remove(&rule
->dst
.addr
);
443 if (rule
->overload_tbl
)
444 pfr_detach_table(rule
->overload_tbl
);
446 pfi_kif_unref(rule
->kif
, PFI_KIF_REF_RULE
);
447 pf_anchor_remove(rule
);
448 pf_empty_pool(&rule
->rpool
.list
);
449 pool_put(&pf_rule_pl
, rule
);
453 tagname2tag(struct pf_tags
*head
, char *tagname
)
455 struct pf_tagname
*tag
, *p
= NULL
;
456 u_int16_t new_tagid
= 1;
458 TAILQ_FOREACH(tag
, head
, entries
)
459 if (strcmp(tagname
, tag
->name
) == 0) {
465 * to avoid fragmentation, we do a linear search from the beginning
466 * and take the first free slot we find. if there is none or the list
467 * is empty, append a new entry at the end.
471 if (!TAILQ_EMPTY(head
))
472 for (p
= TAILQ_FIRST(head
); p
!= NULL
&&
473 p
->tag
== new_tagid
; p
= TAILQ_NEXT(p
, entries
))
474 new_tagid
= p
->tag
+ 1;
476 if (new_tagid
> TAGID_MAX
)
479 /* allocate and fill new struct pf_tagname */
480 tag
= (struct pf_tagname
*)malloc(sizeof(struct pf_tagname
),
484 bzero(tag
, sizeof(struct pf_tagname
));
485 strlcpy(tag
->name
, tagname
, sizeof(tag
->name
));
486 tag
->tag
= new_tagid
;
489 if (p
!= NULL
) /* insert new entry before p */
490 TAILQ_INSERT_BEFORE(p
, tag
, entries
);
491 else /* either list empty or no free slot in between */
492 TAILQ_INSERT_TAIL(head
, tag
, entries
);
498 tag2tagname(struct pf_tags
*head
, u_int16_t tagid
, char *p
)
500 struct pf_tagname
*tag
;
502 TAILQ_FOREACH(tag
, head
, entries
)
503 if (tag
->tag
== tagid
) {
504 strlcpy(p
, tag
->name
, PF_TAG_NAME_SIZE
);
510 tag_unref(struct pf_tags
*head
, u_int16_t tag
)
512 struct pf_tagname
*p
, *next
;
517 for (p
= TAILQ_FIRST(head
); p
!= NULL
; p
= next
) {
518 next
= TAILQ_NEXT(p
, entries
);
521 TAILQ_REMOVE(head
, p
, entries
);
530 pf_tagname2tag(char *tagname
)
532 return (tagname2tag(&pf_tags
, tagname
));
536 pf_tag2tagname(u_int16_t tagid
, char *p
)
538 tag2tagname(&pf_tags
, tagid
, p
);
542 pf_tag_ref(u_int16_t tag
)
544 struct pf_tagname
*t
;
546 TAILQ_FOREACH(t
, &pf_tags
, entries
)
554 pf_tag_unref(u_int16_t tag
)
556 tag_unref(&pf_tags
, tag
);
560 pf_rtlabel_add(struct pf_addr_wrap
*a
)
563 if (a
->type
== PF_ADDR_RTLABEL
&&
564 (a
->v
.rtlabel
= rtlabel_name2id(a
->v
.rtlabelname
)) == 0)
566 #endif /* !__NetBSD__ */
571 pf_rtlabel_remove(struct pf_addr_wrap
*a
)
574 if (a
->type
== PF_ADDR_RTLABEL
)
575 rtlabel_unref(a
->v
.rtlabel
);
576 #endif /* !__NetBSD__ */
580 pf_rtlabel_copyout(struct pf_addr_wrap
*a
)
585 if (a
->type
== PF_ADDR_RTLABEL
&& a
->v
.rtlabel
) {
586 if ((name
= rtlabel_id2name(a
->v
.rtlabel
)) == NULL
)
587 strlcpy(a
->v
.rtlabelname
, "?",
588 sizeof(a
->v
.rtlabelname
));
590 strlcpy(a
->v
.rtlabelname
, name
,
591 sizeof(a
->v
.rtlabelname
));
593 #endif /* !__NetBSD__ */
598 pf_qname2qid(char *qname
)
600 return ((u_int32_t
)tagname2tag(&pf_qids
, qname
));
604 pf_qid2qname(u_int32_t qid
, char *p
)
606 tag2tagname(&pf_qids
, (u_int16_t
)qid
, p
);
610 pf_qid_unref(u_int32_t qid
)
612 tag_unref(&pf_qids
, (u_int16_t
)qid
);
616 pf_begin_altq(u_int32_t
*ticket
)
618 struct pf_altq
*altq
;
621 /* Purge the old altq list */
622 while ((altq
= TAILQ_FIRST(pf_altqs_inactive
)) != NULL
) {
623 TAILQ_REMOVE(pf_altqs_inactive
, altq
, entries
);
624 if (altq
->qname
[0] == 0) {
625 /* detach and destroy the discipline */
626 error
= altq_remove(altq
);
628 pf_qid_unref(altq
->qid
);
629 pool_put(&pf_altq_pl
, altq
);
633 *ticket
= ++ticket_altqs_inactive
;
634 altqs_inactive_open
= 1;
639 pf_rollback_altq(u_int32_t ticket
)
641 struct pf_altq
*altq
;
644 if (!altqs_inactive_open
|| ticket
!= ticket_altqs_inactive
)
646 /* Purge the old altq list */
647 while ((altq
= TAILQ_FIRST(pf_altqs_inactive
)) != NULL
) {
648 TAILQ_REMOVE(pf_altqs_inactive
, altq
, entries
);
649 if (altq
->qname
[0] == 0) {
650 /* detach and destroy the discipline */
651 error
= altq_remove(altq
);
653 pf_qid_unref(altq
->qid
);
654 pool_put(&pf_altq_pl
, altq
);
656 altqs_inactive_open
= 0;
661 pf_commit_altq(u_int32_t ticket
)
663 struct pf_altqqueue
*old_altqs
;
664 struct pf_altq
*altq
;
665 int s
, err
, error
= 0;
667 if (!altqs_inactive_open
|| ticket
!= ticket_altqs_inactive
)
670 /* swap altqs, keep the old. */
672 old_altqs
= pf_altqs_active
;
673 pf_altqs_active
= pf_altqs_inactive
;
674 pf_altqs_inactive
= old_altqs
;
675 ticket_altqs_active
= ticket_altqs_inactive
;
677 /* Attach new disciplines */
678 TAILQ_FOREACH(altq
, pf_altqs_active
, entries
) {
679 if (altq
->qname
[0] == 0) {
680 /* attach the discipline */
681 error
= altq_pfattach(altq
);
682 if (error
== 0 && pf_altq_running
)
683 error
= pf_enable_altq(altq
);
691 /* Purge the old altq list */
692 while ((altq
= TAILQ_FIRST(pf_altqs_inactive
)) != NULL
) {
693 TAILQ_REMOVE(pf_altqs_inactive
, altq
, entries
);
694 if (altq
->qname
[0] == 0) {
695 /* detach and destroy the discipline */
697 error
= pf_disable_altq(altq
);
698 err
= altq_pfdetach(altq
);
699 if (err
!= 0 && error
== 0)
701 err
= altq_remove(altq
);
702 if (err
!= 0 && error
== 0)
705 pf_qid_unref(altq
->qid
);
706 pool_put(&pf_altq_pl
, altq
);
710 altqs_inactive_open
= 0;
715 pf_enable_altq(struct pf_altq
*altq
)
718 struct tb_profile tb
;
721 if ((ifp
= ifunit(altq
->ifname
)) == NULL
)
724 if (ifp
->if_snd
.altq_type
!= ALTQT_NONE
)
725 error
= altq_enable(&ifp
->if_snd
);
727 /* set tokenbucket regulator */
728 if (error
== 0 && ifp
!= NULL
&& ALTQ_IS_ENABLED(&ifp
->if_snd
)) {
729 tb
.rate
= altq
->ifbandwidth
;
730 tb
.depth
= altq
->tbrsize
;
732 error
= tbr_set(&ifp
->if_snd
, &tb
);
740 pf_disable_altq(struct pf_altq
*altq
)
743 struct tb_profile tb
;
746 if ((ifp
= ifunit(altq
->ifname
)) == NULL
)
750 * when the discipline is no longer referenced, it was overridden
751 * by a new one. if so, just return.
753 if (altq
->altq_disc
!= ifp
->if_snd
.altq_disc
)
756 error
= altq_disable(&ifp
->if_snd
);
759 /* clear tokenbucket regulator */
762 error
= tbr_set(&ifp
->if_snd
, &tb
);
771 pf_begin_rules(u_int32_t
*ticket
, int rs_num
, const char *anchor
)
773 struct pf_ruleset
*rs
;
774 struct pf_rule
*rule
;
776 if (rs_num
< 0 || rs_num
>= PF_RULESET_MAX
)
778 rs
= pf_find_or_create_ruleset(anchor
);
781 while ((rule
= TAILQ_FIRST(rs
->rules
[rs_num
].inactive
.ptr
)) != NULL
) {
782 pf_rm_rule(rs
->rules
[rs_num
].inactive
.ptr
, rule
);
783 rs
->rules
[rs_num
].inactive
.rcount
--;
785 *ticket
= ++rs
->rules
[rs_num
].inactive
.ticket
;
786 rs
->rules
[rs_num
].inactive
.open
= 1;
791 pf_rollback_rules(u_int32_t ticket
, int rs_num
, char *anchor
)
793 struct pf_ruleset
*rs
;
794 struct pf_rule
*rule
;
796 if (rs_num
< 0 || rs_num
>= PF_RULESET_MAX
)
798 rs
= pf_find_ruleset(anchor
);
799 if (rs
== NULL
|| !rs
->rules
[rs_num
].inactive
.open
||
800 rs
->rules
[rs_num
].inactive
.ticket
!= ticket
)
802 while ((rule
= TAILQ_FIRST(rs
->rules
[rs_num
].inactive
.ptr
)) != NULL
) {
803 pf_rm_rule(rs
->rules
[rs_num
].inactive
.ptr
, rule
);
804 rs
->rules
[rs_num
].inactive
.rcount
--;
806 rs
->rules
[rs_num
].inactive
.open
= 0;
810 #define PF_MD5_UPD(st, elm) \
811 MD5Update(ctx, (u_int8_t *) &(st)->elm, sizeof((st)->elm))
813 #define PF_MD5_UPD_STR(st, elm) \
814 MD5Update(ctx, (u_int8_t *) (st)->elm, strlen((st)->elm))
816 #define PF_MD5_UPD_HTONL(st, elm, stor) do { \
817 (stor) = htonl((st)->elm); \
818 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int32_t));\
821 #define PF_MD5_UPD_HTONS(st, elm, stor) do { \
822 (stor) = htons((st)->elm); \
823 MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int16_t));\
827 pf_hash_rule_addr(MD5_CTX
*ctx
, struct pf_rule_addr
*pfr
)
829 PF_MD5_UPD(pfr
, addr
.type
);
830 switch (pfr
->addr
.type
) {
831 case PF_ADDR_DYNIFTL
:
832 PF_MD5_UPD(pfr
, addr
.v
.ifname
);
833 PF_MD5_UPD(pfr
, addr
.iflags
);
836 PF_MD5_UPD(pfr
, addr
.v
.tblname
);
838 case PF_ADDR_ADDRMASK
:
840 PF_MD5_UPD(pfr
, addr
.v
.a
.addr
.addr32
);
841 PF_MD5_UPD(pfr
, addr
.v
.a
.mask
.addr32
);
843 case PF_ADDR_RTLABEL
:
844 PF_MD5_UPD(pfr
, addr
.v
.rtlabelname
);
848 PF_MD5_UPD(pfr
, port
[0]);
849 PF_MD5_UPD(pfr
, port
[1]);
850 PF_MD5_UPD(pfr
, neg
);
851 PF_MD5_UPD(pfr
, port_op
);
855 pf_hash_rule(MD5_CTX
*ctx
, struct pf_rule
*rule
)
860 pf_hash_rule_addr(ctx
, &rule
->src
);
861 pf_hash_rule_addr(ctx
, &rule
->dst
);
862 PF_MD5_UPD_STR(rule
, label
);
863 PF_MD5_UPD_STR(rule
, ifname
);
864 PF_MD5_UPD_STR(rule
, match_tagname
);
865 PF_MD5_UPD_HTONS(rule
, match_tag
, x
); /* dup? */
866 PF_MD5_UPD_HTONL(rule
, os_fingerprint
, y
);
867 PF_MD5_UPD_HTONL(rule
, prob
, y
);
868 PF_MD5_UPD_HTONL(rule
, uid
.uid
[0], y
);
869 PF_MD5_UPD_HTONL(rule
, uid
.uid
[1], y
);
870 PF_MD5_UPD(rule
, uid
.op
);
871 PF_MD5_UPD_HTONL(rule
, gid
.gid
[0], y
);
872 PF_MD5_UPD_HTONL(rule
, gid
.gid
[1], y
);
873 PF_MD5_UPD(rule
, gid
.op
);
874 PF_MD5_UPD_HTONL(rule
, rule_flag
, y
);
875 PF_MD5_UPD(rule
, action
);
876 PF_MD5_UPD(rule
, direction
);
877 PF_MD5_UPD(rule
, af
);
878 PF_MD5_UPD(rule
, quick
);
879 PF_MD5_UPD(rule
, ifnot
);
880 PF_MD5_UPD(rule
, match_tag_not
);
881 PF_MD5_UPD(rule
, natpass
);
882 PF_MD5_UPD(rule
, keep_state
);
883 PF_MD5_UPD(rule
, proto
);
884 PF_MD5_UPD(rule
, type
);
885 PF_MD5_UPD(rule
, code
);
886 PF_MD5_UPD(rule
, flags
);
887 PF_MD5_UPD(rule
, flagset
);
888 PF_MD5_UPD(rule
, allow_opts
);
889 PF_MD5_UPD(rule
, rt
);
890 PF_MD5_UPD(rule
, tos
);
894 pf_commit_rules(u_int32_t ticket
, int rs_num
, char *anchor
)
896 struct pf_ruleset
*rs
;
897 struct pf_rule
*rule
, **old_array
;
898 struct pf_rulequeue
*old_rules
;
900 u_int32_t old_rcount
;
902 if (rs_num
< 0 || rs_num
>= PF_RULESET_MAX
)
904 rs
= pf_find_ruleset(anchor
);
905 if (rs
== NULL
|| !rs
->rules
[rs_num
].inactive
.open
||
906 ticket
!= rs
->rules
[rs_num
].inactive
.ticket
)
909 /* Calculate checksum for the main ruleset */
910 if (rs
== &pf_main_ruleset
) {
911 error
= pf_setup_pfsync_matching(rs
);
916 /* Swap rules, keep the old. */
918 old_rules
= rs
->rules
[rs_num
].active
.ptr
;
919 old_rcount
= rs
->rules
[rs_num
].active
.rcount
;
920 old_array
= rs
->rules
[rs_num
].active
.ptr_array
;
922 rs
->rules
[rs_num
].active
.ptr
=
923 rs
->rules
[rs_num
].inactive
.ptr
;
924 rs
->rules
[rs_num
].active
.ptr_array
=
925 rs
->rules
[rs_num
].inactive
.ptr_array
;
926 rs
->rules
[rs_num
].active
.rcount
=
927 rs
->rules
[rs_num
].inactive
.rcount
;
928 rs
->rules
[rs_num
].inactive
.ptr
= old_rules
;
929 rs
->rules
[rs_num
].inactive
.ptr_array
= old_array
;
930 rs
->rules
[rs_num
].inactive
.rcount
= old_rcount
;
932 rs
->rules
[rs_num
].active
.ticket
=
933 rs
->rules
[rs_num
].inactive
.ticket
;
934 pf_calc_skip_steps(rs
->rules
[rs_num
].active
.ptr
);
937 /* Purge the old rule list. */
938 while ((rule
= TAILQ_FIRST(old_rules
)) != NULL
)
939 pf_rm_rule(old_rules
, rule
);
940 if (rs
->rules
[rs_num
].inactive
.ptr_array
)
941 free(rs
->rules
[rs_num
].inactive
.ptr_array
, M_TEMP
);
942 rs
->rules
[rs_num
].inactive
.ptr_array
= NULL
;
943 rs
->rules
[rs_num
].inactive
.rcount
= 0;
944 rs
->rules
[rs_num
].inactive
.open
= 0;
945 pf_remove_if_empty_ruleset(rs
);
951 pf_state_export(struct pfsync_state
*sp
, struct pf_state_key
*sk
,
954 int secs
= time_second
;
955 bzero(sp
, sizeof(struct pfsync_state
));
957 /* copy from state key */
958 sp
->lan
.addr
= sk
->lan
.addr
;
959 sp
->lan
.port
= sk
->lan
.port
;
960 sp
->gwy
.addr
= sk
->gwy
.addr
;
961 sp
->gwy
.port
= sk
->gwy
.port
;
962 sp
->ext
.addr
= sk
->ext
.addr
;
963 sp
->ext
.port
= sk
->ext
.port
;
964 sp
->proto
= sk
->proto
;
966 sp
->direction
= sk
->direction
;
968 /* copy from state */
969 memcpy(&sp
->id
, &s
->id
, sizeof(sp
->id
));
970 sp
->creatorid
= s
->creatorid
;
971 strlcpy(sp
->ifname
, s
->kif
->pfik_name
, sizeof(sp
->ifname
));
972 pf_state_peer_to_pfsync(&s
->src
, &sp
->src
);
973 pf_state_peer_to_pfsync(&s
->dst
, &sp
->dst
);
975 sp
->rule
= s
->rule
.ptr
->nr
;
976 sp
->nat_rule
= (s
->nat_rule
.ptr
== NULL
) ? -1 : s
->nat_rule
.ptr
->nr
;
977 sp
->anchor
= (s
->anchor
.ptr
== NULL
) ? -1 : s
->anchor
.ptr
->nr
;
979 pf_state_counter_to_pfsync(s
->bytes
[0], sp
->bytes
[0]);
980 pf_state_counter_to_pfsync(s
->bytes
[1], sp
->bytes
[1]);
981 pf_state_counter_to_pfsync(s
->packets
[0], sp
->packets
[0]);
982 pf_state_counter_to_pfsync(s
->packets
[1], sp
->packets
[1]);
983 sp
->creation
= secs
- s
->creation
;
984 sp
->expire
= pf_state_expires(s
);
986 sp
->allow_opts
= s
->allow_opts
;
987 sp
->timeout
= s
->timeout
;
990 sp
->sync_flags
|= PFSYNC_FLAG_SRCNODE
;
992 sp
->sync_flags
|= PFSYNC_FLAG_NATSRCNODE
;
994 if (sp
->expire
> secs
)
1002 pf_state_import(struct pfsync_state
*sp
, struct pf_state_key
*sk
,
1005 /* copy to state key */
1006 sk
->lan
.addr
= sp
->lan
.addr
;
1007 sk
->lan
.port
= sp
->lan
.port
;
1008 sk
->gwy
.addr
= sp
->gwy
.addr
;
1009 sk
->gwy
.port
= sp
->gwy
.port
;
1010 sk
->ext
.addr
= sp
->ext
.addr
;
1011 sk
->ext
.port
= sp
->ext
.port
;
1012 sk
->proto
= sp
->proto
;
1014 sk
->direction
= sp
->direction
;
1017 memcpy(&s
->id
, &sp
->id
, sizeof(sp
->id
));
1018 s
->creatorid
= sp
->creatorid
;
1019 strlcpy(sp
->ifname
, s
->kif
->pfik_name
, sizeof(sp
->ifname
));
1020 pf_state_peer_from_pfsync(&sp
->src
, &s
->src
);
1021 pf_state_peer_from_pfsync(&sp
->dst
, &s
->dst
);
1023 s
->rule
.ptr
= &pf_default_rule
;
1024 s
->nat_rule
.ptr
= NULL
;
1025 s
->anchor
.ptr
= NULL
;
1027 s
->creation
= time_second
;
1029 s
->packets
[0] = s
->packets
[1] = 0;
1030 s
->bytes
[0] = s
->bytes
[1] = 0;
1034 pf_setup_pfsync_matching(struct pf_ruleset
*rs
)
1037 struct pf_rule
*rule
;
1039 u_int8_t digest
[PF_MD5_DIGEST_LENGTH
];
1042 for (rs_cnt
= 0; rs_cnt
< PF_RULESET_MAX
; rs_cnt
++) {
1043 /* XXX PF_RULESET_SCRUB as well? */
1044 if (rs_cnt
== PF_RULESET_SCRUB
)
1047 if (rs
->rules
[rs_cnt
].inactive
.ptr_array
)
1048 free(rs
->rules
[rs_cnt
].inactive
.ptr_array
, M_TEMP
);
1049 rs
->rules
[rs_cnt
].inactive
.ptr_array
= NULL
;
1051 if (rs
->rules
[rs_cnt
].inactive
.rcount
) {
1052 rs
->rules
[rs_cnt
].inactive
.ptr_array
=
1053 malloc(sizeof(void *) *
1054 rs
->rules
[rs_cnt
].inactive
.rcount
,
1057 if (!rs
->rules
[rs_cnt
].inactive
.ptr_array
)
1061 TAILQ_FOREACH(rule
, rs
->rules
[rs_cnt
].inactive
.ptr
,
1063 pf_hash_rule(&ctx
, rule
);
1064 (rs
->rules
[rs_cnt
].inactive
.ptr_array
)[rule
->nr
] = rule
;
1068 MD5Final(digest
, &ctx
);
1069 memcpy(pf_status
.pf_chksum
, digest
, sizeof(pf_status
.pf_chksum
));
1074 pfioctl(dev_t dev
, u_long cmd
, void *addr
, int flags
, struct lwp
*l
)
1076 struct pf_pooladdr
*pa
= NULL
;
1077 struct pf_pool
*pool
= NULL
;
1081 /* XXX keep in sync with switch() below */
1082 if (kauth_authorize_network(l
->l_cred
, KAUTH_NETWORK_FIREWALL
,
1083 KAUTH_REQ_NETWORK_FIREWALL_FW
, NULL
, NULL
, NULL
))
1090 case DIOCSETSTATUSIF
:
1096 case DIOCGETTIMEOUT
:
1097 case DIOCCLRRULECTRS
:
1102 case DIOCGETRULESETS
:
1103 case DIOCGETRULESET
:
1104 case DIOCRGETTABLES
:
1105 case DIOCRGETTSTATS
:
1106 case DIOCRCLRTSTATS
:
1112 case DIOCRGETASTATS
:
1113 case DIOCRCLRASTATS
:
1116 case DIOCGETSRCNODES
:
1117 case DIOCCLRSRCNODES
:
1118 case DIOCIGETIFACES
:
1122 case DIOCRCLRTABLES
:
1123 case DIOCRADDTABLES
:
1124 case DIOCRDELTABLES
:
1125 case DIOCRSETTFLAGS
:
1126 if (((struct pfioc_table
*)addr
)->pfrio_flags
&
1128 break; /* dummy operation ok */
1134 if (!(flags
& FWRITE
))
1142 case DIOCGETTIMEOUT
:
1147 case DIOCGETRULESETS
:
1148 case DIOCGETRULESET
:
1150 case DIOCRGETTABLES
:
1151 case DIOCRGETTSTATS
:
1153 case DIOCRGETASTATS
:
1156 case DIOCGETSRCNODES
:
1157 case DIOCIGETIFACES
:
1159 case DIOCRCLRTABLES
:
1160 case DIOCRADDTABLES
:
1161 case DIOCRDELTABLES
:
1162 case DIOCRCLRTSTATS
:
1167 case DIOCRSETTFLAGS
:
1168 if (((struct pfioc_table
*)addr
)->pfrio_flags
&
1170 flags
|= FWRITE
; /* need write lock for dummy */
1171 break; /* dummy operation ok */
1175 if (((struct pfioc_rule
*)addr
)->action
== PF_GET_CLR_CNTR
)
1183 rw_enter_write(&pf_consistency_lock
);
1185 rw_enter_read(&pf_consistency_lock
);
1191 if (pf_status
.running
)
1195 error
= pf_pfil_attach();
1198 #endif /* __NetBSD__ */
1199 pf_status
.running
= 1;
1200 pf_status
.since
= time_second
;
1201 if (pf_status
.stateid
== 0) {
1202 pf_status
.stateid
= time_second
;
1203 pf_status
.stateid
= pf_status
.stateid
<< 32;
1205 DPFPRINTF(PF_DEBUG_MISC
, ("pf: started\n"));
1210 if (!pf_status
.running
)
1214 error
= pf_pfil_detach();
1217 #endif /* __NetBSD__ */
1218 pf_status
.running
= 0;
1219 pf_status
.since
= time_second
;
1220 DPFPRINTF(PF_DEBUG_MISC
, ("pf: stopped\n"));
1225 struct pfioc_rule
*pr
= (struct pfioc_rule
*)addr
;
1226 struct pf_ruleset
*ruleset
;
1227 struct pf_rule
*rule
, *tail
;
1228 struct pf_pooladdr
*pa
;
1231 pr
->anchor
[sizeof(pr
->anchor
) - 1] = 0;
1232 ruleset
= pf_find_ruleset(pr
->anchor
);
1233 if (ruleset
== NULL
) {
1237 rs_num
= pf_get_ruleset_number(pr
->rule
.action
);
1238 if (rs_num
>= PF_RULESET_MAX
) {
1242 if (pr
->rule
.return_icmp
>> 8 > ICMP_MAXTYPE
) {
1246 if (pr
->ticket
!= ruleset
->rules
[rs_num
].inactive
.ticket
) {
1250 if (pr
->pool_ticket
!= ticket_pabuf
) {
1254 rule
= pool_get(&pf_rule_pl
, PR_NOWAIT
);
1259 bcopy(&pr
->rule
, rule
, sizeof(struct pf_rule
));
1261 rule
->cuid
= kauth_cred_getuid(l
->l_cred
);
1262 rule
->cpid
= l
->l_proc
->p_pid
;
1264 rule
->cuid
= p
->p_cred
->p_ruid
;
1265 rule
->cpid
= p
->p_pid
;
1266 #endif /* !__NetBSD__ */
1267 rule
->anchor
= NULL
;
1269 TAILQ_INIT(&rule
->rpool
.list
);
1270 /* initialize refcounting */
1272 rule
->src_nodes
= 0;
1273 rule
->entries
.tqe_prev
= NULL
;
1275 if (rule
->af
== AF_INET
) {
1276 pool_put(&pf_rule_pl
, rule
);
1277 error
= EAFNOSUPPORT
;
1282 if (rule
->af
== AF_INET6
) {
1283 pool_put(&pf_rule_pl
, rule
);
1284 error
= EAFNOSUPPORT
;
1288 tail
= TAILQ_LAST(ruleset
->rules
[rs_num
].inactive
.ptr
,
1291 rule
->nr
= tail
->nr
+ 1;
1294 if (rule
->ifname
[0]) {
1295 rule
->kif
= pfi_kif_get(rule
->ifname
);
1296 if (rule
->kif
== NULL
) {
1297 pool_put(&pf_rule_pl
, rule
);
1301 pfi_kif_ref(rule
->kif
, PFI_KIF_REF_RULE
);
1305 if (rule
->rtableid
> 0 && !rtable_exists(rule
->rtableid
))
1307 #endif /* !__NetBSD__ */
1311 if (rule
->qname
[0] != 0) {
1312 if ((rule
->qid
= pf_qname2qid(rule
->qname
)) == 0)
1314 else if (rule
->pqname
[0] != 0) {
1316 pf_qname2qid(rule
->pqname
)) == 0)
1319 rule
->pqid
= rule
->qid
;
1322 if (rule
->tagname
[0])
1323 if ((rule
->tag
= pf_tagname2tag(rule
->tagname
)) == 0)
1325 if (rule
->match_tagname
[0])
1326 if ((rule
->match_tag
=
1327 pf_tagname2tag(rule
->match_tagname
)) == 0)
1329 if (rule
->rt
&& !rule
->direction
)
1334 if (rule
->logif
>= PFLOGIFS_MAX
)
1337 if (pf_rtlabel_add(&rule
->src
.addr
) ||
1338 pf_rtlabel_add(&rule
->dst
.addr
))
1340 if (pfi_dynaddr_setup(&rule
->src
.addr
, rule
->af
))
1342 if (pfi_dynaddr_setup(&rule
->dst
.addr
, rule
->af
))
1344 if (pf_tbladdr_setup(ruleset
, &rule
->src
.addr
))
1346 if (pf_tbladdr_setup(ruleset
, &rule
->dst
.addr
))
1348 if (pf_anchor_setup(rule
, ruleset
, pr
->anchor_call
))
1350 TAILQ_FOREACH(pa
, &pf_pabuf
, entries
)
1351 if (pf_tbladdr_setup(ruleset
, &pa
->addr
))
1354 if (rule
->overload_tblname
[0]) {
1355 if ((rule
->overload_tbl
= pfr_attach_table(ruleset
,
1356 rule
->overload_tblname
)) == NULL
)
1359 rule
->overload_tbl
->pfrkt_flags
|=
1363 pf_mv_pool(&pf_pabuf
, &rule
->rpool
.list
);
1364 if (((((rule
->action
== PF_NAT
) || (rule
->action
== PF_RDR
) ||
1365 (rule
->action
== PF_BINAT
)) && rule
->anchor
== NULL
) ||
1366 (rule
->rt
> PF_FASTROUTE
)) &&
1367 (TAILQ_FIRST(&rule
->rpool
.list
) == NULL
))
1371 pf_rm_rule(NULL
, rule
);
1374 rule
->rpool
.cur
= TAILQ_FIRST(&rule
->rpool
.list
);
1375 rule
->evaluations
= rule
->packets
[0] = rule
->packets
[1] =
1376 rule
->bytes
[0] = rule
->bytes
[1] = 0;
1377 TAILQ_INSERT_TAIL(ruleset
->rules
[rs_num
].inactive
.ptr
,
1379 ruleset
->rules
[rs_num
].inactive
.rcount
++;
1383 case DIOCGETRULES
: {
1384 struct pfioc_rule
*pr
= (struct pfioc_rule
*)addr
;
1385 struct pf_ruleset
*ruleset
;
1386 struct pf_rule
*tail
;
1389 pr
->anchor
[sizeof(pr
->anchor
) - 1] = 0;
1390 ruleset
= pf_find_ruleset(pr
->anchor
);
1391 if (ruleset
== NULL
) {
1395 rs_num
= pf_get_ruleset_number(pr
->rule
.action
);
1396 if (rs_num
>= PF_RULESET_MAX
) {
1400 tail
= TAILQ_LAST(ruleset
->rules
[rs_num
].active
.ptr
,
1403 pr
->nr
= tail
->nr
+ 1;
1406 pr
->ticket
= ruleset
->rules
[rs_num
].active
.ticket
;
1411 struct pfioc_rule
*pr
= (struct pfioc_rule
*)addr
;
1412 struct pf_ruleset
*ruleset
;
1413 struct pf_rule
*rule
;
1416 pr
->anchor
[sizeof(pr
->anchor
) - 1] = 0;
1417 ruleset
= pf_find_ruleset(pr
->anchor
);
1418 if (ruleset
== NULL
) {
1422 rs_num
= pf_get_ruleset_number(pr
->rule
.action
);
1423 if (rs_num
>= PF_RULESET_MAX
) {
1427 if (pr
->ticket
!= ruleset
->rules
[rs_num
].active
.ticket
) {
1431 rule
= TAILQ_FIRST(ruleset
->rules
[rs_num
].active
.ptr
);
1432 while ((rule
!= NULL
) && (rule
->nr
!= pr
->nr
))
1433 rule
= TAILQ_NEXT(rule
, entries
);
1438 bcopy(rule
, &pr
->rule
, sizeof(struct pf_rule
));
1439 if (pf_anchor_copyout(ruleset
, rule
, pr
)) {
1443 pfi_dynaddr_copyout(&pr
->rule
.src
.addr
);
1444 pfi_dynaddr_copyout(&pr
->rule
.dst
.addr
);
1445 pf_tbladdr_copyout(&pr
->rule
.src
.addr
);
1446 pf_tbladdr_copyout(&pr
->rule
.dst
.addr
);
1447 pf_rtlabel_copyout(&pr
->rule
.src
.addr
);
1448 pf_rtlabel_copyout(&pr
->rule
.dst
.addr
);
1449 for (i
= 0; i
< PF_SKIP_COUNT
; ++i
)
1450 if (rule
->skip
[i
].ptr
== NULL
)
1451 pr
->rule
.skip
[i
].nr
= -1;
1453 pr
->rule
.skip
[i
].nr
=
1454 rule
->skip
[i
].ptr
->nr
;
1456 if (pr
->action
== PF_GET_CLR_CNTR
) {
1457 rule
->evaluations
= 0;
1458 rule
->packets
[0] = rule
->packets
[1] = 0;
1459 rule
->bytes
[0] = rule
->bytes
[1] = 0;
1464 case DIOCCHANGERULE
: {
1465 struct pfioc_rule
*pcr
= (struct pfioc_rule
*)addr
;
1466 struct pf_ruleset
*ruleset
;
1467 struct pf_rule
*oldrule
= NULL
, *newrule
= NULL
;
1471 if (!(pcr
->action
== PF_CHANGE_REMOVE
||
1472 pcr
->action
== PF_CHANGE_GET_TICKET
) &&
1473 pcr
->pool_ticket
!= ticket_pabuf
) {
1478 if (pcr
->action
< PF_CHANGE_ADD_HEAD
||
1479 pcr
->action
> PF_CHANGE_GET_TICKET
) {
1483 ruleset
= pf_find_ruleset(pcr
->anchor
);
1484 if (ruleset
== NULL
) {
1488 rs_num
= pf_get_ruleset_number(pcr
->rule
.action
);
1489 if (rs_num
>= PF_RULESET_MAX
) {
1494 if (pcr
->action
== PF_CHANGE_GET_TICKET
) {
1495 pcr
->ticket
= ++ruleset
->rules
[rs_num
].active
.ticket
;
1499 ruleset
->rules
[rs_num
].active
.ticket
) {
1503 if (pcr
->rule
.return_icmp
>> 8 > ICMP_MAXTYPE
) {
1509 if (pcr
->action
!= PF_CHANGE_REMOVE
) {
1510 newrule
= pool_get(&pf_rule_pl
, PR_NOWAIT
);
1511 if (newrule
== NULL
) {
1515 bcopy(&pcr
->rule
, newrule
, sizeof(struct pf_rule
));
1517 newrule
->cuid
= kauth_cred_getuid(l
->l_cred
);
1518 newrule
->cpid
= l
->l_proc
->p_pid
;
1520 newrule
->cuid
= p
->p_cred
->p_ruid
;
1521 newrule
->cpid
= p
->p_pid
;
1522 #endif /* !__NetBSD__ */
1523 TAILQ_INIT(&newrule
->rpool
.list
);
1524 /* initialize refcounting */
1525 newrule
->states
= 0;
1526 newrule
->entries
.tqe_prev
= NULL
;
1528 if (newrule
->af
== AF_INET
) {
1529 pool_put(&pf_rule_pl
, newrule
);
1530 error
= EAFNOSUPPORT
;
1535 if (newrule
->af
== AF_INET6
) {
1536 pool_put(&pf_rule_pl
, newrule
);
1537 error
= EAFNOSUPPORT
;
1541 if (newrule
->ifname
[0]) {
1542 newrule
->kif
= pfi_kif_get(newrule
->ifname
);
1543 if (newrule
->kif
== NULL
) {
1544 pool_put(&pf_rule_pl
, newrule
);
1548 pfi_kif_ref(newrule
->kif
, PFI_KIF_REF_RULE
);
1550 newrule
->kif
= NULL
;
1553 if (newrule
->rtableid
> 0 &&
1554 !rtable_exists(newrule
->rtableid
))
1556 #endif /* !__NetBSD__ */
1560 if (newrule
->qname
[0] != 0) {
1562 pf_qname2qid(newrule
->qname
)) == 0)
1564 else if (newrule
->pqname
[0] != 0) {
1565 if ((newrule
->pqid
=
1566 pf_qname2qid(newrule
->pqname
)) == 0)
1569 newrule
->pqid
= newrule
->qid
;
1572 if (newrule
->tagname
[0])
1574 pf_tagname2tag(newrule
->tagname
)) == 0)
1576 if (newrule
->match_tagname
[0])
1577 if ((newrule
->match_tag
= pf_tagname2tag(
1578 newrule
->match_tagname
)) == 0)
1580 if (newrule
->rt
&& !newrule
->direction
)
1585 if (newrule
->logif
>= PFLOGIFS_MAX
)
1588 if (pf_rtlabel_add(&newrule
->src
.addr
) ||
1589 pf_rtlabel_add(&newrule
->dst
.addr
))
1591 if (pfi_dynaddr_setup(&newrule
->src
.addr
, newrule
->af
))
1593 if (pfi_dynaddr_setup(&newrule
->dst
.addr
, newrule
->af
))
1595 if (pf_tbladdr_setup(ruleset
, &newrule
->src
.addr
))
1597 if (pf_tbladdr_setup(ruleset
, &newrule
->dst
.addr
))
1599 if (pf_anchor_setup(newrule
, ruleset
, pcr
->anchor_call
))
1601 TAILQ_FOREACH(pa
, &pf_pabuf
, entries
)
1602 if (pf_tbladdr_setup(ruleset
, &pa
->addr
))
1605 if (newrule
->overload_tblname
[0]) {
1606 if ((newrule
->overload_tbl
= pfr_attach_table(
1607 ruleset
, newrule
->overload_tblname
)) ==
1611 newrule
->overload_tbl
->pfrkt_flags
|=
1615 pf_mv_pool(&pf_pabuf
, &newrule
->rpool
.list
);
1616 if (((((newrule
->action
== PF_NAT
) ||
1617 (newrule
->action
== PF_RDR
) ||
1618 (newrule
->action
== PF_BINAT
) ||
1619 (newrule
->rt
> PF_FASTROUTE
)) &&
1620 !newrule
->anchor
)) &&
1621 (TAILQ_FIRST(&newrule
->rpool
.list
) == NULL
))
1625 pf_rm_rule(NULL
, newrule
);
1628 newrule
->rpool
.cur
= TAILQ_FIRST(&newrule
->rpool
.list
);
1629 newrule
->evaluations
= 0;
1630 newrule
->packets
[0] = newrule
->packets
[1] = 0;
1631 newrule
->bytes
[0] = newrule
->bytes
[1] = 0;
1633 pf_empty_pool(&pf_pabuf
);
1635 if (pcr
->action
== PF_CHANGE_ADD_HEAD
)
1636 oldrule
= TAILQ_FIRST(
1637 ruleset
->rules
[rs_num
].active
.ptr
);
1638 else if (pcr
->action
== PF_CHANGE_ADD_TAIL
)
1639 oldrule
= TAILQ_LAST(
1640 ruleset
->rules
[rs_num
].active
.ptr
, pf_rulequeue
);
1642 oldrule
= TAILQ_FIRST(
1643 ruleset
->rules
[rs_num
].active
.ptr
);
1644 while ((oldrule
!= NULL
) && (oldrule
->nr
!= pcr
->nr
))
1645 oldrule
= TAILQ_NEXT(oldrule
, entries
);
1646 if (oldrule
== NULL
) {
1647 if (newrule
!= NULL
)
1648 pf_rm_rule(NULL
, newrule
);
1654 if (pcr
->action
== PF_CHANGE_REMOVE
) {
1655 pf_rm_rule(ruleset
->rules
[rs_num
].active
.ptr
, oldrule
);
1656 ruleset
->rules
[rs_num
].active
.rcount
--;
1658 if (oldrule
== NULL
)
1660 ruleset
->rules
[rs_num
].active
.ptr
,
1662 else if (pcr
->action
== PF_CHANGE_ADD_HEAD
||
1663 pcr
->action
== PF_CHANGE_ADD_BEFORE
)
1664 TAILQ_INSERT_BEFORE(oldrule
, newrule
, entries
);
1667 ruleset
->rules
[rs_num
].active
.ptr
,
1668 oldrule
, newrule
, entries
);
1669 ruleset
->rules
[rs_num
].active
.rcount
++;
1673 TAILQ_FOREACH(oldrule
,
1674 ruleset
->rules
[rs_num
].active
.ptr
, entries
)
1677 ruleset
->rules
[rs_num
].active
.ticket
++;
1679 pf_calc_skip_steps(ruleset
->rules
[rs_num
].active
.ptr
);
1680 pf_remove_if_empty_ruleset(ruleset
);
1685 case DIOCCLRSTATES
: {
1686 struct pf_state
*s
, *nexts
;
1687 struct pfioc_state_kill
*psk
= (struct pfioc_state_kill
*)addr
;
1690 for (s
= RB_MIN(pf_state_tree_id
, &tree_id
); s
; s
= nexts
) {
1691 nexts
= RB_NEXT(pf_state_tree_id
, &tree_id
, s
);
1693 if (!psk
->psk_ifname
[0] || !strcmp(psk
->psk_ifname
,
1694 s
->kif
->pfik_name
)) {
1696 /* don't send out individual delete messages */
1697 s
->sync_flags
= PFSTATE_NOSYNC
;
1703 psk
->psk_af
= killed
;
1705 pfsync_clear_states(pf_status
.hostid
, psk
->psk_ifname
);
1710 case DIOCKILLSTATES
: {
1711 struct pf_state
*s
, *nexts
;
1712 struct pf_state_key
*sk
;
1713 struct pf_state_host
*src
, *dst
;
1714 struct pfioc_state_kill
*psk
= (struct pfioc_state_kill
*)addr
;
1717 for (s
= RB_MIN(pf_state_tree_id
, &tree_id
); s
;
1719 nexts
= RB_NEXT(pf_state_tree_id
, &tree_id
, s
);
1722 if (sk
->direction
== PF_OUT
) {
1729 if ((!psk
->psk_af
|| sk
->af
== psk
->psk_af
)
1730 && (!psk
->psk_proto
|| psk
->psk_proto
==
1732 PF_MATCHA(psk
->psk_src
.neg
,
1733 &psk
->psk_src
.addr
.v
.a
.addr
,
1734 &psk
->psk_src
.addr
.v
.a
.mask
,
1735 &src
->addr
, sk
->af
) &&
1736 PF_MATCHA(psk
->psk_dst
.neg
,
1737 &psk
->psk_dst
.addr
.v
.a
.addr
,
1738 &psk
->psk_dst
.addr
.v
.a
.mask
,
1739 &dst
->addr
, sk
->af
) &&
1740 (psk
->psk_src
.port_op
== 0 ||
1741 pf_match_port(psk
->psk_src
.port_op
,
1742 psk
->psk_src
.port
[0], psk
->psk_src
.port
[1],
1744 (psk
->psk_dst
.port_op
== 0 ||
1745 pf_match_port(psk
->psk_dst
.port_op
,
1746 psk
->psk_dst
.port
[0], psk
->psk_dst
.port
[1],
1748 (!psk
->psk_ifname
[0] || !strcmp(psk
->psk_ifname
,
1749 s
->kif
->pfik_name
))) {
1751 /* send immediate delete of state */
1752 pfsync_delete_state(s
);
1753 s
->sync_flags
|= PFSTATE_NOSYNC
;
1759 psk
->psk_af
= killed
;
1763 case DIOCADDSTATE
: {
1764 struct pfioc_state
*ps
= (struct pfioc_state
*)addr
;
1765 struct pfsync_state
*sp
= (struct pfsync_state
*)ps
->state
;
1767 struct pf_state_key
*sk
;
1768 struct pfi_kif
*kif
;
1770 if (sp
->timeout
>= PFTM_MAX
&&
1771 sp
->timeout
!= PFTM_UNTIL_PACKET
) {
1775 s
= pool_get(&pf_state_pl
, PR_NOWAIT
);
1780 bzero(s
, sizeof(struct pf_state
));
1781 if ((sk
= pf_alloc_state_key(s
)) == NULL
) {
1785 pf_state_import(sp
, sk
, s
);
1786 kif
= pfi_kif_get(sp
->ifname
);
1788 pool_put(&pf_state_pl
, s
);
1789 pool_put(&pf_state_key_pl
, sk
);
1793 if (pf_insert_state(kif
, s
)) {
1794 pfi_kif_unref(kif
, PFI_KIF_REF_NONE
);
1795 pool_put(&pf_state_pl
, s
);
1796 pool_put(&pf_state_key_pl
, sk
);
1802 case DIOCGETSTATE
: {
1803 struct pfioc_state
*ps
= (struct pfioc_state
*)addr
;
1808 RB_FOREACH(s
, pf_state_tree_id
, &tree_id
) {
1818 pf_state_export((struct pfsync_state
*)&ps
->state
,
1823 case DIOCGETSTATES
: {
1824 struct pfioc_states
*ps
= (struct pfioc_states
*)addr
;
1825 struct pf_state
*state
;
1826 struct pfsync_state
*p
, *pstore
;
1829 if (ps
->ps_len
== 0) {
1830 nr
= pf_status
.states
;
1831 ps
->ps_len
= sizeof(struct pfsync_state
) * nr
;
1835 pstore
= malloc(sizeof(*pstore
), M_TEMP
, M_WAITOK
);
1839 state
= TAILQ_FIRST(&state_list
);
1841 if (state
->timeout
!= PFTM_UNLINKED
) {
1842 if ((nr
+1) * sizeof(*p
) > (unsigned)ps
->ps_len
)
1845 pf_state_export(pstore
,
1846 state
->state_key
, state
);
1847 error
= copyout(pstore
, p
, sizeof(*p
));
1849 free(pstore
, M_TEMP
);
1855 state
= TAILQ_NEXT(state
, entry_list
);
1858 ps
->ps_len
= sizeof(struct pfsync_state
) * nr
;
1860 free(pstore
, M_TEMP
);
1864 case DIOCGETSTATUS
: {
1865 struct pf_status
*s
= (struct pf_status
*)addr
;
1866 bcopy(&pf_status
, s
, sizeof(struct pf_status
));
1867 pfi_fill_oldstatus(s
);
1871 case DIOCSETSTATUSIF
: {
1872 struct pfioc_if
*pi
= (struct pfioc_if
*)addr
;
1874 if (pi
->ifname
[0] == 0) {
1875 bzero(pf_status
.ifname
, IFNAMSIZ
);
1878 if (ifunit(pi
->ifname
) == NULL
) {
1882 strlcpy(pf_status
.ifname
, pi
->ifname
, IFNAMSIZ
);
1886 case DIOCCLRSTATUS
: {
1887 bzero(pf_status
.counters
, sizeof(pf_status
.counters
));
1888 bzero(pf_status
.fcounters
, sizeof(pf_status
.fcounters
));
1889 bzero(pf_status
.scounters
, sizeof(pf_status
.scounters
));
1890 pf_status
.since
= time_second
;
1891 if (*pf_status
.ifname
)
1892 pfi_clr_istats(pf_status
.ifname
);
1897 struct pfioc_natlook
*pnl
= (struct pfioc_natlook
*)addr
;
1898 struct pf_state_key
*sk
;
1899 struct pf_state
*state
;
1900 struct pf_state_key_cmp key
;
1901 int m
= 0, direction
= pnl
->direction
;
1904 key
.proto
= pnl
->proto
;
1907 PF_AZERO(&pnl
->saddr
, pnl
->af
) ||
1908 PF_AZERO(&pnl
->daddr
, pnl
->af
) ||
1909 ((pnl
->proto
== IPPROTO_TCP
||
1910 pnl
->proto
== IPPROTO_UDP
) &&
1911 (!pnl
->dport
|| !pnl
->sport
)))
1915 * userland gives us source and dest of connection,
1916 * reverse the lookup so we ask for what happens with
1917 * the return traffic, enabling us to find it in the
1920 if (direction
== PF_IN
) {
1921 PF_ACPY(&key
.ext
.addr
, &pnl
->daddr
, pnl
->af
);
1922 key
.ext
.port
= pnl
->dport
;
1923 PF_ACPY(&key
.gwy
.addr
, &pnl
->saddr
, pnl
->af
);
1924 key
.gwy
.port
= pnl
->sport
;
1925 state
= pf_find_state_all(&key
, PF_EXT_GWY
, &m
);
1927 PF_ACPY(&key
.lan
.addr
, &pnl
->daddr
, pnl
->af
);
1928 key
.lan
.port
= pnl
->dport
;
1929 PF_ACPY(&key
.ext
.addr
, &pnl
->saddr
, pnl
->af
);
1930 key
.ext
.port
= pnl
->sport
;
1931 state
= pf_find_state_all(&key
, PF_LAN_EXT
, &m
);
1934 error
= E2BIG
; /* more than one state */
1935 else if (state
!= NULL
) {
1936 sk
= state
->state_key
;
1937 if (direction
== PF_IN
) {
1938 PF_ACPY(&pnl
->rsaddr
, &sk
->lan
.addr
,
1940 pnl
->rsport
= sk
->lan
.port
;
1941 PF_ACPY(&pnl
->rdaddr
, &pnl
->daddr
,
1943 pnl
->rdport
= pnl
->dport
;
1945 PF_ACPY(&pnl
->rdaddr
, &sk
->gwy
.addr
,
1947 pnl
->rdport
= sk
->gwy
.port
;
1948 PF_ACPY(&pnl
->rsaddr
, &pnl
->saddr
,
1950 pnl
->rsport
= pnl
->sport
;
1958 case DIOCSETTIMEOUT
: {
1959 struct pfioc_tm
*pt
= (struct pfioc_tm
*)addr
;
1962 if (pt
->timeout
< 0 || pt
->timeout
>= PFTM_MAX
||
1967 old
= pf_default_rule
.timeout
[pt
->timeout
];
1968 if (pt
->timeout
== PFTM_INTERVAL
&& pt
->seconds
== 0)
1970 pf_default_rule
.timeout
[pt
->timeout
] = pt
->seconds
;
1971 if (pt
->timeout
== PFTM_INTERVAL
&& pt
->seconds
< old
)
1972 wakeup(pf_purge_thread
);
1977 case DIOCGETTIMEOUT
: {
1978 struct pfioc_tm
*pt
= (struct pfioc_tm
*)addr
;
1980 if (pt
->timeout
< 0 || pt
->timeout
>= PFTM_MAX
) {
1984 pt
->seconds
= pf_default_rule
.timeout
[pt
->timeout
];
1988 case DIOCGETLIMIT
: {
1989 struct pfioc_limit
*pl
= (struct pfioc_limit
*)addr
;
1991 if (pl
->index
< 0 || pl
->index
>= PF_LIMIT_MAX
) {
1995 pl
->limit
= pf_pool_limits
[pl
->index
].limit
;
1999 case DIOCSETLIMIT
: {
2000 struct pfioc_limit
*pl
= (struct pfioc_limit
*)addr
;
2003 if (pl
->index
< 0 || pl
->index
>= PF_LIMIT_MAX
||
2004 pf_pool_limits
[pl
->index
].pp
== NULL
) {
2009 pool_sethardlimit(pf_pool_limits
[pl
->index
].pp
,
2010 pl
->limit
, NULL
, 0);
2012 if (pool_sethardlimit(pf_pool_limits
[pl
->index
].pp
,
2013 pl
->limit
, NULL
, 0) != 0) {
2017 #endif /* !__NetBSD__ */
2018 old_limit
= pf_pool_limits
[pl
->index
].limit
;
2019 pf_pool_limits
[pl
->index
].limit
= pl
->limit
;
2020 pl
->limit
= old_limit
;
2024 case DIOCSETDEBUG
: {
2025 u_int32_t
*level
= (u_int32_t
*)addr
;
2027 pf_status
.debug
= *level
;
2031 case DIOCCLRRULECTRS
: {
2032 /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */
2033 struct pf_ruleset
*ruleset
= &pf_main_ruleset
;
2034 struct pf_rule
*rule
;
2037 ruleset
->rules
[PF_RULESET_FILTER
].active
.ptr
, entries
) {
2038 rule
->evaluations
= 0;
2039 rule
->packets
[0] = rule
->packets
[1] = 0;
2040 rule
->bytes
[0] = rule
->bytes
[1] = 0;
2046 case DIOCSTARTALTQ
: {
2047 struct pf_altq
*altq
;
2049 /* enable all altq interfaces on active list */
2050 TAILQ_FOREACH(altq
, pf_altqs_active
, entries
) {
2051 if (altq
->qname
[0] == 0) {
2052 error
= pf_enable_altq(altq
);
2058 pf_altq_running
= 1;
2059 DPFPRINTF(PF_DEBUG_MISC
, ("altq: started\n"));
2063 case DIOCSTOPALTQ
: {
2064 struct pf_altq
*altq
;
2066 /* disable all altq interfaces on active list */
2067 TAILQ_FOREACH(altq
, pf_altqs_active
, entries
) {
2068 if (altq
->qname
[0] == 0) {
2069 error
= pf_disable_altq(altq
);
2075 pf_altq_running
= 0;
2076 DPFPRINTF(PF_DEBUG_MISC
, ("altq: stopped\n"));
2081 struct pfioc_altq
*pa
= (struct pfioc_altq
*)addr
;
2082 struct pf_altq
*altq
, *a
;
2084 if (pa
->ticket
!= ticket_altqs_inactive
) {
2088 altq
= pool_get(&pf_altq_pl
, PR_NOWAIT
);
2093 bcopy(&pa
->altq
, altq
, sizeof(struct pf_altq
));
2096 * if this is for a queue, find the discipline and
2097 * copy the necessary fields
2099 if (altq
->qname
[0] != 0) {
2100 if ((altq
->qid
= pf_qname2qid(altq
->qname
)) == 0) {
2102 pool_put(&pf_altq_pl
, altq
);
2105 TAILQ_FOREACH(a
, pf_altqs_inactive
, entries
) {
2106 if (strncmp(a
->ifname
, altq
->ifname
,
2107 IFNAMSIZ
) == 0 && a
->qname
[0] == 0) {
2108 altq
->altq_disc
= a
->altq_disc
;
2114 error
= altq_add(altq
);
2116 pool_put(&pf_altq_pl
, altq
);
2120 TAILQ_INSERT_TAIL(pf_altqs_inactive
, altq
, entries
);
2121 bcopy(altq
, &pa
->altq
, sizeof(struct pf_altq
));
2125 case DIOCGETALTQS
: {
2126 struct pfioc_altq
*pa
= (struct pfioc_altq
*)addr
;
2127 struct pf_altq
*altq
;
2130 TAILQ_FOREACH(altq
, pf_altqs_active
, entries
)
2132 pa
->ticket
= ticket_altqs_active
;
2137 struct pfioc_altq
*pa
= (struct pfioc_altq
*)addr
;
2138 struct pf_altq
*altq
;
2141 if (pa
->ticket
!= ticket_altqs_active
) {
2146 altq
= TAILQ_FIRST(pf_altqs_active
);
2147 while ((altq
!= NULL
) && (nr
< pa
->nr
)) {
2148 altq
= TAILQ_NEXT(altq
, entries
);
2155 bcopy(altq
, &pa
->altq
, sizeof(struct pf_altq
));
2159 case DIOCCHANGEALTQ
:
2160 /* CHANGEALTQ not supported yet! */
2164 case DIOCGETQSTATS
: {
2165 struct pfioc_qstats
*pq
= (struct pfioc_qstats
*)addr
;
2166 struct pf_altq
*altq
;
2170 if (pq
->ticket
!= ticket_altqs_active
) {
2174 nbytes
= pq
->nbytes
;
2176 altq
= TAILQ_FIRST(pf_altqs_active
);
2177 while ((altq
!= NULL
) && (nr
< pq
->nr
)) {
2178 altq
= TAILQ_NEXT(altq
, entries
);
2185 error
= altq_getqstats(altq
, pq
->buf
, &nbytes
);
2187 pq
->scheduler
= altq
->scheduler
;
2188 pq
->nbytes
= nbytes
;
2194 case DIOCBEGINADDRS
: {
2195 struct pfioc_pooladdr
*pp
= (struct pfioc_pooladdr
*)addr
;
2197 pf_empty_pool(&pf_pabuf
);
2198 pp
->ticket
= ++ticket_pabuf
;
2203 struct pfioc_pooladdr
*pp
= (struct pfioc_pooladdr
*)addr
;
2205 if (pp
->ticket
!= ticket_pabuf
) {
2210 if (pp
->af
== AF_INET
) {
2211 error
= EAFNOSUPPORT
;
2216 if (pp
->af
== AF_INET6
) {
2217 error
= EAFNOSUPPORT
;
2221 if (pp
->addr
.addr
.type
!= PF_ADDR_ADDRMASK
&&
2222 pp
->addr
.addr
.type
!= PF_ADDR_DYNIFTL
&&
2223 pp
->addr
.addr
.type
!= PF_ADDR_TABLE
) {
2227 pa
= pool_get(&pf_pooladdr_pl
, PR_NOWAIT
);
2232 bcopy(&pp
->addr
, pa
, sizeof(struct pf_pooladdr
));
2233 if (pa
->ifname
[0]) {
2234 pa
->kif
= pfi_kif_get(pa
->ifname
);
2235 if (pa
->kif
== NULL
) {
2236 pool_put(&pf_pooladdr_pl
, pa
);
2240 pfi_kif_ref(pa
->kif
, PFI_KIF_REF_RULE
);
2242 if (pfi_dynaddr_setup(&pa
->addr
, pp
->af
)) {
2243 pfi_dynaddr_remove(&pa
->addr
);
2244 pfi_kif_unref(pa
->kif
, PFI_KIF_REF_RULE
);
2245 pool_put(&pf_pooladdr_pl
, pa
);
2249 TAILQ_INSERT_TAIL(&pf_pabuf
, pa
, entries
);
2253 case DIOCGETADDRS
: {
2254 struct pfioc_pooladdr
*pp
= (struct pfioc_pooladdr
*)addr
;
2257 pool
= pf_get_pool(pp
->anchor
, pp
->ticket
, pp
->r_action
,
2258 pp
->r_num
, 0, 1, 0);
2263 TAILQ_FOREACH(pa
, &pool
->list
, entries
)
2269 struct pfioc_pooladdr
*pp
= (struct pfioc_pooladdr
*)addr
;
2272 pool
= pf_get_pool(pp
->anchor
, pp
->ticket
, pp
->r_action
,
2273 pp
->r_num
, 0, 1, 1);
2278 pa
= TAILQ_FIRST(&pool
->list
);
2279 while ((pa
!= NULL
) && (nr
< pp
->nr
)) {
2280 pa
= TAILQ_NEXT(pa
, entries
);
2287 bcopy(pa
, &pp
->addr
, sizeof(struct pf_pooladdr
));
2288 pfi_dynaddr_copyout(&pp
->addr
.addr
);
2289 pf_tbladdr_copyout(&pp
->addr
.addr
);
2290 pf_rtlabel_copyout(&pp
->addr
.addr
);
2294 case DIOCCHANGEADDR
: {
2295 struct pfioc_pooladdr
*pca
= (struct pfioc_pooladdr
*)addr
;
2296 struct pf_pooladdr
*oldpa
= NULL
, *newpa
= NULL
;
2297 struct pf_ruleset
*ruleset
;
2299 if (pca
->action
< PF_CHANGE_ADD_HEAD
||
2300 pca
->action
> PF_CHANGE_REMOVE
) {
2304 if (pca
->addr
.addr
.type
!= PF_ADDR_ADDRMASK
&&
2305 pca
->addr
.addr
.type
!= PF_ADDR_DYNIFTL
&&
2306 pca
->addr
.addr
.type
!= PF_ADDR_TABLE
) {
2311 ruleset
= pf_find_ruleset(pca
->anchor
);
2312 if (ruleset
== NULL
) {
2316 pool
= pf_get_pool(pca
->anchor
, pca
->ticket
, pca
->r_action
,
2317 pca
->r_num
, pca
->r_last
, 1, 1);
2322 if (pca
->action
!= PF_CHANGE_REMOVE
) {
2323 newpa
= pool_get(&pf_pooladdr_pl
, PR_NOWAIT
);
2324 if (newpa
== NULL
) {
2328 bcopy(&pca
->addr
, newpa
, sizeof(struct pf_pooladdr
));
2330 if (pca
->af
== AF_INET
) {
2331 pool_put(&pf_pooladdr_pl
, newpa
);
2332 error
= EAFNOSUPPORT
;
2337 if (pca
->af
== AF_INET6
) {
2338 pool_put(&pf_pooladdr_pl
, newpa
);
2339 error
= EAFNOSUPPORT
;
2343 if (newpa
->ifname
[0]) {
2344 newpa
->kif
= pfi_kif_get(newpa
->ifname
);
2345 if (newpa
->kif
== NULL
) {
2346 pool_put(&pf_pooladdr_pl
, newpa
);
2350 pfi_kif_ref(newpa
->kif
, PFI_KIF_REF_RULE
);
2353 if (pfi_dynaddr_setup(&newpa
->addr
, pca
->af
) ||
2354 pf_tbladdr_setup(ruleset
, &newpa
->addr
)) {
2355 pfi_dynaddr_remove(&newpa
->addr
);
2356 pfi_kif_unref(newpa
->kif
, PFI_KIF_REF_RULE
);
2357 pool_put(&pf_pooladdr_pl
, newpa
);
2363 if (pca
->action
== PF_CHANGE_ADD_HEAD
)
2364 oldpa
= TAILQ_FIRST(&pool
->list
);
2365 else if (pca
->action
== PF_CHANGE_ADD_TAIL
)
2366 oldpa
= TAILQ_LAST(&pool
->list
, pf_palist
);
2370 oldpa
= TAILQ_FIRST(&pool
->list
);
2371 while ((oldpa
!= NULL
) && (i
< pca
->nr
)) {
2372 oldpa
= TAILQ_NEXT(oldpa
, entries
);
2375 if (oldpa
== NULL
) {
2381 if (pca
->action
== PF_CHANGE_REMOVE
) {
2382 TAILQ_REMOVE(&pool
->list
, oldpa
, entries
);
2383 pfi_dynaddr_remove(&oldpa
->addr
);
2384 pf_tbladdr_remove(&oldpa
->addr
);
2385 pfi_kif_unref(oldpa
->kif
, PFI_KIF_REF_RULE
);
2386 pool_put(&pf_pooladdr_pl
, oldpa
);
2389 TAILQ_INSERT_TAIL(&pool
->list
, newpa
, entries
);
2390 else if (pca
->action
== PF_CHANGE_ADD_HEAD
||
2391 pca
->action
== PF_CHANGE_ADD_BEFORE
)
2392 TAILQ_INSERT_BEFORE(oldpa
, newpa
, entries
);
2394 TAILQ_INSERT_AFTER(&pool
->list
, oldpa
,
2398 pool
->cur
= TAILQ_FIRST(&pool
->list
);
2399 PF_ACPY(&pool
->counter
, &pool
->cur
->addr
.v
.a
.addr
,
2404 case DIOCGETRULESETS
: {
2405 struct pfioc_ruleset
*pr
= (struct pfioc_ruleset
*)addr
;
2406 struct pf_ruleset
*ruleset
;
2407 struct pf_anchor
*anchor
;
2409 pr
->path
[sizeof(pr
->path
) - 1] = 0;
2410 if ((ruleset
= pf_find_ruleset(pr
->path
)) == NULL
) {
2415 if (ruleset
->anchor
== NULL
) {
2416 /* XXX kludge for pf_main_ruleset */
2417 RB_FOREACH(anchor
, pf_anchor_global
, &pf_anchors
)
2418 if (anchor
->parent
== NULL
)
2421 RB_FOREACH(anchor
, pf_anchor_node
,
2422 &ruleset
->anchor
->children
)
2428 case DIOCGETRULESET
: {
2429 struct pfioc_ruleset
*pr
= (struct pfioc_ruleset
*)addr
;
2430 struct pf_ruleset
*ruleset
;
2431 struct pf_anchor
*anchor
;
2434 pr
->path
[sizeof(pr
->path
) - 1] = 0;
2435 if ((ruleset
= pf_find_ruleset(pr
->path
)) == NULL
) {
2440 if (ruleset
->anchor
== NULL
) {
2441 /* XXX kludge for pf_main_ruleset */
2442 RB_FOREACH(anchor
, pf_anchor_global
, &pf_anchors
)
2443 if (anchor
->parent
== NULL
&& nr
++ == pr
->nr
) {
2444 strlcpy(pr
->name
, anchor
->name
,
2449 RB_FOREACH(anchor
, pf_anchor_node
,
2450 &ruleset
->anchor
->children
)
2451 if (nr
++ == pr
->nr
) {
2452 strlcpy(pr
->name
, anchor
->name
,
2462 case DIOCRCLRTABLES
: {
2463 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2465 if (io
->pfrio_esize
!= 0) {
2469 error
= pfr_clr_tables(&io
->pfrio_table
, &io
->pfrio_ndel
,
2470 io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2474 case DIOCRADDTABLES
: {
2475 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2477 if (io
->pfrio_esize
!= sizeof(struct pfr_table
)) {
2481 error
= pfr_add_tables(io
->pfrio_buffer
, io
->pfrio_size
,
2482 &io
->pfrio_nadd
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2486 case DIOCRDELTABLES
: {
2487 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2489 if (io
->pfrio_esize
!= sizeof(struct pfr_table
)) {
2493 error
= pfr_del_tables(io
->pfrio_buffer
, io
->pfrio_size
,
2494 &io
->pfrio_ndel
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2498 case DIOCRGETTABLES
: {
2499 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2501 if (io
->pfrio_esize
!= sizeof(struct pfr_table
)) {
2505 error
= pfr_get_tables(&io
->pfrio_table
, io
->pfrio_buffer
,
2506 &io
->pfrio_size
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2510 case DIOCRGETTSTATS
: {
2511 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2513 if (io
->pfrio_esize
!= sizeof(struct pfr_tstats
)) {
2517 error
= pfr_get_tstats(&io
->pfrio_table
, io
->pfrio_buffer
,
2518 &io
->pfrio_size
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2522 case DIOCRCLRTSTATS
: {
2523 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2525 if (io
->pfrio_esize
!= sizeof(struct pfr_table
)) {
2529 error
= pfr_clr_tstats(io
->pfrio_buffer
, io
->pfrio_size
,
2530 &io
->pfrio_nzero
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2534 case DIOCRSETTFLAGS
: {
2535 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2537 if (io
->pfrio_esize
!= sizeof(struct pfr_table
)) {
2541 error
= pfr_set_tflags(io
->pfrio_buffer
, io
->pfrio_size
,
2542 io
->pfrio_setflag
, io
->pfrio_clrflag
, &io
->pfrio_nchange
,
2543 &io
->pfrio_ndel
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2547 case DIOCRCLRADDRS
: {
2548 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2550 if (io
->pfrio_esize
!= 0) {
2554 error
= pfr_clr_addrs(&io
->pfrio_table
, &io
->pfrio_ndel
,
2555 io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2559 case DIOCRADDADDRS
: {
2560 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2562 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2566 error
= pfr_add_addrs(&io
->pfrio_table
, io
->pfrio_buffer
,
2567 io
->pfrio_size
, &io
->pfrio_nadd
, io
->pfrio_flags
|
2568 PFR_FLAG_USERIOCTL
);
2572 case DIOCRDELADDRS
: {
2573 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2575 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2579 error
= pfr_del_addrs(&io
->pfrio_table
, io
->pfrio_buffer
,
2580 io
->pfrio_size
, &io
->pfrio_ndel
, io
->pfrio_flags
|
2581 PFR_FLAG_USERIOCTL
);
2585 case DIOCRSETADDRS
: {
2586 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2588 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2592 error
= pfr_set_addrs(&io
->pfrio_table
, io
->pfrio_buffer
,
2593 io
->pfrio_size
, &io
->pfrio_size2
, &io
->pfrio_nadd
,
2594 &io
->pfrio_ndel
, &io
->pfrio_nchange
, io
->pfrio_flags
|
2595 PFR_FLAG_USERIOCTL
, 0);
2599 case DIOCRGETADDRS
: {
2600 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2602 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2606 error
= pfr_get_addrs(&io
->pfrio_table
, io
->pfrio_buffer
,
2607 &io
->pfrio_size
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2611 case DIOCRGETASTATS
: {
2612 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2614 if (io
->pfrio_esize
!= sizeof(struct pfr_astats
)) {
2618 error
= pfr_get_astats(&io
->pfrio_table
, io
->pfrio_buffer
,
2619 &io
->pfrio_size
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2623 case DIOCRCLRASTATS
: {
2624 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2626 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2630 error
= pfr_clr_astats(&io
->pfrio_table
, io
->pfrio_buffer
,
2631 io
->pfrio_size
, &io
->pfrio_nzero
, io
->pfrio_flags
|
2632 PFR_FLAG_USERIOCTL
);
2636 case DIOCRTSTADDRS
: {
2637 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2639 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2643 error
= pfr_tst_addrs(&io
->pfrio_table
, io
->pfrio_buffer
,
2644 io
->pfrio_size
, &io
->pfrio_nmatch
, io
->pfrio_flags
|
2645 PFR_FLAG_USERIOCTL
);
2649 case DIOCRINADEFINE
: {
2650 struct pfioc_table
*io
= (struct pfioc_table
*)addr
;
2652 if (io
->pfrio_esize
!= sizeof(struct pfr_addr
)) {
2656 error
= pfr_ina_define(&io
->pfrio_table
, io
->pfrio_buffer
,
2657 io
->pfrio_size
, &io
->pfrio_nadd
, &io
->pfrio_naddr
,
2658 io
->pfrio_ticket
, io
->pfrio_flags
| PFR_FLAG_USERIOCTL
);
2663 struct pf_osfp_ioctl
*io
= (struct pf_osfp_ioctl
*)addr
;
2664 error
= pf_osfp_add(io
);
2669 struct pf_osfp_ioctl
*io
= (struct pf_osfp_ioctl
*)addr
;
2670 error
= pf_osfp_get(io
);
2675 struct pfioc_trans
*io
= (struct pfioc_trans
*)addr
;
2676 struct pfioc_trans_e
*ioe
;
2677 struct pfr_table
*table
;
2680 if (io
->esize
!= sizeof(*ioe
)) {
2684 ioe
= (struct pfioc_trans_e
*)malloc(sizeof(*ioe
),
2686 table
= (struct pfr_table
*)malloc(sizeof(*table
),
2688 for (i
= 0; i
< io
->size
; i
++) {
2689 if (copyin(io
->array
+i
, ioe
, sizeof(*ioe
))) {
2690 free(table
, M_TEMP
);
2695 switch (ioe
->rs_num
) {
2697 case PF_RULESET_ALTQ
:
2698 if (ioe
->anchor
[0]) {
2699 free(table
, M_TEMP
);
2704 if ((error
= pf_begin_altq(&ioe
->ticket
))) {
2705 free(table
, M_TEMP
);
2711 case PF_RULESET_TABLE
:
2712 bzero(table
, sizeof(*table
));
2713 strlcpy(table
->pfrt_anchor
, ioe
->anchor
,
2714 sizeof(table
->pfrt_anchor
));
2715 if ((error
= pfr_ina_begin(table
,
2716 &ioe
->ticket
, NULL
, 0))) {
2717 free(table
, M_TEMP
);
2723 if ((error
= pf_begin_rules(&ioe
->ticket
,
2724 ioe
->rs_num
, ioe
->anchor
))) {
2725 free(table
, M_TEMP
);
2731 if (copyout(ioe
, io
->array
+i
, sizeof(io
->array
[i
]))) {
2732 free(table
, M_TEMP
);
2738 free(table
, M_TEMP
);
2743 case DIOCXROLLBACK
: {
2744 struct pfioc_trans
*io
= (struct pfioc_trans
*)addr
;
2745 struct pfioc_trans_e
*ioe
;
2746 struct pfr_table
*table
;
2749 if (io
->esize
!= sizeof(*ioe
)) {
2753 ioe
= (struct pfioc_trans_e
*)malloc(sizeof(*ioe
),
2755 table
= (struct pfr_table
*)malloc(sizeof(*table
),
2757 for (i
= 0; i
< io
->size
; i
++) {
2758 if (copyin(io
->array
+i
, ioe
, sizeof(*ioe
))) {
2759 free(table
, M_TEMP
);
2764 switch (ioe
->rs_num
) {
2766 case PF_RULESET_ALTQ
:
2767 if (ioe
->anchor
[0]) {
2768 free(table
, M_TEMP
);
2773 if ((error
= pf_rollback_altq(ioe
->ticket
))) {
2774 free(table
, M_TEMP
);
2776 goto fail
; /* really bad */
2780 case PF_RULESET_TABLE
:
2781 bzero(table
, sizeof(*table
));
2782 strlcpy(table
->pfrt_anchor
, ioe
->anchor
,
2783 sizeof(table
->pfrt_anchor
));
2784 if ((error
= pfr_ina_rollback(table
,
2785 ioe
->ticket
, NULL
, 0))) {
2786 free(table
, M_TEMP
);
2788 goto fail
; /* really bad */
2792 if ((error
= pf_rollback_rules(ioe
->ticket
,
2793 ioe
->rs_num
, ioe
->anchor
))) {
2794 free(table
, M_TEMP
);
2796 goto fail
; /* really bad */
2801 free(table
, M_TEMP
);
2807 struct pfioc_trans
*io
= (struct pfioc_trans
*)addr
;
2808 struct pfioc_trans_e
*ioe
;
2809 struct pfr_table
*table
;
2810 struct pf_ruleset
*rs
;
2813 if (io
->esize
!= sizeof(*ioe
)) {
2817 ioe
= (struct pfioc_trans_e
*)malloc(sizeof(*ioe
),
2819 table
= (struct pfr_table
*)malloc(sizeof(*table
),
2821 /* first makes sure everything will succeed */
2822 for (i
= 0; i
< io
->size
; i
++) {
2823 if (copyin(io
->array
+i
, ioe
, sizeof(*ioe
))) {
2824 free(table
, M_TEMP
);
2829 switch (ioe
->rs_num
) {
2831 case PF_RULESET_ALTQ
:
2832 if (ioe
->anchor
[0]) {
2833 free(table
, M_TEMP
);
2838 if (!altqs_inactive_open
|| ioe
->ticket
!=
2839 ticket_altqs_inactive
) {
2840 free(table
, M_TEMP
);
2847 case PF_RULESET_TABLE
:
2848 rs
= pf_find_ruleset(ioe
->anchor
);
2849 if (rs
== NULL
|| !rs
->topen
|| ioe
->ticket
!=
2851 free(table
, M_TEMP
);
2858 if (ioe
->rs_num
< 0 || ioe
->rs_num
>=
2860 free(table
, M_TEMP
);
2865 rs
= pf_find_ruleset(ioe
->anchor
);
2867 !rs
->rules
[ioe
->rs_num
].inactive
.open
||
2868 rs
->rules
[ioe
->rs_num
].inactive
.ticket
!=
2870 free(table
, M_TEMP
);
2878 /* now do the commit - no errors should happen here */
2879 for (i
= 0; i
< io
->size
; i
++) {
2880 if (copyin(io
->array
+i
, ioe
, sizeof(*ioe
))) {
2881 free(table
, M_TEMP
);
2886 switch (ioe
->rs_num
) {
2888 case PF_RULESET_ALTQ
:
2889 if ((error
= pf_commit_altq(ioe
->ticket
))) {
2890 free(table
, M_TEMP
);
2892 goto fail
; /* really bad */
2896 case PF_RULESET_TABLE
:
2897 bzero(table
, sizeof(*table
));
2898 strlcpy(table
->pfrt_anchor
, ioe
->anchor
,
2899 sizeof(table
->pfrt_anchor
));
2900 if ((error
= pfr_ina_commit(table
, ioe
->ticket
,
2902 free(table
, M_TEMP
);
2904 goto fail
; /* really bad */
2908 if ((error
= pf_commit_rules(ioe
->ticket
,
2909 ioe
->rs_num
, ioe
->anchor
))) {
2910 free(table
, M_TEMP
);
2912 goto fail
; /* really bad */
2917 free(table
, M_TEMP
);
2922 case DIOCGETSRCNODES
: {
2923 struct pfioc_src_nodes
*psn
= (struct pfioc_src_nodes
*)addr
;
2924 struct pf_src_node
*n
, *p
, *pstore
;
2926 int space
= psn
->psn_len
;
2929 RB_FOREACH(n
, pf_src_tree
, &tree_src_tracking
)
2931 psn
->psn_len
= sizeof(struct pf_src_node
) * nr
;
2935 pstore
= malloc(sizeof(*pstore
), M_TEMP
, M_WAITOK
);
2937 p
= psn
->psn_src_nodes
;
2938 RB_FOREACH(n
, pf_src_tree
, &tree_src_tracking
) {
2939 int secs
= time_second
, diff
;
2941 if ((nr
+ 1) * sizeof(*p
) > (unsigned)psn
->psn_len
)
2944 bcopy(n
, pstore
, sizeof(*pstore
));
2945 if (n
->rule
.ptr
!= NULL
)
2946 pstore
->rule
.nr
= n
->rule
.ptr
->nr
;
2947 pstore
->creation
= secs
- pstore
->creation
;
2948 if (pstore
->expire
> secs
)
2949 pstore
->expire
-= secs
;
2953 /* adjust the connection rate estimate */
2954 diff
= secs
- n
->conn_rate
.last
;
2955 if (diff
>= n
->conn_rate
.seconds
)
2956 pstore
->conn_rate
.count
= 0;
2958 pstore
->conn_rate
.count
-=
2959 n
->conn_rate
.count
* diff
/
2960 n
->conn_rate
.seconds
;
2962 error
= copyout(pstore
, p
, sizeof(*p
));
2964 free(pstore
, M_TEMP
);
2970 psn
->psn_len
= sizeof(struct pf_src_node
) * nr
;
2972 free(pstore
, M_TEMP
);
2976 case DIOCCLRSRCNODES
: {
2977 struct pf_src_node
*n
;
2978 struct pf_state
*state
;
2980 RB_FOREACH(state
, pf_state_tree_id
, &tree_id
) {
2981 state
->src_node
= NULL
;
2982 state
->nat_src_node
= NULL
;
2984 RB_FOREACH(n
, pf_src_tree
, &tree_src_tracking
) {
2988 pf_purge_expired_src_nodes(1);
2989 pf_status
.src_nodes
= 0;
2993 case DIOCKILLSRCNODES
: {
2994 struct pf_src_node
*sn
;
2996 struct pfioc_src_node_kill
*psnk
= \
2997 (struct pfioc_src_node_kill
*) addr
;
3000 RB_FOREACH(sn
, pf_src_tree
, &tree_src_tracking
) {
3001 if (PF_MATCHA(psnk
->psnk_src
.neg
, \
3002 &psnk
->psnk_src
.addr
.v
.a
.addr
, \
3003 &psnk
->psnk_src
.addr
.v
.a
.mask
, \
3004 &sn
->addr
, sn
->af
) &&
3005 PF_MATCHA(psnk
->psnk_dst
.neg
, \
3006 &psnk
->psnk_dst
.addr
.v
.a
.addr
, \
3007 &psnk
->psnk_dst
.addr
.v
.a
.mask
, \
3008 &sn
->raddr
, sn
->af
)) {
3009 /* Handle state to src_node linkage */
3010 if (sn
->states
!= 0) {
3011 RB_FOREACH(s
, pf_state_tree_id
,
3013 if (s
->src_node
== sn
)
3015 if (s
->nat_src_node
== sn
)
3016 s
->nat_src_node
= NULL
;
3026 pf_purge_expired_src_nodes(1);
3028 psnk
->psnk_af
= killed
;
3032 case DIOCSETHOSTID
: {
3033 u_int32_t
*hostid
= (u_int32_t
*)addr
;
3036 pf_status
.hostid
= arc4random();
3038 pf_status
.hostid
= *hostid
;
3046 case DIOCIGETIFACES
: {
3047 struct pfioc_iface
*io
= (struct pfioc_iface
*)addr
;
3049 if (io
->pfiio_esize
!= sizeof(struct pfi_kif
)) {
3053 error
= pfi_get_ifaces(io
->pfiio_name
, io
->pfiio_buffer
,
3058 case DIOCSETIFFLAG
: {
3059 struct pfioc_iface
*io
= (struct pfioc_iface
*)addr
;
3061 error
= pfi_set_flags(io
->pfiio_name
, io
->pfiio_flags
);
3065 case DIOCCLRIFFLAG
: {
3066 struct pfioc_iface
*io
= (struct pfioc_iface
*)addr
;
3068 error
= pfi_clear_flags(io
->pfiio_name
, io
->pfiio_flags
);
3079 rw_exit_write(&pf_consistency_lock
);
3081 rw_exit_read(&pf_consistency_lock
);
3088 pfil4_wrapper(void *arg
, struct mbuf
**mp
, struct ifnet
*ifp
, int dir
)
3093 * ensure that mbufs are writable beforehand
3094 * as it's assumed by pf code.
3095 * ip hdr (60 bytes) + tcp hdr (60 bytes) should be enough.
3098 error
= m_makewritable(mp
, 0, 60 + 60, M_DONTWAIT
);
3106 * If the packet is out-bound, we can't delay checksums
3107 * here. For in-bound, the checksum has already been
3110 if (dir
== PFIL_OUT
) {
3111 if ((*mp
)->m_pkthdr
.csum_flags
& (M_CSUM_TCPv4
|M_CSUM_UDPv4
)) {
3112 in_delayed_cksum(*mp
);
3113 (*mp
)->m_pkthdr
.csum_flags
&=
3114 ~(M_CSUM_TCPv4
|M_CSUM_UDPv4
);
3118 if (pf_test(dir
== PFIL_OUT
? PF_OUT
: PF_IN
, ifp
, mp
, NULL
)
3122 return EHOSTUNREACH
;
3126 * we're not compatible with fast-forward.
3129 if (dir
== PFIL_IN
&& *mp
) {
3130 (*mp
)->m_flags
&= ~M_CANFASTFWD
;
3139 pfil6_wrapper(void *arg
, struct mbuf
**mp
, struct ifnet
*ifp
, int dir
)
3144 * ensure that mbufs are writable beforehand
3145 * as it's assumed by pf code.
3148 error
= m_makewritable(mp
, 0, M_COPYALL
, M_DONTWAIT
);
3156 * If the packet is out-bound, we can't delay checksums
3157 * here. For in-bound, the checksum has already been
3160 if (dir
== PFIL_OUT
) {
3161 if ((*mp
)->m_pkthdr
.csum_flags
& (M_CSUM_TCPv6
|M_CSUM_UDPv6
)) {
3162 in6_delayed_cksum(*mp
);
3163 (*mp
)->m_pkthdr
.csum_flags
&=
3164 ~(M_CSUM_TCPv6
|M_CSUM_UDPv6
);
3168 if (pf_test6(dir
== PFIL_OUT
? PF_OUT
: PF_IN
, ifp
, mp
, NULL
)
3172 return EHOSTUNREACH
;
3179 pf_pfil_attach(void)
3181 struct pfil_head
*ph_inet
;
3183 struct pfil_head
*ph_inet6
;
3187 if (pf_pfil_attached
)
3190 ph_inet
= pfil_head_get(PFIL_TYPE_AF
, AF_INET
);
3192 error
= pfil_add_hook((void *)pfil4_wrapper
, NULL
,
3193 PFIL_IN
|PFIL_OUT
, ph_inet
);
3200 ph_inet6
= pfil_head_get(PFIL_TYPE_AF
, AF_INET6
);
3202 error
= pfil_add_hook((void *)pfil6_wrapper
, NULL
,
3203 PFIL_IN
|PFIL_OUT
, ph_inet6
);
3210 pf_pfil_attached
= 1;
3216 pfil_remove_hook(pfil4_wrapper
, NULL
, PFIL_IN
|PFIL_OUT
, ph_inet
);
3223 pf_pfil_detach(void)
3225 struct pfil_head
*ph_inet
;
3227 struct pfil_head
*ph_inet6
;
3230 if (pf_pfil_attached
== 0)
3233 ph_inet
= pfil_head_get(PFIL_TYPE_AF
, AF_INET
);
3235 pfil_remove_hook((void *)pfil4_wrapper
, NULL
,
3236 PFIL_IN
|PFIL_OUT
, ph_inet
);
3238 ph_inet6
= pfil_head_get(PFIL_TYPE_AF
, AF_INET6
);
3240 pfil_remove_hook((void *)pfil6_wrapper
, NULL
,
3241 PFIL_IN
|PFIL_OUT
, ph_inet6
);
3243 pf_pfil_attached
= 0;
3247 #endif /* __NetBSD__ */