2  * Copyright (c) 2007-2014 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29 /*      $apfw: git commit b6bf13f8321283cd7ee82b1795e86506084b1b95 $ */ 
  30 /*      $OpenBSD: pf_ioctl.c,v 1.175 2007/02/26 22:47:43 deraadt Exp $ */ 
  33  * Copyright (c) 2001 Daniel Hartmeier 
  34  * Copyright (c) 2002,2003 Henning Brauer 
  35  * All rights reserved. 
  37  * Redistribution and use in source and binary forms, with or without 
  38  * modification, are permitted provided that the following conditions 
  41  *    - Redistributions of source code must retain the above copyright 
  42  *      notice, this list of conditions and the following disclaimer. 
  43  *    - Redistributions in binary form must reproduce the above 
  44  *      copyright notice, this list of conditions and the following 
  45  *      disclaimer in the documentation and/or other materials provided 
  46  *      with the distribution. 
  48  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  49  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
  50  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
  51  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
  52  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
  53  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
  54  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
  55  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  56  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
  58  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  59  * POSSIBILITY OF SUCH DAMAGE. 
  61  * Effort sponsored in part by the Defense Advanced Research Projects 
  62  * Agency (DARPA) and Air Force Research Laboratory, Air Force 
  63  * Materiel Command, USAF, under agreement number F30602-01-2-0537. 
  67 #include <machine/endian.h> 
  68 #include <sys/param.h> 
  69 #include <sys/systm.h> 
  71 #include <sys/filio.h> 
  72 #include <sys/fcntl.h> 
  73 #include <sys/socket.h> 
  74 #include <sys/socketvar.h> 
  75 #include <sys/kernel.h> 
  77 #include <sys/proc_internal.h> 
  78 #include <sys/malloc.h> 
  79 #include <sys/kauth.h> 
  81 #include <sys/mcache.h> 
  82 #include <sys/queue.h> 
  84 #include <mach/vm_param.h> 
  88 #include <net/if_types.h> 
  89 #include <net/route.h> 
  91 #include <netinet/in.h> 
  92 #include <netinet/in_var.h> 
  93 #include <netinet/in_systm.h> 
  94 #include <netinet/ip.h> 
  95 #include <netinet/ip_var.h> 
  96 #include <netinet/ip_icmp.h> 
  97 #include <netinet/if_ether.h> 
 100 #include <netinet/ip_dummynet.h> 
 103 #endif /* DUMMYNET */ 
 105 #include <libkern/crypto/md5.h> 
 107 #include <machine/machine_routines.h> 
 109 #include <miscfs/devfs/devfs.h> 
 111 #include <net/pfvar.h> 
 114 #include <net/if_pfsync.h> 
 118 #include <net/if_pflog.h> 
 122 #include <netinet/ip6.h> 
 123 #include <netinet/in_pcb.h> 
 127 #include <net/altq/altq.h> 
 128 #include <net/altq/altq_cbq.h> 
 129 #include <net/classq/classq_red.h> 
 130 #include <net/classq/classq_rio.h> 
 131 #include <net/classq/classq_blue.h> 
 132 #include <net/classq/classq_sfb.h> 
 135 #include <dev/random/randomdev.h> 
 138 static void pfdetach(void); 
 140 static int pfopen(dev_t
, int, int, struct proc 
*); 
 141 static int pfclose(dev_t
, int, int, struct proc 
*); 
 142 static int pfioctl(dev_t
, u_long
, caddr_t
, int, struct proc 
*); 
 143 static int pfioctl_ioc_table(u_long
, struct pfioc_table_32 
*, 
 144     struct pfioc_table_64 
*, struct proc 
*); 
 145 static int pfioctl_ioc_tokens(u_long
, struct pfioc_tokens_32 
*, 
 146     struct pfioc_tokens_64 
*, struct proc 
*); 
 147 static int pfioctl_ioc_rule(u_long
, int, struct pfioc_rule 
*, struct proc 
*); 
 148 static int pfioctl_ioc_state_kill(u_long
, struct pfioc_state_kill 
*, 
 150 static int pfioctl_ioc_state(u_long
, struct pfioc_state 
*, struct proc 
*); 
 151 static int pfioctl_ioc_states(u_long
, struct pfioc_states_32 
*, 
 152     struct pfioc_states_64 
*, struct proc 
*); 
 153 static int pfioctl_ioc_natlook(u_long
, struct pfioc_natlook 
*, struct proc 
*); 
 154 static int pfioctl_ioc_tm(u_long
, struct pfioc_tm 
*, struct proc 
*); 
 155 static int pfioctl_ioc_limit(u_long
, struct pfioc_limit 
*, struct proc 
*); 
 156 static int pfioctl_ioc_pooladdr(u_long
, struct pfioc_pooladdr 
*, struct proc 
*); 
 157 static int pfioctl_ioc_ruleset(u_long
, struct pfioc_ruleset 
*, struct proc 
*); 
 158 static int pfioctl_ioc_trans(u_long
, struct pfioc_trans_32 
*, 
 159     struct pfioc_trans_64 
*, struct proc 
*); 
 160 static int pfioctl_ioc_src_nodes(u_long
, struct pfioc_src_nodes_32 
*, 
 161     struct pfioc_src_nodes_64 
*, struct proc 
*); 
 162 static int pfioctl_ioc_src_node_kill(u_long
, struct pfioc_src_node_kill 
*, 
 164 static int pfioctl_ioc_iface(u_long
, struct pfioc_iface_32 
*, 
 165     struct pfioc_iface_64 
*, struct proc 
*); 
 166 static struct pf_pool 
*pf_get_pool(char *, u_int32_t
, u_int8_t
, u_int32_t
, 
 167     u_int8_t
, u_int8_t
, u_int8_t
); 
 168 static void pf_mv_pool(struct pf_palist 
*, struct pf_palist 
*); 
 169 static void pf_empty_pool(struct pf_palist 
*); 
 171 static int pf_begin_altq(u_int32_t 
*); 
 172 static int pf_rollback_altq(u_int32_t
); 
 173 static int pf_commit_altq(u_int32_t
); 
 174 static int pf_enable_altq(struct pf_altq 
*); 
 175 static int pf_disable_altq(struct pf_altq 
*); 
 176 static void pf_altq_copyin(struct pf_altq 
*, struct pf_altq 
*); 
 177 static void pf_altq_copyout(struct pf_altq 
*, struct pf_altq 
*); 
 179 static int pf_begin_rules(u_int32_t 
*, int, const char *); 
 180 static int pf_rollback_rules(u_int32_t
, int, char *); 
 181 static int pf_setup_pfsync_matching(struct pf_ruleset 
*); 
 182 static void pf_hash_rule(MD5_CTX 
*, struct pf_rule 
*); 
 183 static void pf_hash_rule_addr(MD5_CTX 
*, struct pf_rule_addr 
*, u_int8_t
); 
 184 static int pf_commit_rules(u_int32_t
, int, char *); 
 185 static void pf_rule_copyin(struct pf_rule 
*, struct pf_rule 
*, struct proc 
*, 
 187 static void pf_rule_copyout(struct pf_rule 
*, struct pf_rule 
*); 
 188 static void pf_state_export(struct pfsync_state 
*, struct pf_state_key 
*, 
 190 static void pf_state_import(struct pfsync_state 
*, struct pf_state_key 
*, 
 192 static void pf_pooladdr_copyin(struct pf_pooladdr 
*, struct pf_pooladdr 
*); 
 193 static void pf_pooladdr_copyout(struct pf_pooladdr 
*, struct pf_pooladdr 
*); 
 194 static void pf_expire_states_and_src_nodes(struct pf_rule 
*); 
 195 static void pf_delete_rule_from_ruleset(struct pf_ruleset 
*, 
 196     int, struct pf_rule 
*); 
 197 static void pf_addrwrap_setup(struct pf_addr_wrap 
*); 
 198 static int pf_rule_setup(struct pfioc_rule 
*, struct pf_rule 
*, 
 199     struct pf_ruleset 
*); 
 200 static void pf_delete_rule_by_owner(char *, u_int32_t
); 
 201 static int pf_delete_rule_by_ticket(struct pfioc_rule 
*, u_int32_t
); 
 202 static void pf_ruleset_cleanup(struct pf_ruleset 
*, int); 
 203 static void pf_deleterule_anchor_step_out(struct pf_ruleset 
**, 
 204     int, struct pf_rule 
**); 
 206 #define PF_CDEV_MAJOR   (-1) 
 208 static struct cdevsw pf_cdevsw 
= { 
 211         /* read */      eno_rdwrt
, 
 212         /* write */     eno_rdwrt
, 
 215         /* reset */     eno_reset
, 
 217         /* select */    eno_select
, 
 219         /* strategy */  eno_strat
, 
 225 static void pf_attach_hooks(void); 
 227 /* currently unused along with pfdetach() */ 
 228 static void pf_detach_hooks(void); 
 232  * This is set during DIOCSTART/DIOCSTOP with pf_perim_lock held as writer, 
 233  * and used in pf_af_hook() for performance optimization, such that packets 
 234  * will enter pf_test() or pf_test6() only when PF is running. 
 236 int pf_is_enabled 
= 0; 
 239 u_int32_t altq_allowed 
= 0; 
 242 u_int32_t pf_hash_seed
; 
 245  * These are the pf enabled reference counting variables 
 247 static u_int64_t pf_enabled_ref_count
; 
 248 static u_int32_t nr_tokens 
= 0; 
 249 static u_int64_t pffwrules
; 
 250 static u_int32_t pfdevcnt
; 
 252 SLIST_HEAD(list_head
, pfioc_kernel_token
); 
 253 static struct list_head token_list_head
; 
 255 struct pf_rule           pf_default_rule
; 
 257 static int               pf_altq_running
; 
 260 #define TAGID_MAX        50000 
 262 static TAILQ_HEAD(pf_tags
, pf_tagname
)  pf_tags 
= 
 263     TAILQ_HEAD_INITIALIZER(pf_tags
); 
 265 static TAILQ_HEAD(pf_tags
, pf_tagname
) 
 266     pf_tags 
= TAILQ_HEAD_INITIALIZER(pf_tags
), 
 267     pf_qids 
= TAILQ_HEAD_INITIALIZER(pf_qids
); 
 270 #if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE) 
 271 #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE 
 273 static u_int16_t         
tagname2tag(struct pf_tags 
*, char *); 
 274 static void              tag2tagname(struct pf_tags 
*, u_int16_t
, char *); 
 275 static void              tag_unref(struct pf_tags 
*, u_int16_t
); 
 276 static int               pf_rtlabel_add(struct pf_addr_wrap 
*); 
 277 static void              pf_rtlabel_remove(struct pf_addr_wrap 
*); 
 278 static void              pf_rtlabel_copyout(struct pf_addr_wrap 
*); 
 281 static int pf_inet_hook(struct ifnet 
*, struct mbuf 
**, int, 
 282     struct ip_fw_args 
*); 
 285 static int pf_inet6_hook(struct ifnet 
*, struct mbuf 
**, int, 
 286     struct ip_fw_args 
*); 
 289 #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x 
 292  * Helper macros for ioctl structures which vary in size (32-bit vs. 64-bit) 
 294 #define PFIOCX_STRUCT_DECL(s)                                           \ 
 297                 struct s##_32   _s##_32;                                \ 
 298                 struct s##_64   _s##_64;                                \ 
 302 #define PFIOCX_STRUCT_BEGIN(a, s, _action) {                            \ 
 303         VERIFY(s##_un == NULL);                                         \ 
 304         s##_un = _MALLOC(sizeof (*s##_un), M_TEMP, M_WAITOK|M_ZERO);    \ 
 305         if (s##_un == NULL) {                                           \ 
 309                         bcopy(a, &s##_un->_u._s##_64,                   \ 
 310                             sizeof (struct s##_64));                    \ 
 312                         bcopy(a, &s##_un->_u._s##_32,                   \ 
 313                             sizeof (struct s##_32));                    \ 
 317 #define PFIOCX_STRUCT_END(s, a) {                                       \ 
 318         VERIFY(s##_un != NULL);                                         \ 
 320                 bcopy(&s##_un->_u._s##_64, a, sizeof (struct s##_64));  \ 
 322                 bcopy(&s##_un->_u._s##_32, a, sizeof (struct s##_32));  \ 
 323         _FREE(s##_un, M_TEMP);                                          \ 
 327 #define PFIOCX_STRUCT_ADDR32(s)         (&s##_un->_u._s##_32) 
 328 #define PFIOCX_STRUCT_ADDR64(s)         (&s##_un->_u._s##_64) 
 331  * Helper macros for regular ioctl structures. 
 333 #define PFIOC_STRUCT_BEGIN(a, v, _action) {                             \ 
 334         VERIFY((v) == NULL);                                            \ 
 335         (v) = _MALLOC(sizeof (*(v)), M_TEMP, M_WAITOK|M_ZERO);          \ 
 339                 bcopy(a, v, sizeof (*(v)));                             \ 
 343 #define PFIOC_STRUCT_END(v, a) {                                        \ 
 344         VERIFY((v) != NULL);                                            \ 
 345         bcopy(v, a, sizeof (*(v)));                                     \ 
 350 #define PFIOC_STRUCT_ADDR32(s)          (&s##_un->_u._s##_32) 
 351 #define PFIOC_STRUCT_ADDR64(s)          (&s##_un->_u._s##_64) 
 353 static lck_attr_t 
*pf_perim_lock_attr
; 
 354 static lck_grp_t 
*pf_perim_lock_grp
; 
 355 static lck_grp_attr_t 
*pf_perim_lock_grp_attr
; 
 357 static lck_attr_t 
*pf_lock_attr
; 
 358 static lck_grp_t 
*pf_lock_grp
; 
 359 static lck_grp_attr_t 
*pf_lock_grp_attr
; 
 361 struct thread 
*pf_purge_thread
; 
 363 extern void pfi_kifaddr_update(void *); 
 365 /* pf enable ref-counting helper functions */ 
 366 static u_int64_t                
generate_token(struct proc 
*); 
 367 static int                      remove_token(struct pfioc_remove_token 
*); 
 368 static void                     invalidate_all_tokens(void); 
 371 generate_token(struct proc 
*p
) 
 373         u_int64_t token_value
; 
 374         struct pfioc_kernel_token 
*new_token
; 
 376         new_token 
= _MALLOC(sizeof (struct pfioc_kernel_token
), M_TEMP
, 
 379         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
 381         if (new_token 
== NULL
) { 
 382                 /* malloc failed! bail! */ 
 383                 printf("%s: unable to allocate pf token structure!", __func__
); 
 387         token_value 
= VM_KERNEL_ADDRPERM((u_int64_t
)(uintptr_t)new_token
); 
 389         new_token
->token
.token_value 
= token_value
; 
 390         new_token
->token
.pid 
= proc_pid(p
); 
 391         proc_name(new_token
->token
.pid
, new_token
->token
.proc_name
, 
 392             sizeof (new_token
->token
.proc_name
)); 
 393         new_token
->token
.timestamp 
= pf_calendar_time_second(); 
 395         SLIST_INSERT_HEAD(&token_list_head
, new_token
, next
); 
 398         return (token_value
); 
 402 remove_token(struct pfioc_remove_token 
*tok
) 
 404         struct pfioc_kernel_token 
*entry
, *tmp
; 
 406         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
 408         SLIST_FOREACH_SAFE(entry
, &token_list_head
, next
, tmp
) { 
 409                 if (tok
->token_value 
== entry
->token
.token_value
) { 
 410                         SLIST_REMOVE(&token_list_head
, entry
, 
 411                             pfioc_kernel_token
, next
); 
 412                         _FREE(entry
, M_TEMP
); 
 414                         return (0);    /* success */ 
 418         printf("pf : remove failure\n"); 
 419         return (ESRCH
);    /* failure */ 
 423 invalidate_all_tokens(void) 
 425         struct pfioc_kernel_token 
*entry
, *tmp
; 
 427         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
 429         SLIST_FOREACH_SAFE(entry
, &token_list_head
, next
, tmp
) { 
 430                 SLIST_REMOVE(&token_list_head
, entry
, pfioc_kernel_token
, next
); 
 431                 _FREE(entry
, M_TEMP
); 
 440         u_int32_t 
*t 
= pf_default_rule
.timeout
; 
 443         pf_perim_lock_grp_attr 
= lck_grp_attr_alloc_init(); 
 444         pf_perim_lock_grp 
= lck_grp_alloc_init("pf_perim", 
 445             pf_perim_lock_grp_attr
); 
 446         pf_perim_lock_attr 
= lck_attr_alloc_init(); 
 447         lck_rw_init(pf_perim_lock
, pf_perim_lock_grp
, pf_perim_lock_attr
); 
 449         pf_lock_grp_attr 
= lck_grp_attr_alloc_init(); 
 450         pf_lock_grp 
= lck_grp_alloc_init("pf", pf_lock_grp_attr
); 
 451         pf_lock_attr 
= lck_attr_alloc_init(); 
 452         lck_mtx_init(pf_lock
, pf_lock_grp
, pf_lock_attr
); 
 454         pool_init(&pf_rule_pl
, sizeof (struct pf_rule
), 0, 0, 0, "pfrulepl", 
 456         pool_init(&pf_src_tree_pl
, sizeof (struct pf_src_node
), 0, 0, 0, 
 458         pool_init(&pf_state_pl
, sizeof (struct pf_state
), 0, 0, 0, "pfstatepl", 
 460         pool_init(&pf_state_key_pl
, sizeof (struct pf_state_key
), 0, 0, 0, 
 461             "pfstatekeypl", NULL
); 
 462         pool_init(&pf_app_state_pl
, sizeof (struct pf_app_state
), 0, 0, 0, 
 463             "pfappstatepl", NULL
); 
 465         pool_init(&pf_altq_pl
, sizeof (struct pf_altq
), 0, 0, 0, "pfaltqpl", 
 468         pool_init(&pf_pooladdr_pl
, sizeof (struct pf_pooladdr
), 0, 0, 0, 
 469             "pfpooladdrpl", NULL
); 
 472         pf_osfp_initialize(); 
 474         pool_sethardlimit(pf_pool_limits
[PF_LIMIT_STATES
].pp
, 
 475             pf_pool_limits
[PF_LIMIT_STATES
].limit
, NULL
, 0); 
 477         if (max_mem 
<= 256*1024*1024) 
 478                 pf_pool_limits
[PF_LIMIT_TABLE_ENTRIES
].limit 
= 
 479                     PFR_KENTRY_HIWAT_SMALL
; 
 481         RB_INIT(&tree_src_tracking
); 
 482         RB_INIT(&pf_anchors
); 
 483         pf_init_ruleset(&pf_main_ruleset
); 
 484         TAILQ_INIT(&pf_pabuf
); 
 485         TAILQ_INIT(&state_list
); 
 487         TAILQ_INIT(&pf_altqs
[0]); 
 488         TAILQ_INIT(&pf_altqs
[1]); 
 489         pf_altqs_active 
= &pf_altqs
[0]; 
 490         pf_altqs_inactive 
= &pf_altqs
[1]; 
 492         PE_parse_boot_argn("altq", &altq_allowed
, sizeof (altq_allowed
)); 
 494         _CASSERT(ALTRQ_PURGE 
== CLASSQRQ_PURGE
); 
 495         _CASSERT(ALTRQ_PURGE_SC 
== CLASSQRQ_PURGE_SC
); 
 496         _CASSERT(ALTRQ_EVENT 
== CLASSQRQ_EVENT
); 
 498         _CASSERT(ALTDQ_REMOVE 
== CLASSQDQ_REMOVE
); 
 499         _CASSERT(ALTDQ_POLL 
== CLASSQDQ_POLL
); 
 502         _CASSERT((SC_BE 
& SCIDX_MASK
) == SCIDX_BE
); 
 503         _CASSERT((SC_BK_SYS 
& SCIDX_MASK
) == SCIDX_BK_SYS
); 
 504         _CASSERT((SC_BK 
& SCIDX_MASK
) == SCIDX_BK
); 
 505         _CASSERT((SC_RD 
& SCIDX_MASK
) == SCIDX_RD
); 
 506         _CASSERT((SC_OAM 
& SCIDX_MASK
) == SCIDX_OAM
); 
 507         _CASSERT((SC_AV 
& SCIDX_MASK
) == SCIDX_AV
); 
 508         _CASSERT((SC_RV 
& SCIDX_MASK
) == SCIDX_RV
); 
 509         _CASSERT((SC_VI 
& SCIDX_MASK
) == SCIDX_VI
); 
 510         _CASSERT((SC_VO 
& SCIDX_MASK
) == SCIDX_VO
); 
 511         _CASSERT((SC_CTL 
& SCIDX_MASK
) == SCIDX_CTL
); 
 513         /* default rule should never be garbage collected */ 
 514         pf_default_rule
.entries
.tqe_prev 
= &pf_default_rule
.entries
.tqe_next
; 
 515         pf_default_rule
.action 
= PF_PASS
; 
 516         pf_default_rule
.nr 
= -1; 
 517         pf_default_rule
.rtableid 
= IFSCOPE_NONE
; 
 519         /* initialize default timeouts */ 
 520         t
[PFTM_TCP_FIRST_PACKET
] = PFTM_TCP_FIRST_PACKET_VAL
; 
 521         t
[PFTM_TCP_OPENING
] = PFTM_TCP_OPENING_VAL
; 
 522         t
[PFTM_TCP_ESTABLISHED
] = PFTM_TCP_ESTABLISHED_VAL
; 
 523         t
[PFTM_TCP_CLOSING
] = PFTM_TCP_CLOSING_VAL
; 
 524         t
[PFTM_TCP_FIN_WAIT
] = PFTM_TCP_FIN_WAIT_VAL
; 
 525         t
[PFTM_TCP_CLOSED
] = PFTM_TCP_CLOSED_VAL
; 
 526         t
[PFTM_UDP_FIRST_PACKET
] = PFTM_UDP_FIRST_PACKET_VAL
; 
 527         t
[PFTM_UDP_SINGLE
] = PFTM_UDP_SINGLE_VAL
; 
 528         t
[PFTM_UDP_MULTIPLE
] = PFTM_UDP_MULTIPLE_VAL
; 
 529         t
[PFTM_ICMP_FIRST_PACKET
] = PFTM_ICMP_FIRST_PACKET_VAL
; 
 530         t
[PFTM_ICMP_ERROR_REPLY
] = PFTM_ICMP_ERROR_REPLY_VAL
; 
 531         t
[PFTM_GREv1_FIRST_PACKET
] = PFTM_GREv1_FIRST_PACKET_VAL
; 
 532         t
[PFTM_GREv1_INITIATING
] = PFTM_GREv1_INITIATING_VAL
; 
 533         t
[PFTM_GREv1_ESTABLISHED
] = PFTM_GREv1_ESTABLISHED_VAL
; 
 534         t
[PFTM_ESP_FIRST_PACKET
] = PFTM_ESP_FIRST_PACKET_VAL
; 
 535         t
[PFTM_ESP_INITIATING
] = PFTM_ESP_INITIATING_VAL
; 
 536         t
[PFTM_ESP_ESTABLISHED
] = PFTM_ESP_ESTABLISHED_VAL
; 
 537         t
[PFTM_OTHER_FIRST_PACKET
] = PFTM_OTHER_FIRST_PACKET_VAL
; 
 538         t
[PFTM_OTHER_SINGLE
] = PFTM_OTHER_SINGLE_VAL
; 
 539         t
[PFTM_OTHER_MULTIPLE
] = PFTM_OTHER_MULTIPLE_VAL
; 
 540         t
[PFTM_FRAG
] = PFTM_FRAG_VAL
; 
 541         t
[PFTM_INTERVAL
] = PFTM_INTERVAL_VAL
; 
 542         t
[PFTM_SRC_NODE
] = PFTM_SRC_NODE_VAL
; 
 543         t
[PFTM_TS_DIFF
] = PFTM_TS_DIFF_VAL
; 
 544         t
[PFTM_ADAPTIVE_START
] = PFSTATE_ADAPT_START
; 
 545         t
[PFTM_ADAPTIVE_END
] = PFSTATE_ADAPT_END
; 
 548         bzero(&pf_status
, sizeof (pf_status
)); 
 549         pf_status
.debug 
= PF_DEBUG_URGENT
; 
 550         pf_hash_seed 
= RandomULong(); 
 552         /* XXX do our best to avoid a conflict */ 
 553         pf_status
.hostid 
= random(); 
 555         if (kernel_thread_start(pf_purge_thread_fn
, NULL
, 
 556             &pf_purge_thread
) != 0) { 
 557                 printf("%s: unable to start purge thread!", __func__
); 
 561         maj 
= cdevsw_add(PF_CDEV_MAJOR
, &pf_cdevsw
); 
 563                 printf("%s: failed to allocate major number!\n", __func__
); 
 566         (void) devfs_make_node(makedev(maj
, PFDEV_PF
), DEVFS_CHAR
, 
 567             UID_ROOT
, GID_WHEEL
, 0600, "pf", 0); 
 569         (void) devfs_make_node(makedev(maj
, PFDEV_PFM
), DEVFS_CHAR
, 
 570             UID_ROOT
, GID_WHEEL
, 0600, "pfm", 0); 
 579         struct pf_anchor        
*anchor
; 
 580         struct pf_state         
*state
; 
 581         struct pf_src_node      
*node
; 
 582         struct pfioc_table      pt
; 
 589         pf_status
.running 
= 0; 
 590         wakeup(pf_purge_thread_fn
); 
 592         /* clear the rulesets */ 
 593         for (i 
= 0; i 
< PF_RULESET_MAX
; i
++) 
 594                 if (pf_begin_rules(&ticket
, i
, &r
) == 0) 
 595                                 pf_commit_rules(ticket
, i
, &r
); 
 597         if (pf_begin_altq(&ticket
) == 0) 
 598                 pf_commit_altq(ticket
); 
 602         RB_FOREACH(state
, pf_state_tree_id
, &tree_id
) { 
 603                 state
->timeout 
= PFTM_PURGE
; 
 605                 state
->sync_flags 
= PFSTATE_NOSYNC
; 
 608         pf_purge_expired_states(pf_status
.states
); 
 611         pfsync_clear_states(pf_status
.hostid
, NULL
); 
 614         /* clear source nodes */ 
 615         RB_FOREACH(state
, pf_state_tree_id
, &tree_id
) { 
 616                 state
->src_node 
= NULL
; 
 617                 state
->nat_src_node 
= NULL
; 
 619         RB_FOREACH(node
, pf_src_tree
, &tree_src_tracking
) { 
 623         pf_purge_expired_src_nodes(); 
 626         memset(&pt
, '\0', sizeof (pt
)); 
 627         pfr_clr_tables(&pt
.pfrio_table
, &pt
.pfrio_ndel
, pt
.pfrio_flags
); 
 629         /* destroy anchors */ 
 630         while ((anchor 
= RB_MIN(pf_anchor_global
, &pf_anchors
)) != NULL
) { 
 631                 for (i 
= 0; i 
< PF_RULESET_MAX
; i
++) 
 632                         if (pf_begin_rules(&ticket
, i
, anchor
->name
) == 0) 
 633                                 pf_commit_rules(ticket
, i
, anchor
->name
); 
 636         /* destroy main ruleset */ 
 637         pf_remove_if_empty_ruleset(&pf_main_ruleset
); 
 639         /* destroy the pools */ 
 640         pool_destroy(&pf_pooladdr_pl
); 
 642         pool_destroy(&pf_altq_pl
); 
 644         pool_destroy(&pf_state_pl
); 
 645         pool_destroy(&pf_rule_pl
); 
 646         pool_destroy(&pf_src_tree_pl
); 
 648         /* destroy subsystems */ 
 649         pf_normalize_destroy(); 
 657 pfopen(dev_t dev
, int flags
, int fmt
, struct proc 
*p
) 
 659 #pragma unused(flags, fmt, p) 
 660         if (minor(dev
) >= PFDEV_MAX
) 
 663         if (minor(dev
) == PFDEV_PFM
) { 
 664                 lck_mtx_lock(pf_lock
); 
 666                         lck_mtx_unlock(pf_lock
); 
 670                 lck_mtx_unlock(pf_lock
); 
 676 pfclose(dev_t dev
, int flags
, int fmt
, struct proc 
*p
) 
 678 #pragma unused(flags, fmt, p) 
 679         if (minor(dev
) >= PFDEV_MAX
) 
 682         if (minor(dev
) == PFDEV_PFM
) { 
 683                 lck_mtx_lock(pf_lock
); 
 684                 VERIFY(pfdevcnt 
> 0); 
 686                 lck_mtx_unlock(pf_lock
); 
 691 static struct pf_pool 
* 
 692 pf_get_pool(char *anchor
, u_int32_t ticket
, u_int8_t rule_action
, 
 693     u_int32_t rule_number
, u_int8_t r_last
, u_int8_t active
, 
 694     u_int8_t check_ticket
) 
 696         struct pf_ruleset       
*ruleset
; 
 697         struct pf_rule          
*rule
; 
 700         ruleset 
= pf_find_ruleset(anchor
); 
 703         rs_num 
= pf_get_ruleset_number(rule_action
); 
 704         if (rs_num 
>= PF_RULESET_MAX
) 
 707                 if (check_ticket 
&& ticket 
!= 
 708                     ruleset
->rules
[rs_num
].active
.ticket
) 
 711                         rule 
= TAILQ_LAST(ruleset
->rules
[rs_num
].active
.ptr
, 
 714                         rule 
= TAILQ_FIRST(ruleset
->rules
[rs_num
].active
.ptr
); 
 716                 if (check_ticket 
&& ticket 
!= 
 717                     ruleset
->rules
[rs_num
].inactive
.ticket
) 
 720                         rule 
= TAILQ_LAST(ruleset
->rules
[rs_num
].inactive
.ptr
, 
 723                         rule 
= TAILQ_FIRST(ruleset
->rules
[rs_num
].inactive
.ptr
); 
 726                 while ((rule 
!= NULL
) && (rule
->nr 
!= rule_number
)) 
 727                         rule 
= TAILQ_NEXT(rule
, entries
); 
 732         return (&rule
->rpool
); 
 736 pf_mv_pool(struct pf_palist 
*poola
, struct pf_palist 
*poolb
) 
 738         struct pf_pooladdr      
*mv_pool_pa
; 
 740         while ((mv_pool_pa 
= TAILQ_FIRST(poola
)) != NULL
) { 
 741                 TAILQ_REMOVE(poola
, mv_pool_pa
, entries
); 
 742                 TAILQ_INSERT_TAIL(poolb
, mv_pool_pa
, entries
); 
 747 pf_empty_pool(struct pf_palist 
*poola
) 
 749         struct pf_pooladdr      
*empty_pool_pa
; 
 751         while ((empty_pool_pa 
= TAILQ_FIRST(poola
)) != NULL
) { 
 752                 pfi_dynaddr_remove(&empty_pool_pa
->addr
); 
 753                 pf_tbladdr_remove(&empty_pool_pa
->addr
); 
 754                 pfi_kif_unref(empty_pool_pa
->kif
, PFI_KIF_REF_RULE
); 
 755                 TAILQ_REMOVE(poola
, empty_pool_pa
, entries
); 
 756                 pool_put(&pf_pooladdr_pl
, empty_pool_pa
); 
 761 pf_rm_rule(struct pf_rulequeue 
*rulequeue
, struct pf_rule 
*rule
) 
 763         if (rulequeue 
!= NULL
) { 
 764                 if (rule
->states 
<= 0) { 
 766                          * XXX - we need to remove the table *before* detaching 
 767                          * the rule to make sure the table code does not delete 
 768                          * the anchor under our feet. 
 770                         pf_tbladdr_remove(&rule
->src
.addr
); 
 771                         pf_tbladdr_remove(&rule
->dst
.addr
); 
 772                         if (rule
->overload_tbl
) 
 773                                 pfr_detach_table(rule
->overload_tbl
); 
 775                 TAILQ_REMOVE(rulequeue
, rule
, entries
); 
 776                 rule
->entries
.tqe_prev 
= NULL
; 
 780         if (rule
->states 
> 0 || rule
->src_nodes 
> 0 || 
 781             rule
->entries
.tqe_prev 
!= NULL
) 
 783         pf_tag_unref(rule
->tag
); 
 784         pf_tag_unref(rule
->match_tag
); 
 787                 if (rule
->pqid 
!= rule
->qid
) 
 788                         pf_qid_unref(rule
->pqid
); 
 789                 pf_qid_unref(rule
->qid
); 
 792         pf_rtlabel_remove(&rule
->src
.addr
); 
 793         pf_rtlabel_remove(&rule
->dst
.addr
); 
 794         pfi_dynaddr_remove(&rule
->src
.addr
); 
 795         pfi_dynaddr_remove(&rule
->dst
.addr
); 
 796         if (rulequeue 
== NULL
) { 
 797                 pf_tbladdr_remove(&rule
->src
.addr
); 
 798                 pf_tbladdr_remove(&rule
->dst
.addr
); 
 799                 if (rule
->overload_tbl
) 
 800                         pfr_detach_table(rule
->overload_tbl
); 
 802         pfi_kif_unref(rule
->kif
, PFI_KIF_REF_RULE
); 
 803         pf_anchor_remove(rule
); 
 804         pf_empty_pool(&rule
->rpool
.list
); 
 805         pool_put(&pf_rule_pl
, rule
); 
 809 tagname2tag(struct pf_tags 
*head
, char *tagname
) 
 811         struct pf_tagname       
*tag
, *p 
= NULL
; 
 812         u_int16_t                new_tagid 
= 1; 
 814         TAILQ_FOREACH(tag
, head
, entries
) 
 815                 if (strcmp(tagname
, tag
->name
) == 0) { 
 821          * to avoid fragmentation, we do a linear search from the beginning 
 822          * and take the first free slot we find. if there is none or the list 
 823          * is empty, append a new entry at the end. 
 827         if (!TAILQ_EMPTY(head
)) 
 828                 for (p 
= TAILQ_FIRST(head
); p 
!= NULL 
&& 
 829                     p
->tag 
== new_tagid
; p 
= TAILQ_NEXT(p
, entries
)) 
 830                         new_tagid 
= p
->tag 
+ 1; 
 832         if (new_tagid 
> TAGID_MAX
) 
 835         /* allocate and fill new struct pf_tagname */ 
 836         tag 
= _MALLOC(sizeof (*tag
), M_TEMP
, M_WAITOK
|M_ZERO
); 
 839         strlcpy(tag
->name
, tagname
, sizeof (tag
->name
)); 
 840         tag
->tag 
= new_tagid
; 
 843         if (p 
!= NULL
)  /* insert new entry before p */ 
 844                 TAILQ_INSERT_BEFORE(p
, tag
, entries
); 
 845         else    /* either list empty or no free slot in between */ 
 846                 TAILQ_INSERT_TAIL(head
, tag
, entries
); 
 852 tag2tagname(struct pf_tags 
*head
, u_int16_t tagid
, char *p
) 
 854         struct pf_tagname       
*tag
; 
 856         TAILQ_FOREACH(tag
, head
, entries
) 
 857                 if (tag
->tag 
== tagid
) { 
 858                         strlcpy(p
, tag
->name
, PF_TAG_NAME_SIZE
); 
 864 tag_unref(struct pf_tags 
*head
, u_int16_t tag
) 
 866         struct pf_tagname       
*p
, *next
; 
 871         for (p 
= TAILQ_FIRST(head
); p 
!= NULL
; p 
= next
) { 
 872                 next 
= TAILQ_NEXT(p
, entries
); 
 875                                 TAILQ_REMOVE(head
, p
, entries
); 
 884 pf_tagname2tag(char *tagname
) 
 886         return (tagname2tag(&pf_tags
, tagname
)); 
 890 pf_tag2tagname(u_int16_t tagid
, char *p
) 
 892         tag2tagname(&pf_tags
, tagid
, p
); 
 896 pf_tag_ref(u_int16_t tag
) 
 898         struct pf_tagname 
*t
; 
 900         TAILQ_FOREACH(t
, &pf_tags
, entries
) 
 908 pf_tag_unref(u_int16_t tag
) 
 910         tag_unref(&pf_tags
, tag
); 
 914 pf_rtlabel_add(struct pf_addr_wrap 
*a
) 
 921 pf_rtlabel_remove(struct pf_addr_wrap 
*a
) 
 927 pf_rtlabel_copyout(struct pf_addr_wrap 
*a
) 
 934 pf_qname2qid(char *qname
) 
 936         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
 938         return ((u_int32_t
)tagname2tag(&pf_qids
, qname
)); 
 942 pf_qid2qname(u_int32_t qid
, char *p
) 
 944         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
 946         tag2tagname(&pf_qids
, (u_int16_t
)qid
, p
); 
 950 pf_qid_unref(u_int32_t qid
) 
 952         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
 954         tag_unref(&pf_qids
, (u_int16_t
)qid
); 
 958 pf_begin_altq(u_int32_t 
*ticket
) 
 960         struct pf_altq  
*altq
; 
 963         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
 965         /* Purge the old altq list */ 
 966         while ((altq 
= TAILQ_FIRST(pf_altqs_inactive
)) != NULL
) { 
 967                 TAILQ_REMOVE(pf_altqs_inactive
, altq
, entries
); 
 968                 if (altq
->qname
[0] == '\0') { 
 969                         /* detach and destroy the discipline */ 
 970                         error 
= altq_remove(altq
); 
 972                         pf_qid_unref(altq
->qid
); 
 973                 pool_put(&pf_altq_pl
, altq
); 
 977         *ticket 
= ++ticket_altqs_inactive
; 
 978         altqs_inactive_open 
= 1; 
 983 pf_rollback_altq(u_int32_t ticket
) 
 985         struct pf_altq  
*altq
; 
 988         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
 990         if (!altqs_inactive_open 
|| ticket 
!= ticket_altqs_inactive
) 
 992         /* Purge the old altq list */ 
 993         while ((altq 
= TAILQ_FIRST(pf_altqs_inactive
)) != NULL
) { 
 994                 TAILQ_REMOVE(pf_altqs_inactive
, altq
, entries
); 
 995                 if (altq
->qname
[0] == '\0') { 
 996                         /* detach and destroy the discipline */ 
 997                         error 
= altq_remove(altq
); 
 999                         pf_qid_unref(altq
->qid
); 
1000                 pool_put(&pf_altq_pl
, altq
); 
1002         altqs_inactive_open 
= 0; 
1007 pf_commit_altq(u_int32_t ticket
) 
1009         struct pf_altqqueue     
*old_altqs
; 
1010         struct pf_altq          
*altq
; 
1013         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
1015         if (!altqs_inactive_open 
|| ticket 
!= ticket_altqs_inactive
) 
1018         /* swap altqs, keep the old. */ 
1019         old_altqs 
= pf_altqs_active
; 
1020         pf_altqs_active 
= pf_altqs_inactive
; 
1021         pf_altqs_inactive 
= old_altqs
; 
1022         ticket_altqs_active 
= ticket_altqs_inactive
; 
1024         /* Attach new disciplines */ 
1025         TAILQ_FOREACH(altq
, pf_altqs_active
, entries
) { 
1026                 if (altq
->qname
[0] == '\0') { 
1027                         /* attach the discipline */ 
1028                         error 
= altq_pfattach(altq
); 
1029                         if (error 
== 0 && pf_altq_running
) 
1030                                 error 
= pf_enable_altq(altq
); 
1037         /* Purge the old altq list */ 
1038         while ((altq 
= TAILQ_FIRST(pf_altqs_inactive
)) != NULL
) { 
1039                 TAILQ_REMOVE(pf_altqs_inactive
, altq
, entries
); 
1040                 if (altq
->qname
[0] == '\0') { 
1041                         /* detach and destroy the discipline */ 
1042                         if (pf_altq_running
) 
1043                                 error 
= pf_disable_altq(altq
); 
1044                         err 
= altq_pfdetach(altq
); 
1045                         if (err 
!= 0 && error 
== 0) 
1047                         err 
= altq_remove(altq
); 
1048                         if (err 
!= 0 && error 
== 0) 
1051                         pf_qid_unref(altq
->qid
); 
1052                 pool_put(&pf_altq_pl
, altq
); 
1055         altqs_inactive_open 
= 0; 
1060 pf_enable_altq(struct pf_altq 
*altq
) 
1063         struct ifclassq         
*ifq
; 
1066         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
1068         if ((ifp 
= ifunit(altq
->ifname
)) == NULL
) 
1073         if (IFCQ_ALTQ(ifq
)->altq_type 
!= ALTQT_NONE
) 
1074                 error 
= altq_enable(IFCQ_ALTQ(ifq
)); 
1076         /* set or clear tokenbucket regulator */ 
1077         if (error 
== 0 && ifp 
!= NULL 
&& ALTQ_IS_ENABLED(IFCQ_ALTQ(ifq
))) { 
1078                 struct tb_profile tb 
= { 0, 0, 0 }; 
1080                 if (altq
->aflags 
& PF_ALTQF_TBR
) { 
1081                         if (altq
->bwtype 
!= PF_ALTQ_BW_ABSOLUTE 
&& 
1082                             altq
->bwtype 
!= PF_ALTQ_BW_PERCENT
) { 
1085                                 if (altq
->bwtype 
== PF_ALTQ_BW_ABSOLUTE
) 
1086                                         tb
.rate 
= altq
->ifbandwidth
; 
1088                                         tb
.percent 
= altq
->ifbandwidth
; 
1089                                 tb
.depth 
= altq
->tbrsize
; 
1090                                 error 
= ifclassq_tbr_set(ifq
, &tb
, TRUE
); 
1092                 } else if (IFCQ_TBR_IS_ENABLED(ifq
)) { 
1093                         error 
= ifclassq_tbr_set(ifq
, &tb
, TRUE
); 
1102 pf_disable_altq(struct pf_altq 
*altq
) 
1105         struct ifclassq         
*ifq
; 
1108         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
1110         if ((ifp 
= ifunit(altq
->ifname
)) == NULL
) 
1114          * when the discipline is no longer referenced, it was overridden 
1115          * by a new one.  if so, just return. 
1119         if (altq
->altq_disc 
!= IFCQ_ALTQ(ifq
)->altq_disc
) { 
1124         error 
= altq_disable(IFCQ_ALTQ(ifq
)); 
1126         if (error 
== 0 && IFCQ_TBR_IS_ENABLED(ifq
)) { 
1127                 /* clear tokenbucket regulator */ 
1128                 struct tb_profile  tb 
= { 0, 0, 0 }; 
1129                 error 
= ifclassq_tbr_set(ifq
, &tb
, TRUE
); 
1137 pf_altq_copyin(struct pf_altq 
*src
, struct pf_altq 
*dst
) 
1139         bcopy(src
, dst
, sizeof (struct pf_altq
)); 
1141         dst
->ifname
[sizeof (dst
->ifname
) - 1] = '\0'; 
1142         dst
->qname
[sizeof (dst
->qname
) - 1] = '\0'; 
1143         dst
->parent
[sizeof (dst
->parent
) - 1] = '\0'; 
1144         dst
->altq_disc 
= NULL
; 
1145         dst
->entries
.tqe_next 
= NULL
; 
1146         dst
->entries
.tqe_prev 
= NULL
; 
1150 pf_altq_copyout(struct pf_altq 
*src
, struct pf_altq 
*dst
) 
1154         bcopy(src
, &pa
, sizeof (struct pf_altq
)); 
1155         pa
.altq_disc 
= NULL
; 
1156         pa
.entries
.tqe_next 
= NULL
; 
1157         pa
.entries
.tqe_prev 
= NULL
; 
1158         bcopy(&pa
, dst
, sizeof (struct pf_altq
)); 
1160 #endif /* PF_ALTQ */ 
1163 pf_begin_rules(u_int32_t 
*ticket
, int rs_num
, const char *anchor
) 
1165         struct pf_ruleset       
*rs
; 
1166         struct pf_rule          
*rule
; 
1168         if (rs_num 
< 0 || rs_num 
>= PF_RULESET_MAX
) 
1170         rs 
= pf_find_or_create_ruleset(anchor
); 
1173         while ((rule 
= TAILQ_FIRST(rs
->rules
[rs_num
].inactive
.ptr
)) != NULL
) { 
1174                 pf_rm_rule(rs
->rules
[rs_num
].inactive
.ptr
, rule
); 
1175                 rs
->rules
[rs_num
].inactive
.rcount
--; 
1177         *ticket 
= ++rs
->rules
[rs_num
].inactive
.ticket
; 
1178         rs
->rules
[rs_num
].inactive
.open 
= 1; 
1183 pf_rollback_rules(u_int32_t ticket
, int rs_num
, char *anchor
) 
1185         struct pf_ruleset       
*rs
; 
1186         struct pf_rule          
*rule
; 
1188         if (rs_num 
< 0 || rs_num 
>= PF_RULESET_MAX
) 
1190         rs 
= pf_find_ruleset(anchor
); 
1191         if (rs 
== NULL 
|| !rs
->rules
[rs_num
].inactive
.open 
|| 
1192             rs
->rules
[rs_num
].inactive
.ticket 
!= ticket
) 
1194         while ((rule 
= TAILQ_FIRST(rs
->rules
[rs_num
].inactive
.ptr
)) != NULL
) { 
1195                 pf_rm_rule(rs
->rules
[rs_num
].inactive
.ptr
, rule
); 
1196                 rs
->rules
[rs_num
].inactive
.rcount
--; 
1198         rs
->rules
[rs_num
].inactive
.open 
= 0; 
1202 #define PF_MD5_UPD(st, elm)                                             \ 
1203         MD5Update(ctx, (u_int8_t *)&(st)->elm, sizeof ((st)->elm)) 
1205 #define PF_MD5_UPD_STR(st, elm)                                         \ 
1206         MD5Update(ctx, (u_int8_t *)(st)->elm, strlen((st)->elm)) 
1208 #define PF_MD5_UPD_HTONL(st, elm, stor) do {                            \ 
1209         (stor) = htonl((st)->elm);                                      \ 
1210         MD5Update(ctx, (u_int8_t *)&(stor), sizeof (u_int32_t));        \ 
1213 #define PF_MD5_UPD_HTONS(st, elm, stor) do {                            \ 
1214         (stor) = htons((st)->elm);                                      \ 
1215         MD5Update(ctx, (u_int8_t *)&(stor), sizeof (u_int16_t));        \ 
1219 pf_hash_rule_addr(MD5_CTX 
*ctx
, struct pf_rule_addr 
*pfr
, u_int8_t proto
) 
1221         PF_MD5_UPD(pfr
, addr
.type
); 
1222         switch (pfr
->addr
.type
) { 
1223         case PF_ADDR_DYNIFTL
: 
1224                 PF_MD5_UPD(pfr
, addr
.v
.ifname
); 
1225                 PF_MD5_UPD(pfr
, addr
.iflags
); 
1228                 PF_MD5_UPD(pfr
, addr
.v
.tblname
); 
1230         case PF_ADDR_ADDRMASK
: 
1231                 /* XXX ignore af? */ 
1232                 PF_MD5_UPD(pfr
, addr
.v
.a
.addr
.addr32
); 
1233                 PF_MD5_UPD(pfr
, addr
.v
.a
.mask
.addr32
); 
1235         case PF_ADDR_RTLABEL
: 
1236                 PF_MD5_UPD(pfr
, addr
.v
.rtlabelname
); 
1243                 PF_MD5_UPD(pfr
, xport
.range
.port
[0]); 
1244                 PF_MD5_UPD(pfr
, xport
.range
.port
[1]); 
1245                 PF_MD5_UPD(pfr
, xport
.range
.op
); 
1252         PF_MD5_UPD(pfr
, neg
); 
1256 pf_hash_rule(MD5_CTX 
*ctx
, struct pf_rule 
*rule
) 
1261         pf_hash_rule_addr(ctx
, &rule
->src
, rule
->proto
); 
1262         pf_hash_rule_addr(ctx
, &rule
->dst
, rule
->proto
); 
1263         PF_MD5_UPD_STR(rule
, label
); 
1264         PF_MD5_UPD_STR(rule
, ifname
); 
1265         PF_MD5_UPD_STR(rule
, match_tagname
); 
1266         PF_MD5_UPD_HTONS(rule
, match_tag
, x
); /* dup? */ 
1267         PF_MD5_UPD_HTONL(rule
, os_fingerprint
, y
); 
1268         PF_MD5_UPD_HTONL(rule
, prob
, y
); 
1269         PF_MD5_UPD_HTONL(rule
, uid
.uid
[0], y
); 
1270         PF_MD5_UPD_HTONL(rule
, uid
.uid
[1], y
); 
1271         PF_MD5_UPD(rule
, uid
.op
); 
1272         PF_MD5_UPD_HTONL(rule
, gid
.gid
[0], y
); 
1273         PF_MD5_UPD_HTONL(rule
, gid
.gid
[1], y
); 
1274         PF_MD5_UPD(rule
, gid
.op
); 
1275         PF_MD5_UPD_HTONL(rule
, rule_flag
, y
); 
1276         PF_MD5_UPD(rule
, action
); 
1277         PF_MD5_UPD(rule
, direction
); 
1278         PF_MD5_UPD(rule
, af
); 
1279         PF_MD5_UPD(rule
, quick
); 
1280         PF_MD5_UPD(rule
, ifnot
); 
1281         PF_MD5_UPD(rule
, match_tag_not
); 
1282         PF_MD5_UPD(rule
, natpass
); 
1283         PF_MD5_UPD(rule
, keep_state
); 
1284         PF_MD5_UPD(rule
, proto
); 
1285         PF_MD5_UPD(rule
, type
); 
1286         PF_MD5_UPD(rule
, code
); 
1287         PF_MD5_UPD(rule
, flags
); 
1288         PF_MD5_UPD(rule
, flagset
); 
1289         PF_MD5_UPD(rule
, allow_opts
); 
1290         PF_MD5_UPD(rule
, rt
); 
1291         PF_MD5_UPD(rule
, tos
); 
1295 pf_commit_rules(u_int32_t ticket
, int rs_num
, char *anchor
) 
1297         struct pf_ruleset       
*rs
; 
1298         struct pf_rule          
*rule
, **old_array
, *r
; 
1299         struct pf_rulequeue     
*old_rules
; 
1301         u_int32_t                old_rcount
; 
1303         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
1305         if (rs_num 
< 0 || rs_num 
>= PF_RULESET_MAX
) 
1307         rs 
= pf_find_ruleset(anchor
); 
1308         if (rs 
== NULL 
|| !rs
->rules
[rs_num
].inactive
.open 
|| 
1309             ticket 
!= rs
->rules
[rs_num
].inactive
.ticket
) 
1312         /* Calculate checksum for the main ruleset */ 
1313         if (rs 
== &pf_main_ruleset
) { 
1314                 error 
= pf_setup_pfsync_matching(rs
); 
1319         /* Swap rules, keep the old. */ 
1320         old_rules 
= rs
->rules
[rs_num
].active
.ptr
; 
1321         old_rcount 
= rs
->rules
[rs_num
].active
.rcount
; 
1322         old_array 
= rs
->rules
[rs_num
].active
.ptr_array
; 
1324         if(old_rcount 
!= 0) { 
1325                 r 
= TAILQ_FIRST(rs
->rules
[rs_num
].active
.ptr
); 
1327                         if (r
->rule_flag 
& PFRULE_PFM
) 
1329                         r 
= TAILQ_NEXT(r
, entries
); 
1334         rs
->rules
[rs_num
].active
.ptr 
= 
1335             rs
->rules
[rs_num
].inactive
.ptr
; 
1336         rs
->rules
[rs_num
].active
.ptr_array 
= 
1337             rs
->rules
[rs_num
].inactive
.ptr_array
; 
1338         rs
->rules
[rs_num
].active
.rcount 
= 
1339             rs
->rules
[rs_num
].inactive
.rcount
; 
1340         rs
->rules
[rs_num
].inactive
.ptr 
= old_rules
; 
1341         rs
->rules
[rs_num
].inactive
.ptr_array 
= old_array
; 
1342         rs
->rules
[rs_num
].inactive
.rcount 
= old_rcount
; 
1344         rs
->rules
[rs_num
].active
.ticket 
= 
1345             rs
->rules
[rs_num
].inactive
.ticket
; 
1346         pf_calc_skip_steps(rs
->rules
[rs_num
].active
.ptr
); 
1349         /* Purge the old rule list. */ 
1350         while ((rule 
= TAILQ_FIRST(old_rules
)) != NULL
) 
1351                 pf_rm_rule(old_rules
, rule
); 
1352         if (rs
->rules
[rs_num
].inactive
.ptr_array
) 
1353                 _FREE(rs
->rules
[rs_num
].inactive
.ptr_array
, M_TEMP
); 
1354         rs
->rules
[rs_num
].inactive
.ptr_array 
= NULL
; 
1355         rs
->rules
[rs_num
].inactive
.rcount 
= 0; 
1356         rs
->rules
[rs_num
].inactive
.open 
= 0; 
1357         pf_remove_if_empty_ruleset(rs
); 
1362 pf_rule_copyin(struct pf_rule 
*src
, struct pf_rule 
*dst
, struct proc 
*p
, 
1365         bcopy(src
, dst
, sizeof (struct pf_rule
)); 
1367         dst
->label
[sizeof (dst
->label
) - 1] = '\0'; 
1368         dst
->ifname
[sizeof (dst
->ifname
) - 1] = '\0'; 
1369         dst
->qname
[sizeof (dst
->qname
) - 1] = '\0'; 
1370         dst
->pqname
[sizeof (dst
->pqname
) - 1] = '\0'; 
1371         dst
->tagname
[sizeof (dst
->tagname
) - 1] = '\0'; 
1372         dst
->match_tagname
[sizeof (dst
->match_tagname
) - 1] = '\0'; 
1373         dst
->overload_tblname
[sizeof (dst
->overload_tblname
) - 1] = '\0'; 
1375         dst
->cuid 
= kauth_cred_getuid(p
->p_ucred
); 
1376         dst
->cpid 
= p
->p_pid
; 
1380         dst
->overload_tbl 
= NULL
; 
1382         TAILQ_INIT(&dst
->rpool
.list
); 
1383         dst
->rpool
.cur 
= NULL
; 
1385         /* initialize refcounting */ 
1389         dst
->entries
.tqe_prev 
= NULL
; 
1390         dst
->entries
.tqe_next 
= NULL
; 
1391         if ((uint8_t)minordev 
== PFDEV_PFM
) 
1392                 dst
->rule_flag 
|= PFRULE_PFM
; 
1396 pf_rule_copyout(struct pf_rule 
*src
, struct pf_rule 
*dst
) 
1398         bcopy(src
, dst
, sizeof (struct pf_rule
)); 
1402         dst
->overload_tbl 
= NULL
; 
1404         TAILQ_INIT(&dst
->rpool
.list
); 
1405         dst
->rpool
.cur 
= NULL
; 
1407         dst
->entries
.tqe_prev 
= NULL
; 
1408         dst
->entries
.tqe_next 
= NULL
; 
1412 pf_state_export(struct pfsync_state 
*sp
, struct pf_state_key 
*sk
, 
1415         uint64_t secs 
= pf_time_second(); 
1416         bzero(sp
, sizeof (struct pfsync_state
)); 
1418         /* copy from state key */ 
1419         sp
->lan
.addr 
= sk
->lan
.addr
; 
1420         sp
->lan
.xport 
= sk
->lan
.xport
; 
1421         sp
->gwy
.addr 
= sk
->gwy
.addr
; 
1422         sp
->gwy
.xport 
= sk
->gwy
.xport
; 
1423         sp
->ext
.addr 
= sk
->ext
.addr
; 
1424         sp
->ext
.xport 
= sk
->ext
.xport
; 
1425         sp
->proto_variant 
= sk
->proto_variant
; 
1427         sp
->proto 
= sk
->proto
; 
1429         sp
->direction 
= sk
->direction
; 
1430         sp
->flowhash 
= sk
->flowhash
; 
1432         /* copy from state */ 
1433         memcpy(&sp
->id
, &s
->id
, sizeof (sp
->id
)); 
1434         sp
->creatorid 
= s
->creatorid
; 
1435         strlcpy(sp
->ifname
, s
->kif
->pfik_name
, sizeof (sp
->ifname
)); 
1436         pf_state_peer_to_pfsync(&s
->src
, &sp
->src
); 
1437         pf_state_peer_to_pfsync(&s
->dst
, &sp
->dst
); 
1439         sp
->rule 
= s
->rule
.ptr
->nr
; 
1440         sp
->nat_rule 
= (s
->nat_rule
.ptr 
== NULL
) ? 
1441             (unsigned)-1 : s
->nat_rule
.ptr
->nr
; 
1442         sp
->anchor 
= (s
->anchor
.ptr 
== NULL
) ? 
1443             (unsigned)-1 : s
->anchor
.ptr
->nr
; 
1445         pf_state_counter_to_pfsync(s
->bytes
[0], sp
->bytes
[0]); 
1446         pf_state_counter_to_pfsync(s
->bytes
[1], sp
->bytes
[1]); 
1447         pf_state_counter_to_pfsync(s
->packets
[0], sp
->packets
[0]); 
1448         pf_state_counter_to_pfsync(s
->packets
[1], sp
->packets
[1]); 
1449         sp
->creation 
= secs 
- s
->creation
; 
1450         sp
->expire 
= pf_state_expires(s
); 
1452         sp
->allow_opts 
= s
->allow_opts
; 
1453         sp
->timeout 
= s
->timeout
; 
1456                 sp
->sync_flags 
|= PFSYNC_FLAG_SRCNODE
; 
1457         if (s
->nat_src_node
) 
1458                 sp
->sync_flags 
|= PFSYNC_FLAG_NATSRCNODE
; 
1460         if (sp
->expire 
> secs
) 
1468 pf_state_import(struct pfsync_state 
*sp
, struct pf_state_key 
*sk
, 
1471         /* copy to state key */ 
1472         sk
->lan
.addr 
= sp
->lan
.addr
; 
1473         sk
->lan
.xport 
= sp
->lan
.xport
; 
1474         sk
->gwy
.addr 
= sp
->gwy
.addr
; 
1475         sk
->gwy
.xport 
= sp
->gwy
.xport
; 
1476         sk
->ext
.addr 
= sp
->ext
.addr
; 
1477         sk
->ext
.xport 
= sp
->ext
.xport
; 
1478         sk
->proto_variant 
= sp
->proto_variant
; 
1480         sk
->proto 
= sp
->proto
; 
1482         sk
->direction 
= sp
->direction
; 
1483         sk
->flowhash 
= pf_calc_state_key_flowhash(sk
); 
1486         memcpy(&s
->id
, &sp
->id
, sizeof (sp
->id
)); 
1487         s
->creatorid 
= sp
->creatorid
; 
1488         pf_state_peer_from_pfsync(&sp
->src
, &s
->src
); 
1489         pf_state_peer_from_pfsync(&sp
->dst
, &s
->dst
); 
1491         s
->rule
.ptr 
= &pf_default_rule
; 
1492         s
->nat_rule
.ptr 
= NULL
; 
1493         s
->anchor
.ptr 
= NULL
; 
1495         s
->creation 
= pf_time_second(); 
1496         s
->expire 
= pf_time_second(); 
1498                 s
->expire 
-= pf_default_rule
.timeout
[sp
->timeout
] - sp
->expire
; 
1500         s
->packets
[0] = s
->packets
[1] = 0; 
1501         s
->bytes
[0] = s
->bytes
[1] = 0; 
1505 pf_pooladdr_copyin(struct pf_pooladdr 
*src
, struct pf_pooladdr 
*dst
) 
1507         bcopy(src
, dst
, sizeof (struct pf_pooladdr
)); 
1509         dst
->entries
.tqe_prev 
= NULL
; 
1510         dst
->entries
.tqe_next 
= NULL
; 
1511         dst
->ifname
[sizeof (dst
->ifname
) - 1] = '\0'; 
1516 pf_pooladdr_copyout(struct pf_pooladdr 
*src
, struct pf_pooladdr 
*dst
) 
1518         bcopy(src
, dst
, sizeof (struct pf_pooladdr
)); 
1520         dst
->entries
.tqe_prev 
= NULL
; 
1521         dst
->entries
.tqe_next 
= NULL
; 
1526 pf_setup_pfsync_matching(struct pf_ruleset 
*rs
) 
1529         struct pf_rule          
*rule
; 
1531         u_int8_t                 digest
[PF_MD5_DIGEST_LENGTH
]; 
1534         for (rs_cnt 
= 0; rs_cnt 
< PF_RULESET_MAX
; rs_cnt
++) { 
1535                 /* XXX PF_RULESET_SCRUB as well? */ 
1536                 if (rs_cnt 
== PF_RULESET_SCRUB
) 
1539                 if (rs
->rules
[rs_cnt
].inactive
.ptr_array
) 
1540                         _FREE(rs
->rules
[rs_cnt
].inactive
.ptr_array
, M_TEMP
); 
1541                 rs
->rules
[rs_cnt
].inactive
.ptr_array 
= NULL
; 
1543                 if (rs
->rules
[rs_cnt
].inactive
.rcount
) { 
1544                         rs
->rules
[rs_cnt
].inactive
.ptr_array 
= 
1545                             _MALLOC(sizeof (caddr_t
) * 
1546                             rs
->rules
[rs_cnt
].inactive
.rcount
, 
1549                         if (!rs
->rules
[rs_cnt
].inactive
.ptr_array
) 
1553                 TAILQ_FOREACH(rule
, rs
->rules
[rs_cnt
].inactive
.ptr
, 
1555                         pf_hash_rule(&ctx
, rule
); 
1556                         (rs
->rules
[rs_cnt
].inactive
.ptr_array
)[rule
->nr
] = rule
; 
1560         MD5Final(digest
, &ctx
); 
1561         memcpy(pf_status
.pf_chksum
, digest
, sizeof (pf_status
.pf_chksum
)); 
1568         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
1570         VERIFY(pf_is_enabled 
== 0); 
1573         pf_status
.running 
= 1; 
1574         pf_status
.since 
= pf_calendar_time_second(); 
1575         if (pf_status
.stateid 
== 0) { 
1576                 pf_status
.stateid 
= pf_time_second(); 
1577                 pf_status
.stateid 
= pf_status
.stateid 
<< 32; 
1579         wakeup(pf_purge_thread_fn
); 
1580         DPFPRINTF(PF_DEBUG_MISC
, ("pf: started\n")); 
1586         lck_mtx_assert(pf_lock
, LCK_MTX_ASSERT_OWNED
); 
1588         VERIFY(pf_is_enabled
); 
1590         pf_status
.running 
= 0; 
1592         pf_status
.since 
= pf_calendar_time_second(); 
1593         wakeup(pf_purge_thread_fn
); 
1594         DPFPRINTF(PF_DEBUG_MISC
, ("pf: stopped\n")); 
1598 pfioctl(dev_t dev
, u_long cmd
, caddr_t addr
, int flags
, struct proc 
*p
) 
1601         int p64 
= proc_is64bit(p
); 
1603         int minordev 
= minor(dev
); 
1605         if (kauth_cred_issuser(kauth_cred_get()) == 0) 
1608         /* XXX keep in sync with switch() below */ 
1609         if (securelevel 
> 1) 
1616                 case DIOCSETSTATUSIF
: 
1622                 case DIOCINSERTRULE
: 
1623                 case DIOCDELETERULE
: 
1624                 case DIOCGETTIMEOUT
: 
1625                 case DIOCCLRRULECTRS
: 
1630                 case DIOCGETRULESETS
: 
1631                 case DIOCGETRULESET
: 
1632                 case DIOCRGETTABLES
: 
1633                 case DIOCRGETTSTATS
: 
1634                 case DIOCRCLRTSTATS
: 
1640                 case DIOCRGETASTATS
: 
1641                 case DIOCRCLRASTATS
: 
1644                 case DIOCGETSRCNODES
: 
1645                 case DIOCCLRSRCNODES
: 
1646                 case DIOCIGETIFACES
: 
1651                 case DIOCRCLRTABLES
: 
1652                 case DIOCRADDTABLES
: 
1653                 case DIOCRDELTABLES
: 
1654                 case DIOCRSETTFLAGS
: { 
1657                         bcopy(&((struct pfioc_table 
*)(void *)addr
)-> 
1658                             pfrio_flags
, &pfrio_flags
, sizeof (pfrio_flags
)); 
1660                         if (pfrio_flags 
& PFR_FLAG_DUMMY
) 
1661                                 break; /* dummy operation ok */ 
1668         if (!(flags 
& FWRITE
)) 
1674                 case DIOCGETSTARTERS
: 
1681                 case DIOCINSERTRULE
: 
1682                 case DIOCDELETERULE
: 
1683                 case DIOCGETTIMEOUT
: 
1688                 case DIOCGETRULESETS
: 
1689                 case DIOCGETRULESET
: 
1691                 case DIOCRGETTABLES
: 
1692                 case DIOCRGETTSTATS
: 
1694                 case DIOCRGETASTATS
: 
1697                 case DIOCGETSRCNODES
: 
1698                 case DIOCIGETIFACES
: 
1701                 case DIOCRCLRTABLES
: 
1702                 case DIOCRADDTABLES
: 
1703                 case DIOCRDELTABLES
: 
1704                 case DIOCRCLRTSTATS
: 
1709                 case DIOCRSETTFLAGS
: { 
1712                         bcopy(&((struct pfioc_table 
*)(void *)addr
)-> 
1713                             pfrio_flags
, &pfrio_flags
, sizeof (pfrio_flags
)); 
1715                         if (pfrio_flags 
& PFR_FLAG_DUMMY
) { 
1716                                 flags 
|= FWRITE
; /* need write lock for dummy */ 
1717                                 break; /* dummy operation ok */ 
1724                         bcopy(&((struct pfioc_rule 
*)(void *)addr
)->action
, 
1725                             &action
, sizeof (action
)); 
1727                         if (action 
== PF_GET_CLR_CNTR
) 
1742         case DIOCCHANGEALTQ
: 
1744                 /* fail if ALTQ is disabled */ 
1749 #endif /* PF_ALTQ */ 
1752                 lck_rw_lock_exclusive(pf_perim_lock
); 
1754                 lck_rw_lock_shared(pf_perim_lock
); 
1756         lck_mtx_lock(pf_lock
); 
1761                 if (pf_status
.running
) { 
1763                          * Increment the reference for a simple -e enable, so 
1764                          * that even if other processes drop their references, 
1765                          * pf will still be available to processes that turned 
1766                          * it on without taking a reference 
1768                         if (nr_tokens 
== pf_enabled_ref_count
) { 
1769                                 pf_enabled_ref_count
++; 
1770                                 VERIFY(pf_enabled_ref_count 
!= 0); 
1773                 } else if (pf_purge_thread 
== NULL
) { 
1777                         pf_enabled_ref_count
++; 
1778                         VERIFY(pf_enabled_ref_count 
!= 0); 
1782         case DIOCSTARTREF
:              /* u_int64_t */ 
1783                 if (pf_purge_thread 
== NULL
) { 
1788                         /* small enough to be on stack */ 
1789                         if ((token 
= generate_token(p
)) != 0) { 
1790                                 if (pf_is_enabled 
== 0) { 
1793                                 pf_enabled_ref_count
++; 
1794                                 VERIFY(pf_enabled_ref_count 
!= 0); 
1797                                 DPFPRINTF(PF_DEBUG_URGENT
, 
1798                                     ("pf: unable to generate token\n")); 
1800                         bcopy(&token
, addr
, sizeof (token
)); 
1805                 if (!pf_status
.running
) { 
1809                         pf_enabled_ref_count 
= 0; 
1810                         invalidate_all_tokens(); 
1814         case DIOCSTOPREF
:               /* struct pfioc_remove_token */ 
1815                 if (!pf_status
.running
) { 
1818                         struct pfioc_remove_token pfrt
; 
1820                         /* small enough to be on stack */ 
1821                         bcopy(addr
, &pfrt
, sizeof (pfrt
)); 
1822                         if ((error 
= remove_token(&pfrt
)) == 0) { 
1823                                 VERIFY(pf_enabled_ref_count 
!= 0); 
1824                                 pf_enabled_ref_count
--; 
1825                                 /* return currently held references */ 
1826                                 pfrt
.refcount 
= pf_enabled_ref_count
; 
1827                                 DPFPRINTF(PF_DEBUG_MISC
, 
1828                                     ("pf: enabled refcount decremented\n")); 
1831                                 DPFPRINTF(PF_DEBUG_URGENT
, 
1832                                     ("pf: token mismatch\n")); 
1834                         bcopy(&pfrt
, addr
, sizeof (pfrt
)); 
1836                         if (error 
== 0 && pf_enabled_ref_count 
== 0) 
1841         case DIOCGETSTARTERS
: {         /* struct pfioc_tokens */ 
1842                 PFIOCX_STRUCT_DECL(pfioc_tokens
); 
1844                 PFIOCX_STRUCT_BEGIN(addr
, pfioc_tokens
, error 
= ENOMEM
; break;); 
1845                 error 
= pfioctl_ioc_tokens(cmd
, 
1846                     PFIOCX_STRUCT_ADDR32(pfioc_tokens
), 
1847                     PFIOCX_STRUCT_ADDR64(pfioc_tokens
), p
); 
1848                 PFIOCX_STRUCT_END(pfioc_tokens
, addr
); 
1852         case DIOCADDRULE
:               /* struct pfioc_rule */ 
1853         case DIOCGETRULES
:              /* struct pfioc_rule */ 
1854         case DIOCGETRULE
:               /* struct pfioc_rule */ 
1855         case DIOCCHANGERULE
:            /* struct pfioc_rule */ 
1856         case DIOCINSERTRULE
:            /* struct pfioc_rule */ 
1857         case DIOCDELETERULE
: {          /* struct pfioc_rule */ 
1858                 struct pfioc_rule 
*pr 
= NULL
; 
1860                 PFIOC_STRUCT_BEGIN(addr
, pr
, error 
= ENOMEM
; break;); 
1861                 error 
= pfioctl_ioc_rule(cmd
, minordev
, pr
, p
); 
1862                 PFIOC_STRUCT_END(pr
, addr
); 
1866         case DIOCCLRSTATES
:             /* struct pfioc_state_kill */ 
1867         case DIOCKILLSTATES
: {          /* struct pfioc_state_kill */ 
1868                 struct pfioc_state_kill 
*psk 
= NULL
; 
1870                 PFIOC_STRUCT_BEGIN(addr
, psk
, error 
= ENOMEM
; break;); 
1871                 error 
= pfioctl_ioc_state_kill(cmd
, psk
, p
); 
1872                 PFIOC_STRUCT_END(psk
, addr
); 
1876         case DIOCADDSTATE
:              /* struct pfioc_state */ 
1877         case DIOCGETSTATE
: {            /* struct pfioc_state */ 
1878                 struct pfioc_state 
*ps 
= NULL
; 
1880                 PFIOC_STRUCT_BEGIN(addr
, ps
, error 
= ENOMEM
; break;); 
1881                 error 
= pfioctl_ioc_state(cmd
, ps
, p
); 
1882                 PFIOC_STRUCT_END(ps
, addr
); 
1886         case DIOCGETSTATES
: {           /* struct pfioc_states */ 
1887                 PFIOCX_STRUCT_DECL(pfioc_states
); 
1889                 PFIOCX_STRUCT_BEGIN(addr
, pfioc_states
, error 
= ENOMEM
; break;); 
1890                 error 
= pfioctl_ioc_states(cmd
, 
1891                     PFIOCX_STRUCT_ADDR32(pfioc_states
), 
1892                     PFIOCX_STRUCT_ADDR64(pfioc_states
), p
); 
1893                 PFIOCX_STRUCT_END(pfioc_states
, addr
); 
1897         case DIOCGETSTATUS
: {           /* struct pf_status */ 
1898                 struct pf_status 
*s 
= NULL
; 
1900                 PFIOC_STRUCT_BEGIN(&pf_status
, s
, error 
= ENOMEM
; break;); 
1901                 pfi_update_status(s
->ifname
, s
); 
1902                 PFIOC_STRUCT_END(s
, addr
); 
1906         case DIOCSETSTATUSIF
: {         /* struct pfioc_if */ 
1907                 struct pfioc_if 
*pi 
= (struct pfioc_if 
*)(void *)addr
; 
1909                 /* OK for unaligned accesses */ 
1910                 if (pi
->ifname
[0] == 0) { 
1911                         bzero(pf_status
.ifname
, IFNAMSIZ
); 
1914                 strlcpy(pf_status
.ifname
, pi
->ifname
, IFNAMSIZ
); 
1918         case DIOCCLRSTATUS
: { 
1919                 bzero(pf_status
.counters
, sizeof (pf_status
.counters
)); 
1920                 bzero(pf_status
.fcounters
, sizeof (pf_status
.fcounters
)); 
1921                 bzero(pf_status
.scounters
, sizeof (pf_status
.scounters
)); 
1922                 pf_status
.since 
= pf_calendar_time_second(); 
1923                 if (*pf_status
.ifname
) 
1924                         pfi_update_status(pf_status
.ifname
, NULL
); 
1928         case DIOCNATLOOK
: {             /* struct pfioc_natlook */ 
1929                 struct pfioc_natlook 
*pnl 
= NULL
; 
1931                 PFIOC_STRUCT_BEGIN(addr
, pnl
, error 
= ENOMEM
; break;); 
1932                 error 
= pfioctl_ioc_natlook(cmd
, pnl
, p
); 
1933                 PFIOC_STRUCT_END(pnl
, addr
); 
1937         case DIOCSETTIMEOUT
:            /* struct pfioc_tm */ 
1938         case DIOCGETTIMEOUT
: {          /* struct pfioc_tm */ 
1941                 /* small enough to be on stack */ 
1942                 bcopy(addr
, &pt
, sizeof (pt
)); 
1943                 error 
= pfioctl_ioc_tm(cmd
, &pt
, p
); 
1944                 bcopy(&pt
, addr
, sizeof (pt
)); 
1948         case DIOCGETLIMIT
:              /* struct pfioc_limit */ 
1949         case DIOCSETLIMIT
: {            /* struct pfioc_limit */ 
1950                 struct pfioc_limit pl
; 
1952                 /* small enough to be on stack */ 
1953                 bcopy(addr
, &pl
, sizeof (pl
)); 
1954                 error 
= pfioctl_ioc_limit(cmd
, &pl
, p
); 
1955                 bcopy(&pl
, addr
, sizeof (pl
)); 
1959         case DIOCSETDEBUG
: {            /* u_int32_t */ 
1960                 bcopy(addr
, &pf_status
.debug
, sizeof (u_int32_t
)); 
1964         case DIOCCLRRULECTRS
: { 
1965                 /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */ 
1966                 struct pf_ruleset       
*ruleset 
= &pf_main_ruleset
; 
1967                 struct pf_rule          
*rule
; 
1970                     ruleset
->rules
[PF_RULESET_FILTER
].active
.ptr
, entries
) { 
1971                         rule
->evaluations 
= 0; 
1972                         rule
->packets
[0] = rule
->packets
[1] = 0; 
1973                         rule
->bytes
[0] = rule
->bytes
[1] = 0; 
1978         case DIOCGIFSPEED
: { 
1979                 struct pf_ifspeed 
*psp 
= (struct pf_ifspeed 
*)(void *)addr
; 
1980                 struct pf_ifspeed ps
; 
1984                 if (psp
->ifname
[0] != '\0') { 
1985                         /* Can we completely trust user-land? */ 
1986                         strlcpy(ps
.ifname
, psp
->ifname
, IFNAMSIZ
); 
1987                         ps
.ifname
[IFNAMSIZ 
- 1] = '\0'; 
1988                         ifp 
= ifunit(ps
.ifname
); 
1990                                 baudrate 
= ifp
->if_output_bw
.max_bw
; 
1991                                 bcopy(&baudrate
, &psp
->baudrate
, 
2003         case DIOCSTARTALTQ
: { 
2004                 struct pf_altq          
*altq
; 
2006                 VERIFY(altq_allowed
); 
2007                 /* enable all altq interfaces on active list */ 
2008                 TAILQ_FOREACH(altq
, pf_altqs_active
, entries
) { 
2009                         if (altq
->qname
[0] == '\0') { 
2010                                 error 
= pf_enable_altq(altq
); 
2016                         pf_altq_running 
= 1; 
2017                 DPFPRINTF(PF_DEBUG_MISC
, ("altq: started\n")); 
2021         case DIOCSTOPALTQ
: { 
2022                 struct pf_altq          
*altq
; 
2024                 VERIFY(altq_allowed
); 
2025                 /* disable all altq interfaces on active list */ 
2026                 TAILQ_FOREACH(altq
, pf_altqs_active
, entries
) { 
2027                         if (altq
->qname
[0] == '\0') { 
2028                                 error 
= pf_disable_altq(altq
); 
2034                         pf_altq_running 
= 0; 
2035                 DPFPRINTF(PF_DEBUG_MISC
, ("altq: stopped\n")); 
2039         case DIOCADDALTQ
: {             /* struct pfioc_altq */ 
2040                 struct pfioc_altq       
*pa 
= (struct pfioc_altq 
*)(void *)addr
; 
2041                 struct pf_altq          
*altq
, *a
; 
2044                 VERIFY(altq_allowed
); 
2045                 bcopy(&pa
->ticket
, &ticket
, sizeof (ticket
)); 
2046                 if (ticket 
!= ticket_altqs_inactive
) { 
2050                 altq 
= pool_get(&pf_altq_pl
, PR_WAITOK
); 
2055                 pf_altq_copyin(&pa
->altq
, altq
); 
2058                  * if this is for a queue, find the discipline and 
2059                  * copy the necessary fields 
2061                 if (altq
->qname
[0] != '\0') { 
2062                         if ((altq
->qid 
= pf_qname2qid(altq
->qname
)) == 0) { 
2064                                 pool_put(&pf_altq_pl
, altq
); 
2067                         altq
->altq_disc 
= NULL
; 
2068                         TAILQ_FOREACH(a
, pf_altqs_inactive
, entries
) { 
2069                                 if (strncmp(a
->ifname
, altq
->ifname
, 
2070                                     IFNAMSIZ
) == 0 && a
->qname
[0] == '\0') { 
2071                                         altq
->altq_disc 
= a
->altq_disc
; 
2077                 error 
= altq_add(altq
); 
2079                         pool_put(&pf_altq_pl
, altq
); 
2083                 TAILQ_INSERT_TAIL(pf_altqs_inactive
, altq
, entries
); 
2084                 pf_altq_copyout(altq
, &pa
->altq
); 
2088         case DIOCGETALTQS
: { 
2089                 struct pfioc_altq       
*pa 
= (struct pfioc_altq 
*)(void *)addr
; 
2090                 struct pf_altq          
*altq
; 
2093                 VERIFY(altq_allowed
); 
2095                 TAILQ_FOREACH(altq
, pf_altqs_active
, entries
) 
2097                 bcopy(&nr
, &pa
->nr
, sizeof (nr
)); 
2098                 bcopy(&ticket_altqs_active
, &pa
->ticket
, sizeof (pa
->ticket
)); 
2103                 struct pfioc_altq       
*pa 
= (struct pfioc_altq 
*)(void *)addr
; 
2104                 struct pf_altq          
*altq
; 
2105                 u_int32_t                nr
, pa_nr
, ticket
; 
2107                 VERIFY(altq_allowed
); 
2108                 bcopy(&pa
->ticket
, &ticket
, sizeof (ticket
)); 
2109                 if (ticket 
!= ticket_altqs_active
) { 
2113                 bcopy(&pa
->nr
, &pa_nr
, sizeof (pa_nr
)); 
2115                 altq 
= TAILQ_FIRST(pf_altqs_active
); 
2116                 while ((altq 
!= NULL
) && (nr 
< pa_nr
)) { 
2117                         altq 
= TAILQ_NEXT(altq
, entries
); 
2124                 pf_altq_copyout(altq
, &pa
->altq
); 
2128         case DIOCCHANGEALTQ
: 
2129                 VERIFY(altq_allowed
); 
2130                 /* CHANGEALTQ not supported yet! */ 
2134         case DIOCGETQSTATS
: { 
2135                 struct pfioc_qstats 
*pq 
= (struct pfioc_qstats 
*)(void *)addr
; 
2136                 struct pf_altq          
*altq
; 
2137                 u_int32_t                nr
, pq_nr
, ticket
; 
2140                 VERIFY(altq_allowed
); 
2141                 bcopy(&pq
->ticket
, &ticket
, sizeof (ticket
)); 
2142                 if (ticket 
!= ticket_altqs_active
) { 
2146                 bcopy(&pq
->nr
, &pq_nr
, sizeof (pq_nr
)); 
2148                 altq 
= TAILQ_FIRST(pf_altqs_active
); 
2149                 while ((altq 
!= NULL
) && (nr 
< pq_nr
)) { 
2150                         altq 
= TAILQ_NEXT(altq
, entries
); 
2157                 bcopy(&pq
->nbytes
, &nbytes
, sizeof (nbytes
)); 
2158                 error 
= altq_getqstats(altq
, pq
->buf
, &nbytes
); 
2160                         pq
->scheduler 
= altq
->scheduler
; 
2161                         bcopy(&nbytes
, &pq
->nbytes
, sizeof (nbytes
)); 
2165 #endif /* PF_ALTQ */ 
2167         case DIOCBEGINADDRS
:            /* struct pfioc_pooladdr */ 
2168         case DIOCADDADDR
:               /* struct pfioc_pooladdr */ 
2169         case DIOCGETADDRS
:              /* struct pfioc_pooladdr */ 
2170         case DIOCGETADDR
:               /* struct pfioc_pooladdr */ 
2171         case DIOCCHANGEADDR
: {          /* struct pfioc_pooladdr */ 
2172                 struct pfioc_pooladdr 
*pp 
= NULL
; 
2174                 PFIOC_STRUCT_BEGIN(addr
, pp
, error 
= ENOMEM
; break;) 
2175                 error 
= pfioctl_ioc_pooladdr(cmd
, pp
, p
); 
2176                 PFIOC_STRUCT_END(pp
, addr
); 
2180         case DIOCGETRULESETS
:           /* struct pfioc_ruleset */ 
2181         case DIOCGETRULESET
: {          /* struct pfioc_ruleset */ 
2182                 struct pfioc_ruleset 
*pr 
= NULL
; 
2184                 PFIOC_STRUCT_BEGIN(addr
, pr
, error 
= ENOMEM
; break;); 
2185                 error 
= pfioctl_ioc_ruleset(cmd
, pr
, p
); 
2186                 PFIOC_STRUCT_END(pr
, addr
); 
2190         case DIOCRCLRTABLES
:            /* struct pfioc_table */ 
2191         case DIOCRADDTABLES
:            /* struct pfioc_table */ 
2192         case DIOCRDELTABLES
:            /* struct pfioc_table */ 
2193         case DIOCRGETTABLES
:            /* struct pfioc_table */ 
2194         case DIOCRGETTSTATS
:            /* struct pfioc_table */ 
2195         case DIOCRCLRTSTATS
:            /* struct pfioc_table */ 
2196         case DIOCRSETTFLAGS
:            /* struct pfioc_table */ 
2197         case DIOCRCLRADDRS
:             /* struct pfioc_table */ 
2198         case DIOCRADDADDRS
:             /* struct pfioc_table */ 
2199         case DIOCRDELADDRS
:             /* struct pfioc_table */ 
2200         case DIOCRSETADDRS
:             /* struct pfioc_table */ 
2201         case DIOCRGETADDRS
:             /* struct pfioc_table */ 
2202         case DIOCRGETASTATS
:            /* struct pfioc_table */ 
2203         case DIOCRCLRASTATS
:            /* struct pfioc_table */ 
2204         case DIOCRTSTADDRS
:             /* struct pfioc_table */ 
2205         case DIOCRINADEFINE
: {          /* struct pfioc_table */ 
2206                 PFIOCX_STRUCT_DECL(pfioc_table
); 
2208                 PFIOCX_STRUCT_BEGIN(addr
, pfioc_table
, error 
= ENOMEM
; break;); 
2209                 error 
= pfioctl_ioc_table(cmd
, 
2210                     PFIOCX_STRUCT_ADDR32(pfioc_table
), 
2211                     PFIOCX_STRUCT_ADDR64(pfioc_table
), p
); 
2212                 PFIOCX_STRUCT_END(pfioc_table
, addr
); 
2216         case DIOCOSFPADD
:               /* struct pf_osfp_ioctl */ 
2217         case DIOCOSFPGET
: {             /* struct pf_osfp_ioctl */ 
2218                 struct pf_osfp_ioctl 
*io 
= NULL
; 
2220                 PFIOC_STRUCT_BEGIN(addr
, io
, error 
= ENOMEM
; break;); 
2221                 if (cmd 
== DIOCOSFPADD
) { 
2222                         error 
= pf_osfp_add(io
); 
2224                         VERIFY(cmd 
== DIOCOSFPGET
); 
2225                         error 
= pf_osfp_get(io
); 
2227                 PFIOC_STRUCT_END(io
, addr
); 
2231         case DIOCXBEGIN
:                /* struct pfioc_trans */ 
2232         case DIOCXROLLBACK
:             /* struct pfioc_trans */ 
2233         case DIOCXCOMMIT
: {             /* struct pfioc_trans */ 
2234                 PFIOCX_STRUCT_DECL(pfioc_trans
); 
2236                 PFIOCX_STRUCT_BEGIN(addr
, pfioc_trans
, error 
= ENOMEM
; break;); 
2237                 error 
= pfioctl_ioc_trans(cmd
, 
2238                     PFIOCX_STRUCT_ADDR32(pfioc_trans
), 
2239                     PFIOCX_STRUCT_ADDR64(pfioc_trans
), p
); 
2240                 PFIOCX_STRUCT_END(pfioc_trans
, addr
); 
2244         case DIOCGETSRCNODES
: {         /* struct pfioc_src_nodes */ 
2245                 PFIOCX_STRUCT_DECL(pfioc_src_nodes
); 
2247                 PFIOCX_STRUCT_BEGIN(addr
, pfioc_src_nodes
, 
2248                     error 
= ENOMEM
; break;); 
2249                 error 
= pfioctl_ioc_src_nodes(cmd
, 
2250                     PFIOCX_STRUCT_ADDR32(pfioc_src_nodes
), 
2251                     PFIOCX_STRUCT_ADDR64(pfioc_src_nodes
), p
); 
2252                 PFIOCX_STRUCT_END(pfioc_src_nodes
, addr
); 
2256         case DIOCCLRSRCNODES
: { 
2257                 struct pf_src_node      
*n
; 
2258                 struct pf_state         
*state
; 
2260                 RB_FOREACH(state
, pf_state_tree_id
, &tree_id
) { 
2261                         state
->src_node 
= NULL
; 
2262                         state
->nat_src_node 
= NULL
; 
2264                 RB_FOREACH(n
, pf_src_tree
, &tree_src_tracking
) { 
2268                 pf_purge_expired_src_nodes(); 
2269                 pf_status
.src_nodes 
= 0; 
2273         case DIOCKILLSRCNODES
: {        /* struct pfioc_src_node_kill */ 
2274                 struct pfioc_src_node_kill 
*psnk 
= NULL
; 
2276                 PFIOC_STRUCT_BEGIN(addr
, psnk
, error 
= ENOMEM
; break;); 
2277                 error 
= pfioctl_ioc_src_node_kill(cmd
, psnk
, p
); 
2278                 PFIOC_STRUCT_END(psnk
, addr
); 
2282         case DIOCSETHOSTID
: {           /* u_int32_t */ 
2285                 /* small enough to be on stack */ 
2286                 bcopy(addr
, &hid
, sizeof (hid
)); 
2288                         pf_status
.hostid 
= random(); 
2290                         pf_status
.hostid 
= hid
; 
2298         case DIOCIGETIFACES
:            /* struct pfioc_iface */ 
2299         case DIOCSETIFFLAG
:             /* struct pfioc_iface */ 
2300         case DIOCCLRIFFLAG
: {           /* struct pfioc_iface */ 
2301                 PFIOCX_STRUCT_DECL(pfioc_iface
); 
2303                 PFIOCX_STRUCT_BEGIN(addr
, pfioc_iface
, error 
= ENOMEM
; break;); 
2304                 error 
= pfioctl_ioc_iface(cmd
, 
2305                     PFIOCX_STRUCT_ADDR32(pfioc_iface
), 
2306                     PFIOCX_STRUCT_ADDR64(pfioc_iface
), p
); 
2307                 PFIOCX_STRUCT_END(pfioc_iface
, addr
); 
2316         lck_mtx_unlock(pf_lock
); 
2317         lck_rw_done(pf_perim_lock
); 
2323 pfioctl_ioc_table(u_long cmd
, struct pfioc_table_32 
*io32
, 
2324     struct pfioc_table_64 
*io64
, struct proc 
*p
) 
2326         int p64 
= proc_is64bit(p
); 
2333          * 64-bit structure processing 
2336         case DIOCRCLRTABLES
: 
2337                 if (io64
->pfrio_esize 
!= 0) { 
2341                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2342                 error 
= pfr_clr_tables(&io64
->pfrio_table
, &io64
->pfrio_ndel
, 
2343                     io64
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2346         case DIOCRADDTABLES
: 
2347                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_table
)) { 
2351                 error 
= pfr_add_tables(io64
->pfrio_buffer
, io64
->pfrio_size
, 
2352                     &io64
->pfrio_nadd
, io64
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2355         case DIOCRDELTABLES
: 
2356                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_table
)) { 
2360                 error 
= pfr_del_tables(io64
->pfrio_buffer
, io64
->pfrio_size
, 
2361                     &io64
->pfrio_ndel
, io64
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2364         case DIOCRGETTABLES
: 
2365                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_table
)) { 
2369                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2370                 error 
= pfr_get_tables(&io64
->pfrio_table
, io64
->pfrio_buffer
, 
2371                     &io64
->pfrio_size
, io64
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2374         case DIOCRGETTSTATS
: 
2375                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_tstats
)) { 
2379                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2380                 error 
= pfr_get_tstats(&io64
->pfrio_table
, io64
->pfrio_buffer
, 
2381                     &io64
->pfrio_size
, io64
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2384         case DIOCRCLRTSTATS
: 
2385                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_table
)) { 
2389                 error 
= pfr_clr_tstats(io64
->pfrio_buffer
, io64
->pfrio_size
, 
2390                     &io64
->pfrio_nzero
, io64
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2393         case DIOCRSETTFLAGS
: 
2394                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_table
)) { 
2398                 error 
= pfr_set_tflags(io64
->pfrio_buffer
, io64
->pfrio_size
, 
2399                     io64
->pfrio_setflag
, io64
->pfrio_clrflag
, 
2400                     &io64
->pfrio_nchange
, &io64
->pfrio_ndel
, 
2401                     io64
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2405                 if (io64
->pfrio_esize 
!= 0) { 
2409                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2410                 error 
= pfr_clr_addrs(&io64
->pfrio_table
, &io64
->pfrio_ndel
, 
2411                     io64
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2415                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2419                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2420                 error 
= pfr_add_addrs(&io64
->pfrio_table
, io64
->pfrio_buffer
, 
2421                     io64
->pfrio_size
, &io64
->pfrio_nadd
, io64
->pfrio_flags 
| 
2422                     PFR_FLAG_USERIOCTL
); 
2426                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2430                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2431                 error 
= pfr_del_addrs(&io64
->pfrio_table
, io64
->pfrio_buffer
, 
2432                     io64
->pfrio_size
, &io64
->pfrio_ndel
, io64
->pfrio_flags 
| 
2433                     PFR_FLAG_USERIOCTL
); 
2437                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2441                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2442                 error 
= pfr_set_addrs(&io64
->pfrio_table
, io64
->pfrio_buffer
, 
2443                     io64
->pfrio_size
, &io64
->pfrio_size2
, &io64
->pfrio_nadd
, 
2444                     &io64
->pfrio_ndel
, &io64
->pfrio_nchange
, io64
->pfrio_flags 
| 
2445                     PFR_FLAG_USERIOCTL
, 0); 
2449                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2453                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2454                 error 
= pfr_get_addrs(&io64
->pfrio_table
, io64
->pfrio_buffer
, 
2455                     &io64
->pfrio_size
, io64
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2458         case DIOCRGETASTATS
: 
2459                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_astats
)) { 
2463                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2464                 error 
= pfr_get_astats(&io64
->pfrio_table
, io64
->pfrio_buffer
, 
2465                     &io64
->pfrio_size
, io64
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2468         case DIOCRCLRASTATS
: 
2469                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2473                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2474                 error 
= pfr_clr_astats(&io64
->pfrio_table
, io64
->pfrio_buffer
, 
2475                     io64
->pfrio_size
, &io64
->pfrio_nzero
, io64
->pfrio_flags 
| 
2476                     PFR_FLAG_USERIOCTL
); 
2480                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2484                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2485                 error 
= pfr_tst_addrs(&io64
->pfrio_table
, io64
->pfrio_buffer
, 
2486                     io64
->pfrio_size
, &io64
->pfrio_nmatch
, io64
->pfrio_flags 
| 
2487                     PFR_FLAG_USERIOCTL
); 
2490         case DIOCRINADEFINE
: 
2491                 if (io64
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2495                 pfr_table_copyin_cleanup(&io64
->pfrio_table
); 
2496                 error 
= pfr_ina_define(&io64
->pfrio_table
, io64
->pfrio_buffer
, 
2497                     io64
->pfrio_size
, &io64
->pfrio_nadd
, &io64
->pfrio_naddr
, 
2498                     io64
->pfrio_ticket
, io64
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2509          * 32-bit structure processing 
2512         case DIOCRCLRTABLES
: 
2513                 if (io32
->pfrio_esize 
!= 0) { 
2517                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2518                 error 
= pfr_clr_tables(&io32
->pfrio_table
, &io32
->pfrio_ndel
, 
2519                     io32
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2522         case DIOCRADDTABLES
: 
2523                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_table
)) { 
2527                 error 
= pfr_add_tables(io32
->pfrio_buffer
, io32
->pfrio_size
, 
2528                     &io32
->pfrio_nadd
, io32
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2531         case DIOCRDELTABLES
: 
2532                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_table
)) { 
2536                 error 
= pfr_del_tables(io32
->pfrio_buffer
, io32
->pfrio_size
, 
2537                     &io32
->pfrio_ndel
, io32
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2540         case DIOCRGETTABLES
: 
2541                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_table
)) { 
2545                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2546                 error 
= pfr_get_tables(&io32
->pfrio_table
, io32
->pfrio_buffer
, 
2547                     &io32
->pfrio_size
, io32
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2550         case DIOCRGETTSTATS
: 
2551                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_tstats
)) { 
2555                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2556                 error 
= pfr_get_tstats(&io32
->pfrio_table
, io32
->pfrio_buffer
, 
2557                     &io32
->pfrio_size
, io32
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2560         case DIOCRCLRTSTATS
: 
2561                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_table
)) { 
2565                 error 
= pfr_clr_tstats(io32
->pfrio_buffer
, io32
->pfrio_size
, 
2566                     &io32
->pfrio_nzero
, io32
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2569         case DIOCRSETTFLAGS
: 
2570                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_table
)) { 
2574                 error 
= pfr_set_tflags(io32
->pfrio_buffer
, io32
->pfrio_size
, 
2575                     io32
->pfrio_setflag
, io32
->pfrio_clrflag
, 
2576                     &io32
->pfrio_nchange
, &io32
->pfrio_ndel
, 
2577                     io32
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2581                 if (io32
->pfrio_esize 
!= 0) { 
2585                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2586                 error 
= pfr_clr_addrs(&io32
->pfrio_table
, &io32
->pfrio_ndel
, 
2587                     io32
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2591                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2595                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2596                 error 
= pfr_add_addrs(&io32
->pfrio_table
, io32
->pfrio_buffer
, 
2597                     io32
->pfrio_size
, &io32
->pfrio_nadd
, io32
->pfrio_flags 
| 
2598                     PFR_FLAG_USERIOCTL
); 
2602                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2606                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2607                 error 
= pfr_del_addrs(&io32
->pfrio_table
, io32
->pfrio_buffer
, 
2608                     io32
->pfrio_size
, &io32
->pfrio_ndel
, io32
->pfrio_flags 
| 
2609                     PFR_FLAG_USERIOCTL
); 
2613                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2617                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2618                 error 
= pfr_set_addrs(&io32
->pfrio_table
, io32
->pfrio_buffer
, 
2619                     io32
->pfrio_size
, &io32
->pfrio_size2
, &io32
->pfrio_nadd
, 
2620                     &io32
->pfrio_ndel
, &io32
->pfrio_nchange
, io32
->pfrio_flags 
| 
2621                     PFR_FLAG_USERIOCTL
, 0); 
2625                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2629                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2630                 error 
= pfr_get_addrs(&io32
->pfrio_table
, io32
->pfrio_buffer
, 
2631                     &io32
->pfrio_size
, io32
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2634         case DIOCRGETASTATS
: 
2635                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_astats
)) { 
2639                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2640                 error 
= pfr_get_astats(&io32
->pfrio_table
, io32
->pfrio_buffer
, 
2641                     &io32
->pfrio_size
, io32
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2644         case DIOCRCLRASTATS
: 
2645                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2649                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2650                 error 
= pfr_clr_astats(&io32
->pfrio_table
, io32
->pfrio_buffer
, 
2651                     io32
->pfrio_size
, &io32
->pfrio_nzero
, io32
->pfrio_flags 
| 
2652                     PFR_FLAG_USERIOCTL
); 
2656                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2660                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2661                 error 
= pfr_tst_addrs(&io32
->pfrio_table
, io32
->pfrio_buffer
, 
2662                     io32
->pfrio_size
, &io32
->pfrio_nmatch
, io32
->pfrio_flags 
| 
2663                     PFR_FLAG_USERIOCTL
); 
2666         case DIOCRINADEFINE
: 
2667                 if (io32
->pfrio_esize 
!= sizeof (struct pfr_addr
)) { 
2671                 pfr_table_copyin_cleanup(&io32
->pfrio_table
); 
2672                 error 
= pfr_ina_define(&io32
->pfrio_table
, io32
->pfrio_buffer
, 
2673                     io32
->pfrio_size
, &io32
->pfrio_nadd
, &io32
->pfrio_naddr
, 
2674                     io32
->pfrio_ticket
, io32
->pfrio_flags 
| PFR_FLAG_USERIOCTL
); 
2687 pfioctl_ioc_tokens(u_long cmd
, struct pfioc_tokens_32 
*tok32
, 
2688     struct pfioc_tokens_64 
*tok64
, struct proc 
*p
) 
2690         struct pfioc_token 
*tokens
; 
2691         struct pfioc_kernel_token 
*entry
, *tmp
; 
2692         user_addr_t token_buf
; 
2693         int ocnt
, cnt
, error 
= 0, p64 
= proc_is64bit(p
); 
2697         case DIOCGETSTARTERS
: { 
2700                 if (nr_tokens 
== 0) { 
2705                 size 
= sizeof (struct pfioc_token
) * nr_tokens
; 
2706                 ocnt 
= cnt 
= (p64 
? tok64
->size 
: tok32
->size
); 
2715                 token_buf 
= (p64 
? tok64
->pgt_buf 
: tok32
->pgt_buf
); 
2716                 tokens 
= _MALLOC(size
, M_TEMP
, M_WAITOK
|M_ZERO
); 
2717                 if (tokens 
== NULL
) { 
2722                 ptr 
= (void *)tokens
; 
2723                 SLIST_FOREACH_SAFE(entry
, &token_list_head
, next
, tmp
) { 
2724                         struct pfioc_token 
*t
; 
2726                         if ((unsigned)cnt 
< sizeof (*tokens
)) 
2727                                 break;    /* no more buffer space left */ 
2729                         t 
= (struct pfioc_token 
*)(void *)ptr
; 
2730                         t
->token_value  
= entry
->token
.token_value
; 
2731                         t
->timestamp    
= entry
->token
.timestamp
; 
2732                         t
->pid          
= entry
->token
.pid
; 
2733                         bcopy(entry
->token
.proc_name
, t
->proc_name
, 
2734                             PFTOK_PROCNAME_LEN
); 
2735                         ptr 
+= sizeof (struct pfioc_token
); 
2737                         cnt 
-= sizeof (struct pfioc_token
); 
2741                         error 
= copyout(tokens
, token_buf
, ocnt 
- cnt
); 
2744                         tok64
->size 
= ocnt 
- cnt
; 
2746                         tok32
->size 
= ocnt 
- cnt
; 
2748                 _FREE(tokens
, M_TEMP
); 
2761 pf_expire_states_and_src_nodes(struct pf_rule 
*rule
) 
2763         struct pf_state         
*state
; 
2764         struct pf_src_node      
*sn
; 
2767         /* expire the states */ 
2768         state 
= TAILQ_FIRST(&state_list
); 
2770                 if (state
->rule
.ptr 
== rule
) 
2771                         state
->timeout 
= PFTM_PURGE
; 
2772                 state 
= TAILQ_NEXT(state
, entry_list
); 
2774         pf_purge_expired_states(pf_status
.states
); 
2776         /* expire the src_nodes */ 
2777         RB_FOREACH(sn
, pf_src_tree
, &tree_src_tracking
) { 
2778                 if (sn
->rule
.ptr 
!= rule
) 
2780                 if (sn
->states 
!= 0) { 
2781                         RB_FOREACH(state
, pf_state_tree_id
, 
2783                                 if (state
->src_node 
== sn
) 
2784                                         state
->src_node 
= NULL
; 
2785                                 if (state
->nat_src_node 
== sn
) 
2786                                         state
->nat_src_node 
= NULL
; 
2794                 pf_purge_expired_src_nodes(); 
2798 pf_delete_rule_from_ruleset(struct pf_ruleset 
*ruleset
, int rs_num
, 
2799     struct pf_rule 
*rule
) 
2804         pf_expire_states_and_src_nodes(rule
); 
2806         pf_rm_rule(ruleset
->rules
[rs_num
].active
.ptr
, rule
); 
2807         if (ruleset
->rules
[rs_num
].active
.rcount
-- == 0) 
2808                 panic("%s: rcount value broken!", __func__
); 
2809         r 
= TAILQ_FIRST(ruleset
->rules
[rs_num
].active
.ptr
); 
2813                 r 
= TAILQ_NEXT(r
, entries
); 
2819 pf_ruleset_cleanup(struct pf_ruleset 
*ruleset
, int rs
) 
2821         pf_calc_skip_steps(ruleset
->rules
[rs
].active
.ptr
); 
2822         ruleset
->rules
[rs
].active
.ticket 
= 
2823             ++ruleset
->rules
[rs
].inactive
.ticket
; 
2827  * req_dev encodes the PF interface. Currently, possible values are 
2831 pf_delete_rule_by_ticket(struct pfioc_rule 
*pr
, u_int32_t req_dev
) 
2833         struct pf_ruleset       
*ruleset
; 
2834         struct pf_rule          
*rule 
= NULL
; 
2839         is_anchor 
= (pr
->anchor_call
[0] != '\0'); 
2840         if ((ruleset 
= pf_find_ruleset_with_owner(pr
->anchor
, 
2841             pr
->rule
.owner
, is_anchor
, &error
)) == NULL
) 
2844         for (i 
= 0; i 
< PF_RULESET_MAX 
&& rule 
== NULL
; i
++) { 
2845                 rule 
= TAILQ_FIRST(ruleset
->rules
[i
].active
.ptr
); 
2846                 while (rule 
&& (rule
->ticket 
!= pr
->rule
.ticket
)) 
2847                         rule 
= TAILQ_NEXT(rule
, entries
); 
2854         if (strcmp(rule
->owner
, pr
->rule
.owner
)) 
2858         if (rule
->anchor 
&& (ruleset 
!= &pf_main_ruleset
) && 
2859             ((strcmp(ruleset
->anchor
->owner
, "")) == 0) && 
2860             ((ruleset
->rules
[i
].active
.rcount 
- 1) == 0)) { 
2861                 /* set rule & ruleset to parent and repeat */ 
2862                 struct pf_rule 
*delete_rule 
= rule
; 
2863                 struct pf_ruleset 
*delete_ruleset 
= ruleset
; 
2865 #define parent_ruleset          ruleset->anchor->parent->ruleset 
2866                 if (ruleset
->anchor
->parent 
== NULL
) 
2867                         ruleset 
= &pf_main_ruleset
; 
2869                         ruleset 
= &parent_ruleset
; 
2871                 rule 
= TAILQ_FIRST(ruleset
->rules
[i
].active
.ptr
); 
2873                     (rule
->anchor 
!= delete_ruleset
->anchor
)) 
2874                         rule 
= TAILQ_NEXT(rule
, entries
); 
2876                         panic("%s: rule not found!", __func__
); 
2879                  * if reqest device != rule's device, bail : 
2880                  * with error if ticket matches; 
2881                  * without error if ticket doesn't match (i.e. its just cleanup) 
2883                 if ((rule
->rule_flag 
& PFRULE_PFM
) ^ req_dev
) { 
2884                         if (rule
->ticket 
!= pr
->rule
.ticket
) { 
2891                 if (delete_rule
->rule_flag 
& PFRULE_PFM
) { 
2895                 pf_delete_rule_from_ruleset(delete_ruleset
, 
2897                 delete_ruleset
->rules
[i
].active
.ticket 
= 
2898                     ++delete_ruleset
->rules
[i
].inactive
.ticket
; 
2902                  * process deleting rule only if device that added the 
2903                  * rule matches device that issued the request 
2905                 if ((rule
->rule_flag 
& PFRULE_PFM
) ^ req_dev
) 
2907                 if (rule
->rule_flag 
& PFRULE_PFM
) 
2909                 pf_delete_rule_from_ruleset(ruleset
, i
, 
2911                 pf_ruleset_cleanup(ruleset
, i
); 
2918  * req_dev encodes the PF interface. Currently, possible values are 
2922 pf_delete_rule_by_owner(char *owner
, u_int32_t req_dev
) 
2924         struct pf_ruleset       
*ruleset
; 
2925         struct pf_rule          
*rule
, *next
; 
2928         for (int rs 
= 0; rs 
< PF_RULESET_MAX
; rs
++) { 
2929                 rule 
= TAILQ_FIRST(pf_main_ruleset
.rules
[rs
].active
.ptr
); 
2930                 ruleset 
= &pf_main_ruleset
; 
2932                         next 
= TAILQ_NEXT(rule
, entries
); 
2934                          * process deleting rule only if device that added the 
2935                          * rule matches device that issued the request 
2937                         if ((rule
->rule_flag 
& PFRULE_PFM
) ^ req_dev
) { 
2942                                 if (((strcmp(rule
->owner
, owner
)) == 0) || 
2943                                     ((strcmp(rule
->owner
, "")) == 0)) { 
2944                                         if (rule
->anchor
->ruleset
.rules
[rs
].active
.rcount 
> 0) { 
2946                                                         pf_ruleset_cleanup(ruleset
, rs
); 
2949                                                 /* step into anchor */ 
2951                                                     &rule
->anchor
->ruleset
; 
2952                                                 rule 
= TAILQ_FIRST(ruleset
->rules
[rs
].active
.ptr
); 
2955                                                 if (rule
->rule_flag 
& 
2958                                                 pf_delete_rule_from_ruleset(ruleset
, rs
, rule
); 
2965                                 if (((strcmp(rule
->owner
, owner
)) == 0)) { 
2967                                         if (rule
->rule_flag 
& PFRULE_PFM
) 
2969                                         pf_delete_rule_from_ruleset(ruleset
, 
2977                                         pf_ruleset_cleanup(ruleset
, rs
); 
2980                                 if (ruleset 
!= &pf_main_ruleset
) 
2981                                         pf_deleterule_anchor_step_out(&ruleset
, 
2989 pf_deleterule_anchor_step_out(struct pf_ruleset 
**ruleset_ptr
, 
2990     int rs
, struct pf_rule 
**rule_ptr
) 
2992         struct pf_ruleset 
*ruleset 
= *ruleset_ptr
; 
2993         struct pf_rule 
*rule 
= *rule_ptr
; 
2995         /* step out of anchor */ 
2996         struct pf_ruleset 
*rs_copy 
= ruleset
; 
2997         ruleset 
= ruleset
->anchor
->parent
? 
2998             &ruleset
->anchor
->parent
->ruleset
:&pf_main_ruleset
; 
3000         rule 
= TAILQ_FIRST(ruleset
->rules
[rs
].active
.ptr
); 
3001         while (rule 
&& (rule
->anchor 
!= rs_copy
->anchor
)) 
3002                 rule 
= TAILQ_NEXT(rule
, entries
); 
3004                 panic("%s: parent rule of anchor not found!", __func__
); 
3005         if (rule
->anchor
->ruleset
.rules
[rs
].active
.rcount 
> 0) 
3006                 rule 
= TAILQ_NEXT(rule
, entries
); 
3008         *ruleset_ptr 
= ruleset
; 
3013 pf_addrwrap_setup(struct pf_addr_wrap 
*aw
) 
3016         bzero(&aw
->p
, sizeof aw
->p
); 
3020 pf_rule_setup(struct pfioc_rule 
*pr
, struct pf_rule 
*rule
, 
3021     struct pf_ruleset 
*ruleset
) { 
3022         struct pf_pooladdr      
*apa
; 
3025         if (rule
->ifname
[0]) { 
3026                 rule
->kif 
= pfi_kif_get(rule
->ifname
); 
3027                 if (rule
->kif 
== NULL
) { 
3028                         pool_put(&pf_rule_pl
, rule
); 
3031                 pfi_kif_ref(rule
->kif
, PFI_KIF_REF_RULE
); 
3035         if (altq_allowed 
&& rule
->qname
[0] != '\0') { 
3036                 if ((rule
->qid 
= pf_qname2qid(rule
->qname
)) == 0) 
3038                 else if (rule
->pqname
[0] != '\0') { 
3040                             pf_qname2qid(rule
->pqname
)) == 0) 
3043                         rule
->pqid 
= rule
->qid
; 
3045 #endif /* PF_ALTQ */ 
3046         if (rule
->tagname
[0]) 
3047                 if ((rule
->tag 
= pf_tagname2tag(rule
->tagname
)) == 0) 
3049         if (rule
->match_tagname
[0]) 
3050                 if ((rule
->match_tag 
= 
3051                     pf_tagname2tag(rule
->match_tagname
)) == 0) 
3053         if (rule
->rt 
&& !rule
->direction
) 
3058         if (rule
->logif 
>= PFLOGIFS_MAX
) 
3061         pf_addrwrap_setup(&rule
->src
.addr
); 
3062         pf_addrwrap_setup(&rule
->dst
.addr
); 
3063         if (pf_rtlabel_add(&rule
->src
.addr
) || 
3064             pf_rtlabel_add(&rule
->dst
.addr
)) 
3066         if (pfi_dynaddr_setup(&rule
->src
.addr
, rule
->af
)) 
3068         if (pfi_dynaddr_setup(&rule
->dst
.addr
, rule
->af
)) 
3070         if (pf_tbladdr_setup(ruleset
, &rule
->src
.addr
)) 
3072         if (pf_tbladdr_setup(ruleset
, &rule
->dst
.addr
)) 
3074         if (pf_anchor_setup(rule
, ruleset
, pr
->anchor_call
)) 
3076         TAILQ_FOREACH(apa
, &pf_pabuf
, entries
) 
3077                 if (pf_tbladdr_setup(ruleset
, &apa
->addr
)) 
3080         if (rule
->overload_tblname
[0]) { 
3081                 if ((rule
->overload_tbl 
= pfr_attach_table(ruleset
, 
3082                     rule
->overload_tblname
)) == NULL
) 
3085                         rule
->overload_tbl
->pfrkt_flags 
|= 
3089         pf_mv_pool(&pf_pabuf
, &rule
->rpool
.list
); 
3090         if (((((rule
->action 
== PF_NAT
) || (rule
->action 
== PF_RDR
) || 
3091             (rule
->action 
== PF_BINAT
)) && rule
->anchor 
== NULL
) || 
3092             (rule
->rt 
> PF_FASTROUTE
)) && 
3093             (TAILQ_FIRST(&rule
->rpool
.list
) == NULL
)) 
3097                 pf_rm_rule(NULL
, rule
); 
3100         rule
->rpool
.cur 
= TAILQ_FIRST(&rule
->rpool
.list
); 
3101         rule
->evaluations 
= rule
->packets
[0] = rule
->packets
[1] = 
3102             rule
->bytes
[0] = rule
->bytes
[1] = 0; 
3108 pfioctl_ioc_rule(u_long cmd
, int minordev
, struct pfioc_rule 
*pr
, struct proc 
*p
) 
3111         u_int32_t req_dev 
= 0; 
3115                 struct pf_ruleset       
*ruleset
; 
3116                 struct pf_rule          
*rule
, *tail
; 
3119                 pr
->anchor
[sizeof (pr
->anchor
) - 1] = '\0'; 
3120                 pr
->anchor_call
[sizeof (pr
->anchor_call
) - 1] = '\0'; 
3121                 ruleset 
= pf_find_ruleset(pr
->anchor
); 
3122                 if (ruleset 
== NULL
) { 
3126                 rs_num 
= pf_get_ruleset_number(pr
->rule
.action
); 
3127                 if (rs_num 
>= PF_RULESET_MAX
) { 
3131                 if (pr
->rule
.return_icmp 
>> 8 > ICMP_MAXTYPE
) { 
3135                 if (pr
->ticket 
!= ruleset
->rules
[rs_num
].inactive
.ticket
) { 
3139                 if (pr
->pool_ticket 
!= ticket_pabuf
) { 
3143                 rule 
= pool_get(&pf_rule_pl
, PR_WAITOK
); 
3148                 pf_rule_copyin(&pr
->rule
, rule
, p
, minordev
); 
3150                 if (rule
->af 
== AF_INET
) { 
3151                         pool_put(&pf_rule_pl
, rule
); 
3152                         error 
= EAFNOSUPPORT
; 
3157                 if (rule
->af 
== AF_INET6
) { 
3158                         pool_put(&pf_rule_pl
, rule
); 
3159                         error 
= EAFNOSUPPORT
; 
3163                 tail 
= TAILQ_LAST(ruleset
->rules
[rs_num
].inactive
.ptr
, 
3166                         rule
->nr 
= tail
->nr 
+ 1; 
3170                 if ((error 
= pf_rule_setup(pr
, rule
, ruleset
))) 
3173                 TAILQ_INSERT_TAIL(ruleset
->rules
[rs_num
].inactive
.ptr
, 
3175                 ruleset
->rules
[rs_num
].inactive
.rcount
++; 
3176                 if (rule
->rule_flag 
& PFRULE_PFM
) 
3181         case DIOCGETRULES
: { 
3182                 struct pf_ruleset       
*ruleset
; 
3183                 struct pf_rule          
*tail
; 
3186                 pr
->anchor
[sizeof (pr
->anchor
) - 1] = '\0'; 
3187                 pr
->anchor_call
[sizeof (pr
->anchor_call
) - 1] = '\0'; 
3188                 ruleset 
= pf_find_ruleset(pr
->anchor
); 
3189                 if (ruleset 
== NULL
) { 
3193                 rs_num 
= pf_get_ruleset_number(pr
->rule
.action
); 
3194                 if (rs_num 
>= PF_RULESET_MAX
) { 
3198                 tail 
= TAILQ_LAST(ruleset
->rules
[rs_num
].active
.ptr
, 
3201                         pr
->nr 
= tail
->nr 
+ 1; 
3204                 pr
->ticket 
= ruleset
->rules
[rs_num
].active
.ticket
; 
3209                 struct pf_ruleset       
*ruleset
; 
3210                 struct pf_rule          
*rule
; 
3213                 pr
->anchor
[sizeof (pr
->anchor
) - 1] = '\0'; 
3214                 pr
->anchor_call
[sizeof (pr
->anchor_call
) - 1] = '\0'; 
3215                 ruleset 
= pf_find_ruleset(pr
->anchor
); 
3216                 if (ruleset 
== NULL
) { 
3220                 rs_num 
= pf_get_ruleset_number(pr
->rule
.action
); 
3221                 if (rs_num 
>= PF_RULESET_MAX
) { 
3225                 if (pr
->ticket 
!= ruleset
->rules
[rs_num
].active
.ticket
) { 
3229                 rule 
= TAILQ_FIRST(ruleset
->rules
[rs_num
].active
.ptr
); 
3230                 while ((rule 
!= NULL
) && (rule
->nr 
!= pr
->nr
)) 
3231                         rule 
= TAILQ_NEXT(rule
, entries
); 
3236                 pf_rule_copyout(rule
, &pr
->rule
); 
3237                 if (pf_anchor_copyout(ruleset
, rule
, pr
)) { 
3241                 pfi_dynaddr_copyout(&pr
->rule
.src
.addr
); 
3242                 pfi_dynaddr_copyout(&pr
->rule
.dst
.addr
); 
3243                 pf_tbladdr_copyout(&pr
->rule
.src
.addr
); 
3244                 pf_tbladdr_copyout(&pr
->rule
.dst
.addr
); 
3245                 pf_rtlabel_copyout(&pr
->rule
.src
.addr
); 
3246                 pf_rtlabel_copyout(&pr
->rule
.dst
.addr
); 
3247                 for (i 
= 0; i 
< PF_SKIP_COUNT
; ++i
) 
3248                         if (rule
->skip
[i
].ptr 
== NULL
) 
3249                                 pr
->rule
.skip
[i
].nr 
= -1; 
3251                                 pr
->rule
.skip
[i
].nr 
= 
3252                                     rule
->skip
[i
].ptr
->nr
; 
3254                 if (pr
->action 
== PF_GET_CLR_CNTR
) { 
3255                         rule
->evaluations 
= 0; 
3256                         rule
->packets
[0] = rule
->packets
[1] = 0; 
3257                         rule
->bytes
[0] = rule
->bytes
[1] = 0; 
3262         case DIOCCHANGERULE
: { 
3263                 struct pfioc_rule       
*pcr 
= pr
; 
3264                 struct pf_ruleset       
*ruleset
; 
3265                 struct pf_rule          
*oldrule 
= NULL
, *newrule 
= NULL
; 
3266                 struct pf_pooladdr      
*pa
; 
3270                 if (!(pcr
->action 
== PF_CHANGE_REMOVE 
|| 
3271                     pcr
->action 
== PF_CHANGE_GET_TICKET
) && 
3272                     pcr
->pool_ticket 
!= ticket_pabuf
) { 
3277                 if (pcr
->action 
< PF_CHANGE_ADD_HEAD 
|| 
3278                     pcr
->action 
> PF_CHANGE_GET_TICKET
) { 
3282                 pcr
->anchor
[sizeof (pcr
->anchor
) - 1] = '\0'; 
3283                 pcr
->anchor_call
[sizeof (pcr
->anchor_call
) - 1] = '\0'; 
3284                 ruleset 
= pf_find_ruleset(pcr
->anchor
); 
3285                 if (ruleset 
== NULL
) { 
3289                 rs_num 
= pf_get_ruleset_number(pcr
->rule
.action
); 
3290                 if (rs_num 
>= PF_RULESET_MAX
) { 
3295                 if (pcr
->action 
== PF_CHANGE_GET_TICKET
) { 
3296                         pcr
->ticket 
= ++ruleset
->rules
[rs_num
].active
.ticket
; 
3300                             ruleset
->rules
[rs_num
].active
.ticket
) { 
3304                         if (pcr
->rule
.return_icmp 
>> 8 > ICMP_MAXTYPE
) { 
3310                 if (pcr
->action 
!= PF_CHANGE_REMOVE
) { 
3311                         newrule 
= pool_get(&pf_rule_pl
, PR_WAITOK
); 
3312                         if (newrule 
== NULL
) { 
3316                         pf_rule_copyin(&pcr
->rule
, newrule
, p
, minordev
); 
3318                         if (newrule
->af 
== AF_INET
) { 
3319                                 pool_put(&pf_rule_pl
, newrule
); 
3320                                 error 
= EAFNOSUPPORT
; 
3325                         if (newrule
->af 
== AF_INET6
) { 
3326                                 pool_put(&pf_rule_pl
, newrule
); 
3327                                 error 
= EAFNOSUPPORT
; 
3331                         if (newrule
->ifname
[0]) { 
3332                                 newrule
->kif 
= pfi_kif_get(newrule
->ifname
); 
3333                                 if (newrule
->kif 
== NULL
) { 
3334                                         pool_put(&pf_rule_pl
, newrule
); 
3338                                 pfi_kif_ref(newrule
->kif
, PFI_KIF_REF_RULE
); 
3340                                 newrule
->kif 
= NULL
; 
3344                         if (altq_allowed 
&& newrule
->qname
[0] != '\0') { 
3346                                     pf_qname2qid(newrule
->qname
)) == 0) 
3348                                 else if (newrule
->pqname
[0] != '\0') { 
3349                                         if ((newrule
->pqid 
= 
3350                                             pf_qname2qid(newrule
->pqname
)) == 0) 
3353                                         newrule
->pqid 
= newrule
->qid
; 
3355 #endif /* PF_ALTQ */ 
3356                         if (newrule
->tagname
[0]) 
3358                                     pf_tagname2tag(newrule
->tagname
)) == 0) 
3360                         if (newrule
->match_tagname
[0]) 
3361                                 if ((newrule
->match_tag 
= pf_tagname2tag( 
3362                                     newrule
->match_tagname
)) == 0) 
3364                         if (newrule
->rt 
&& !newrule
->direction
) 
3369                         if (newrule
->logif 
>= PFLOGIFS_MAX
) 
3372                         pf_addrwrap_setup(&newrule
->src
.addr
); 
3373                         pf_addrwrap_setup(&newrule
->dst
.addr
); 
3374                         if (pf_rtlabel_add(&newrule
->src
.addr
) || 
3375                             pf_rtlabel_add(&newrule
->dst
.addr
)) 
3377                         if (pfi_dynaddr_setup(&newrule
->src
.addr
, newrule
->af
)) 
3379                         if (pfi_dynaddr_setup(&newrule
->dst
.addr
, newrule
->af
)) 
3381                         if (pf_tbladdr_setup(ruleset
, &newrule
->src
.addr
)) 
3383                         if (pf_tbladdr_setup(ruleset
, &newrule
->dst
.addr
)) 
3385                         if (pf_anchor_setup(newrule
, ruleset
, pcr
->anchor_call
)) 
3387                         TAILQ_FOREACH(pa
, &pf_pabuf
, entries
) 
3388                                 if (pf_tbladdr_setup(ruleset
, &pa
->addr
)) 
3391                         if (newrule
->overload_tblname
[0]) { 
3392                                 if ((newrule
->overload_tbl 
= pfr_attach_table( 
3393                                     ruleset
, newrule
->overload_tblname
)) == 
3397                                         newrule
->overload_tbl
->pfrkt_flags 
|= 
3401                         pf_mv_pool(&pf_pabuf
, &newrule
->rpool
.list
); 
3402                         if (((((newrule
->action 
== PF_NAT
) || 
3403                             (newrule
->action 
== PF_RDR
) || 
3404                             (newrule
->action 
== PF_BINAT
) || 
3405                             (newrule
->rt 
> PF_FASTROUTE
)) && 
3406                             !newrule
->anchor
)) && 
3407                             (TAILQ_FIRST(&newrule
->rpool
.list
) == NULL
)) 
3411                                 pf_rm_rule(NULL
, newrule
); 
3414                         newrule
->rpool
.cur 
= TAILQ_FIRST(&newrule
->rpool
.list
); 
3415                         newrule
->evaluations 
= 0; 
3416                         newrule
->packets
[0] = newrule
->packets
[1] = 0; 
3417                         newrule
->bytes
[0] = newrule
->bytes
[1] = 0; 
3419                 pf_empty_pool(&pf_pabuf
); 
3421                 if (pcr
->action 
== PF_CHANGE_ADD_HEAD
) 
3422                         oldrule 
= TAILQ_FIRST( 
3423                             ruleset
->rules
[rs_num
].active
.ptr
); 
3424                 else if (pcr
->action 
== PF_CHANGE_ADD_TAIL
) 
3425                         oldrule 
= TAILQ_LAST( 
3426                             ruleset
->rules
[rs_num
].active
.ptr
, pf_rulequeue
); 
3428                         oldrule 
= TAILQ_FIRST( 
3429                             ruleset
->rules
[rs_num
].active
.ptr
); 
3430                         while ((oldrule 
!= NULL
) && (oldrule
->nr 
!= pcr
->nr
)) 
3431                                 oldrule 
= TAILQ_NEXT(oldrule
, entries
); 
3432                         if (oldrule 
== NULL
) { 
3433                                 if (newrule 
!= NULL
) 
3434                                         pf_rm_rule(NULL
, newrule
); 
3440                 if (pcr
->action 
== PF_CHANGE_REMOVE
) { 
3441                         pf_rm_rule(ruleset
->rules
[rs_num
].active
.ptr
, oldrule
); 
3442                         ruleset
->rules
[rs_num
].active
.rcount
--; 
3444                         if (oldrule 
== NULL
) 
3446                                     ruleset
->rules
[rs_num
].active
.ptr
, 
3448                         else if (pcr
->action 
== PF_CHANGE_ADD_HEAD 
|| 
3449                             pcr
->action 
== PF_CHANGE_ADD_BEFORE
) 
3450                                 TAILQ_INSERT_BEFORE(oldrule
, newrule
, entries
); 
3453                                     ruleset
->rules
[rs_num
].active
.ptr
, 
3454                                     oldrule
, newrule
, entries
); 
3455                         ruleset
->rules
[rs_num
].active
.rcount
++; 
3459                 TAILQ_FOREACH(oldrule
, 
3460                     ruleset
->rules
[rs_num
].active
.ptr
, entries
) 
3463                 ruleset
->rules
[rs_num
].active
.ticket
++; 
3465                 pf_calc_skip_steps(ruleset
->rules
[rs_num
].active
.ptr
); 
3466                 pf_remove_if_empty_ruleset(ruleset
); 
3471         case DIOCINSERTRULE
: { 
3472                 struct pf_ruleset       
*ruleset
; 
3473                 struct pf_rule          
*rule
, *tail
, *r
; 
3477                 pr
->anchor
[sizeof (pr
->anchor
) - 1] = '\0'; 
3478                 pr
->anchor_call
[sizeof (pr
->anchor_call
) - 1] = '\0'; 
3479                 is_anchor 
= (pr
->anchor_call
[0] != '\0'); 
3481                 if ((ruleset 
= pf_find_ruleset_with_owner(pr
->anchor
, 
3482                     pr
->rule
.owner
, is_anchor
, &error
)) == NULL
) 
3485                 rs_num 
= pf_get_ruleset_number(pr
->rule
.action
); 
3486                 if (rs_num 
>= PF_RULESET_MAX
) { 
3490                 if (pr
->rule
.return_icmp 
>> 8 > ICMP_MAXTYPE
) { 
3495                 /* make sure this anchor rule doesn't exist already */ 
3497                         r 
= TAILQ_FIRST(ruleset
->rules
[rs_num
].active
.ptr
); 
3500                                     ((strcmp(r
->anchor
->name
, 
3501                                     pr
->anchor_call
)) == 0)) { 
3502                                         if (((strcmp(pr
->rule
.owner
, 
3504                                             ((strcmp(r
->owner
, "")) == 0)) 
3510                                 r 
= TAILQ_NEXT(r
, entries
); 
3516                 rule 
= pool_get(&pf_rule_pl
, PR_WAITOK
); 
3521                 pf_rule_copyin(&pr
->rule
, rule
, p
, minordev
); 
3523                 if (rule
->af 
== AF_INET
) { 
3524                         pool_put(&pf_rule_pl
, rule
); 
3525                         error 
= EAFNOSUPPORT
; 
3530                 if (rule
->af 
== AF_INET6
) { 
3531                         pool_put(&pf_rule_pl
, rule
); 
3532                         error 
= EAFNOSUPPORT
; 
3537                 r 
= TAILQ_FIRST(ruleset
->rules
[rs_num
].active
.ptr
); 
3538                 while ((r 
!= NULL
) && (rule
->priority 
>= (unsigned)r
->priority
)) 
3539                         r 
= TAILQ_NEXT(r
, entries
); 
3542                             TAILQ_LAST(ruleset
->rules
[rs_num
].active
.ptr
, 
3543                             pf_rulequeue
)) != NULL
) 
3544                                 rule
->nr 
= tail
->nr 
+ 1; 
3551                 if ((error 
= pf_rule_setup(pr
, rule
, ruleset
))) 
3554                 if (rule
->anchor 
!= NULL
) 
3555                         strlcpy(rule
->anchor
->owner
, rule
->owner
, 
3556                             PF_OWNER_NAME_SIZE
); 
3559                         TAILQ_INSERT_BEFORE(r
, rule
, entries
); 
3560                         while (r 
&& ++r
->nr
) 
3561                                 r 
= TAILQ_NEXT(r
, entries
); 
3563                         TAILQ_INSERT_TAIL(ruleset
->rules
[rs_num
].active
.ptr
, 
3565                 ruleset
->rules
[rs_num
].active
.rcount
++; 
3567                 /* Calculate checksum for the main ruleset */ 
3568                 if (ruleset 
== &pf_main_ruleset
) 
3569                         error 
= pf_setup_pfsync_matching(ruleset
); 
3571                 pf_ruleset_cleanup(ruleset
, rs_num
); 
3572                 rule
->ticket 
= VM_KERNEL_ADDRPERM((u_int64_t
)(uintptr_t)rule
); 
3574                 pr
->rule
.ticket 
= rule
->ticket
; 
3575                 pf_rule_copyout(rule
, &pr
->rule
); 
3576                 if (rule
->rule_flag 
& PFRULE_PFM
) 
3581         case DIOCDELETERULE
: { 
3582                 pr
->anchor
[sizeof (pr
->anchor
) - 1] = '\0'; 
3583                 pr
->anchor_call
[sizeof (pr
->anchor_call
) - 1] = '\0'; 
3585                 if (pr
->rule
.return_icmp 
>> 8 > ICMP_MAXTYPE
) { 
3590                 /* get device through which request is made */ 
3591                 if ((uint8_t)minordev 
== PFDEV_PFM
) 
3592                         req_dev 
|= PFRULE_PFM
; 
3594                 if (pr
->rule
.ticket
) { 
3595                         if ((error 
= pf_delete_rule_by_ticket(pr
, req_dev
))) 
3598                         pf_delete_rule_by_owner(pr
->rule
.owner
, req_dev
); 
3612 pfioctl_ioc_state_kill(u_long cmd
, struct pfioc_state_kill 
*psk
, struct proc 
*p
) 
3617         psk
->psk_ifname
[sizeof (psk
->psk_ifname
) - 1] = '\0'; 
3618         psk
->psk_ownername
[sizeof(psk
->psk_ownername
) - 1] = '\0'; 
3620         bool ifname_matched 
= true; 
3621         bool owner_matched 
= true; 
3624         case DIOCCLRSTATES
: { 
3625                 struct pf_state         
*s
, *nexts
; 
3628                 for (s 
= RB_MIN(pf_state_tree_id
, &tree_id
); s
; s 
= nexts
) { 
3629                         nexts 
= RB_NEXT(pf_state_tree_id
, &tree_id
, s
); 
3631                          * Purge all states only when neither ifname 
3632                          * or owner is provided. If any of these are provided 
3633                          * we purge only the states with meta data that match 
3635                         bool unlink_state 
= false; 
3636                         ifname_matched 
= true; 
3637                         owner_matched 
= true; 
3639                         if (psk
->psk_ifname
[0] && 
3640                             strcmp(psk
->psk_ifname
, s
->kif
->pfik_name
)) { 
3641                                 ifname_matched 
= false; 
3644                         if (psk
->psk_ownername
[0] && 
3645                             ((NULL 
== s
->rule
.ptr
) || 
3646                              strcmp(psk
->psk_ownername
, s
->rule
.ptr
->owner
))) { 
3647                                 owner_matched 
= false; 
3650                         unlink_state 
= ifname_matched 
&& owner_matched
; 
3654                                 /* don't send out individual delete messages */ 
3655                                 s
->sync_flags 
= PFSTATE_NOSYNC
; 
3661                 psk
->psk_af 
= killed
; 
3663                 pfsync_clear_states(pf_status
.hostid
, psk
->psk_ifname
); 
3668         case DIOCKILLSTATES
: { 
3669                 struct pf_state         
*s
, *nexts
; 
3670                 struct pf_state_key     
*sk
; 
3671                 struct pf_state_host    
*src
, *dst
; 
3674                 for (s 
= RB_MIN(pf_state_tree_id
, &tree_id
); s
; 
3676                         nexts 
= RB_NEXT(pf_state_tree_id
, &tree_id
, s
); 
3678                         ifname_matched 
= true; 
3679                         owner_matched 
= true; 
3681                         if (psk
->psk_ifname
[0] && 
3682                             strcmp(psk
->psk_ifname
, s
->kif
->pfik_name
)) { 
3683                                 ifname_matched 
= false; 
3686                         if (psk
->psk_ownername
[0] && 
3687                             ((NULL 
== s
->rule
.ptr
) || 
3688                              strcmp(psk
->psk_ownername
, s
->rule
.ptr
->owner
))) { 
3689                                 owner_matched 
= false; 
3692                         if (sk
->direction 
== PF_OUT
) { 
3699                         if ((!psk
->psk_af 
|| sk
->af 
== psk
->psk_af
) && 
3700                             (!psk
->psk_proto 
|| psk
->psk_proto 
== sk
->proto
) && 
3701                             PF_MATCHA(psk
->psk_src
.neg
, 
3702                             &psk
->psk_src
.addr
.v
.a
.addr
, 
3703                             &psk
->psk_src
.addr
.v
.a
.mask
, 
3704                             &src
->addr
, sk
->af
) && 
3705                             PF_MATCHA(psk
->psk_dst
.neg
, 
3706                             &psk
->psk_dst
.addr
.v
.a
.addr
, 
3707                             &psk
->psk_dst
.addr
.v
.a
.mask
, 
3708                             &dst
->addr
, sk
->af
) && 
3709                             (pf_match_xport(psk
->psk_proto
, 
3710                             psk
->psk_proto_variant
, &psk
->psk_src
.xport
, 
3712                             (pf_match_xport(psk
->psk_proto
, 
3713                             psk
->psk_proto_variant
, &psk
->psk_dst
.xport
, 
3718                                 /* send immediate delete of state */ 
3719                                 pfsync_delete_state(s
); 
3720                                 s
->sync_flags 
|= PFSTATE_NOSYNC
; 
3726                 psk
->psk_af 
= killed
; 
3739 pfioctl_ioc_state(u_long cmd
, struct pfioc_state 
*ps
, struct proc 
*p
) 
3745         case DIOCADDSTATE
: { 
3746                 struct pfsync_state     
*sp 
= &ps
->state
; 
3748                 struct pf_state_key     
*sk
; 
3749                 struct pfi_kif          
*kif
; 
3751                 if (sp
->timeout 
>= PFTM_MAX
) { 
3755                 s 
= pool_get(&pf_state_pl
, PR_WAITOK
); 
3760                 bzero(s
, sizeof (struct pf_state
)); 
3761                 if ((sk 
= pf_alloc_state_key(s
, NULL
)) == NULL
) { 
3762                         pool_put(&pf_state_pl
, s
); 
3766                 pf_state_import(sp
, sk
, s
); 
3767                 kif 
= pfi_kif_get(sp
->ifname
); 
3769                         pool_put(&pf_state_pl
, s
); 
3770                         pool_put(&pf_state_key_pl
, sk
); 
3774                 TAILQ_INIT(&s
->unlink_hooks
); 
3775                 s
->state_key
->app_state 
= 0; 
3776                 if (pf_insert_state(kif
, s
)) { 
3777                         pfi_kif_unref(kif
, PFI_KIF_REF_NONE
); 
3778                         pool_put(&pf_state_pl
, s
); 
3782                 pf_default_rule
.states
++; 
3783                 VERIFY(pf_default_rule
.states 
!= 0); 
3787         case DIOCGETSTATE
: { 
3789                 struct pf_state_cmp      id_key
; 
3791                 bcopy(ps
->state
.id
, &id_key
.id
, sizeof (id_key
.id
)); 
3792                 id_key
.creatorid 
= ps
->state
.creatorid
; 
3794                 s 
= pf_find_state_byid(&id_key
); 
3800                 pf_state_export(&ps
->state
, s
->state_key
, s
); 
3813 pfioctl_ioc_states(u_long cmd
, struct pfioc_states_32 
*ps32
, 
3814     struct pfioc_states_64 
*ps64
, struct proc 
*p
) 
3816         int p64 
= proc_is64bit(p
); 
3820         case DIOCGETSTATES
: {           /* struct pfioc_states */ 
3821                 struct pf_state         
*state
; 
3822                 struct pfsync_state     
*pstore
; 
3827                 len 
= (p64 
? ps64
->ps_len 
: ps32
->ps_len
); 
3829                         size 
= sizeof (struct pfsync_state
) * pf_status
.states
; 
3831                                 ps64
->ps_len 
= size
; 
3833                                 ps32
->ps_len 
= size
; 
3837                 pstore 
= _MALLOC(sizeof (*pstore
), M_TEMP
, M_WAITOK
); 
3838                 if (pstore 
== NULL
) { 
3842                 buf 
= (p64 
? ps64
->ps_buf 
: ps32
->ps_buf
); 
3844                 state 
= TAILQ_FIRST(&state_list
); 
3846                         if (state
->timeout 
!= PFTM_UNLINKED
) { 
3847                                 if ((nr 
+ 1) * sizeof (*pstore
) > (unsigned)len
) 
3850                                 pf_state_export(pstore
, 
3851                                     state
->state_key
, state
); 
3852                                 error 
= copyout(pstore
, buf
, sizeof (*pstore
)); 
3854                                         _FREE(pstore
, M_TEMP
); 
3857                                 buf 
+= sizeof (*pstore
); 
3860                         state 
= TAILQ_NEXT(state
, entry_list
); 
3863                 size 
= sizeof (struct pfsync_state
) * nr
; 
3865                         ps64
->ps_len 
= size
; 
3867                         ps32
->ps_len 
= size
; 
3869                 _FREE(pstore
, M_TEMP
); 
3882 pfioctl_ioc_natlook(u_long cmd
, struct pfioc_natlook 
*pnl
, struct proc 
*p
) 
3889                 struct pf_state_key     
*sk
; 
3890                 struct pf_state         
*state
; 
3891                 struct pf_state_key_cmp  key
; 
3892                 int                      m 
= 0, direction 
= pnl
->direction
; 
3895                 key
.proto 
= pnl
->proto
; 
3896                 key
.proto_variant 
= pnl
->proto_variant
; 
3899                     PF_AZERO(&pnl
->saddr
, pnl
->af
) || 
3900                     PF_AZERO(&pnl
->daddr
, pnl
->af
) || 
3901                     ((pnl
->proto 
== IPPROTO_TCP 
|| 
3902                     pnl
->proto 
== IPPROTO_UDP
) && 
3903                     (!pnl
->dxport
.port 
|| !pnl
->sxport
.port
))) 
3907                          * userland gives us source and dest of connection, 
3908                          * reverse the lookup so we ask for what happens with 
3909                          * the return traffic, enabling us to find it in the 
3912                         if (direction 
== PF_IN
) { 
3913                                 PF_ACPY(&key
.ext
.addr
, &pnl
->daddr
, pnl
->af
); 
3914                                 memcpy(&key
.ext
.xport
, &pnl
->dxport
, 
3915                                     sizeof (key
.ext
.xport
)); 
3916                                 PF_ACPY(&key
.gwy
.addr
, &pnl
->saddr
, pnl
->af
); 
3917                                 memcpy(&key
.gwy
.xport
, &pnl
->sxport
, 
3918                                     sizeof (key
.gwy
.xport
)); 
3919                                 state 
= pf_find_state_all(&key
, PF_IN
, &m
); 
3921                                 PF_ACPY(&key
.lan
.addr
, &pnl
->daddr
, pnl
->af
); 
3922                                 memcpy(&key
.lan
.xport
, &pnl
->dxport
, 
3923                                     sizeof (key
.lan
.xport
)); 
3924                                 PF_ACPY(&key
.ext
.addr
, &pnl
->saddr
, pnl
->af
); 
3925                                 memcpy(&key
.ext
.xport
, &pnl
->sxport
, 
3926                                     sizeof (key
.ext
.xport
)); 
3927                                 state 
= pf_find_state_all(&key
, PF_OUT
, &m
); 
3930                                 error 
= E2BIG
;  /* more than one state */ 
3931                         else if (state 
!= NULL
) { 
3932                                 sk 
= state
->state_key
; 
3933                                 if (direction 
== PF_IN
) { 
3934                                         PF_ACPY(&pnl
->rsaddr
, &sk
->lan
.addr
, 
3936                                         memcpy(&pnl
->rsxport
, &sk
->lan
.xport
, 
3937                                             sizeof (pnl
->rsxport
)); 
3938                                         PF_ACPY(&pnl
->rdaddr
, &pnl
->daddr
, 
3940                                         memcpy(&pnl
->rdxport
, &pnl
->dxport
, 
3941                                             sizeof (pnl
->rdxport
)); 
3943                                         PF_ACPY(&pnl
->rdaddr
, &sk
->gwy
.addr
, 
3945                                         memcpy(&pnl
->rdxport
, &sk
->gwy
.xport
, 
3946                                             sizeof (pnl
->rdxport
)); 
3947                                         PF_ACPY(&pnl
->rsaddr
, &pnl
->saddr
, 
3949                                         memcpy(&pnl
->rsxport
, &pnl
->sxport
, 
3950                                             sizeof (pnl
->rsxport
)); 
3967 pfioctl_ioc_tm(u_long cmd
, struct pfioc_tm 
*pt
, struct proc 
*p
) 
3973         case DIOCSETTIMEOUT
: { 
3976                 if (pt
->timeout 
< 0 || pt
->timeout 
>= PFTM_MAX 
|| 
3981                 old 
= pf_default_rule
.timeout
[pt
->timeout
]; 
3982                 if (pt
->timeout 
== PFTM_INTERVAL 
&& pt
->seconds 
== 0) 
3984                 pf_default_rule
.timeout
[pt
->timeout
] = pt
->seconds
; 
3985                 if (pt
->timeout 
== PFTM_INTERVAL 
&& pt
->seconds 
< old
) 
3986                         wakeup(pf_purge_thread_fn
); 
3991         case DIOCGETTIMEOUT
: { 
3992                 if (pt
->timeout 
< 0 || pt
->timeout 
>= PFTM_MAX
) { 
3996                 pt
->seconds 
= pf_default_rule
.timeout
[pt
->timeout
]; 
4009 pfioctl_ioc_limit(u_long cmd
, struct pfioc_limit 
*pl
, struct proc 
*p
) 
4015         case DIOCGETLIMIT
: { 
4017                 if (pl
->index 
< 0 || pl
->index 
>= PF_LIMIT_MAX
) { 
4021                 pl
->limit 
= pf_pool_limits
[pl
->index
].limit
; 
4025         case DIOCSETLIMIT
: { 
4028                 if (pl
->index 
< 0 || pl
->index 
>= PF_LIMIT_MAX 
|| 
4029                     pf_pool_limits
[pl
->index
].pp 
== NULL
) { 
4033                 pool_sethardlimit(pf_pool_limits
[pl
->index
].pp
, 
4034                     pl
->limit
, NULL
, 0); 
4035                 old_limit 
= pf_pool_limits
[pl
->index
].limit
; 
4036                 pf_pool_limits
[pl
->index
].limit 
= pl
->limit
; 
4037                 pl
->limit 
= old_limit
; 
4050 pfioctl_ioc_pooladdr(u_long cmd
, struct pfioc_pooladdr 
*pp
, struct proc 
*p
) 
4053         struct pf_pooladdr 
*pa 
= NULL
; 
4054         struct pf_pool 
*pool 
= NULL
; 
4058         case DIOCBEGINADDRS
: { 
4059                 pf_empty_pool(&pf_pabuf
); 
4060                 pp
->ticket 
= ++ticket_pabuf
; 
4065                 pp
->anchor
[sizeof (pp
->anchor
) - 1] = '\0'; 
4066                 if (pp
->ticket 
!= ticket_pabuf
) { 
4071                 if (pp
->af 
== AF_INET
) { 
4072                         error 
= EAFNOSUPPORT
; 
4077                 if (pp
->af 
== AF_INET6
) { 
4078                         error 
= EAFNOSUPPORT
; 
4082                 if (pp
->addr
.addr
.type 
!= PF_ADDR_ADDRMASK 
&& 
4083                     pp
->addr
.addr
.type 
!= PF_ADDR_DYNIFTL 
&& 
4084                     pp
->addr
.addr
.type 
!= PF_ADDR_TABLE
) { 
4088                 pa 
= pool_get(&pf_pooladdr_pl
, PR_WAITOK
); 
4093                 pf_pooladdr_copyin(&pp
->addr
, pa
); 
4094                 if (pa
->ifname
[0]) { 
4095                         pa
->kif 
= pfi_kif_get(pa
->ifname
); 
4096                         if (pa
->kif 
== NULL
) { 
4097                                 pool_put(&pf_pooladdr_pl
, pa
); 
4101                         pfi_kif_ref(pa
->kif
, PFI_KIF_REF_RULE
); 
4103                 pf_addrwrap_setup(&pa
->addr
); 
4104                 if (pfi_dynaddr_setup(&pa
->addr
, pp
->af
)) { 
4105                         pfi_dynaddr_remove(&pa
->addr
); 
4106                         pfi_kif_unref(pa
->kif
, PFI_KIF_REF_RULE
); 
4107                         pool_put(&pf_pooladdr_pl
, pa
); 
4111                 TAILQ_INSERT_TAIL(&pf_pabuf
, pa
, entries
); 
4115         case DIOCGETADDRS
: { 
4117                 pp
->anchor
[sizeof (pp
->anchor
) - 1] = '\0'; 
4118                 pool 
= pf_get_pool(pp
->anchor
, pp
->ticket
, pp
->r_action
, 
4119                     pp
->r_num
, 0, 1, 0); 
4124                 TAILQ_FOREACH(pa
, &pool
->list
, entries
) 
4132                 pp
->anchor
[sizeof (pp
->anchor
) - 1] = '\0'; 
4133                 pool 
= pf_get_pool(pp
->anchor
, pp
->ticket
, pp
->r_action
, 
4134                     pp
->r_num
, 0, 1, 1); 
4139                 pa 
= TAILQ_FIRST(&pool
->list
); 
4140                 while ((pa 
!= NULL
) && (nr 
< pp
->nr
)) { 
4141                         pa 
= TAILQ_NEXT(pa
, entries
); 
4148                 pf_pooladdr_copyout(pa
, &pp
->addr
); 
4149                 pfi_dynaddr_copyout(&pp
->addr
.addr
); 
4150                 pf_tbladdr_copyout(&pp
->addr
.addr
); 
4151                 pf_rtlabel_copyout(&pp
->addr
.addr
); 
4155         case DIOCCHANGEADDR
: { 
4156                 struct pfioc_pooladdr   
*pca 
= pp
; 
4157                 struct pf_pooladdr      
*oldpa 
= NULL
, *newpa 
= NULL
; 
4158                 struct pf_ruleset       
*ruleset
; 
4160                 if (pca
->action 
< PF_CHANGE_ADD_HEAD 
|| 
4161                     pca
->action 
> PF_CHANGE_REMOVE
) { 
4165                 if (pca
->addr
.addr
.type 
!= PF_ADDR_ADDRMASK 
&& 
4166                     pca
->addr
.addr
.type 
!= PF_ADDR_DYNIFTL 
&& 
4167                     pca
->addr
.addr
.type 
!= PF_ADDR_TABLE
) { 
4172                 pca
->anchor
[sizeof (pca
->anchor
) - 1] = '\0'; 
4173                 ruleset 
= pf_find_ruleset(pca
->anchor
); 
4174                 if (ruleset 
== NULL
) { 
4178                 pool 
= pf_get_pool(pca
->anchor
, pca
->ticket
, pca
->r_action
, 
4179                     pca
->r_num
, pca
->r_last
, 1, 1); 
4184                 if (pca
->action 
!= PF_CHANGE_REMOVE
) { 
4185                         newpa 
= pool_get(&pf_pooladdr_pl
, PR_WAITOK
); 
4186                         if (newpa 
== NULL
) { 
4190                         pf_pooladdr_copyin(&pca
->addr
, newpa
); 
4192                         if (pca
->af 
== AF_INET
) { 
4193                                 pool_put(&pf_pooladdr_pl
, newpa
); 
4194                                 error 
= EAFNOSUPPORT
; 
4199                         if (pca
->af 
== AF_INET6
) { 
4200                                 pool_put(&pf_pooladdr_pl
, newpa
); 
4201                                 error 
= EAFNOSUPPORT
; 
4205                         if (newpa
->ifname
[0]) { 
4206                                 newpa
->kif 
= pfi_kif_get(newpa
->ifname
); 
4207                                 if (newpa
->kif 
== NULL
) { 
4208                                         pool_put(&pf_pooladdr_pl
, newpa
); 
4212                                 pfi_kif_ref(newpa
->kif
, PFI_KIF_REF_RULE
); 
4215                         pf_addrwrap_setup(&newpa
->addr
); 
4216                         if (pfi_dynaddr_setup(&newpa
->addr
, pca
->af
) || 
4217                             pf_tbladdr_setup(ruleset
, &newpa
->addr
)) { 
4218                                 pfi_dynaddr_remove(&newpa
->addr
); 
4219                                 pfi_kif_unref(newpa
->kif
, PFI_KIF_REF_RULE
); 
4220                                 pool_put(&pf_pooladdr_pl
, newpa
); 
4226                 if (pca
->action 
== PF_CHANGE_ADD_HEAD
) 
4227                         oldpa 
= TAILQ_FIRST(&pool
->list
); 
4228                 else if (pca
->action 
== PF_CHANGE_ADD_TAIL
) 
4229                         oldpa 
= TAILQ_LAST(&pool
->list
, pf_palist
); 
4233                         oldpa 
= TAILQ_FIRST(&pool
->list
); 
4234                         while ((oldpa 
!= NULL
) && (i 
< (int)pca
->nr
)) { 
4235                                 oldpa 
= TAILQ_NEXT(oldpa
, entries
); 
4238                         if (oldpa 
== NULL
) { 
4244                 if (pca
->action 
== PF_CHANGE_REMOVE
) { 
4245                         TAILQ_REMOVE(&pool
->list
, oldpa
, entries
); 
4246                         pfi_dynaddr_remove(&oldpa
->addr
); 
4247                         pf_tbladdr_remove(&oldpa
->addr
); 
4248                         pfi_kif_unref(oldpa
->kif
, PFI_KIF_REF_RULE
); 
4249                         pool_put(&pf_pooladdr_pl
, oldpa
); 
4252                                 TAILQ_INSERT_TAIL(&pool
->list
, newpa
, entries
); 
4253                         else if (pca
->action 
== PF_CHANGE_ADD_HEAD 
|| 
4254                             pca
->action 
== PF_CHANGE_ADD_BEFORE
) 
4255                                 TAILQ_INSERT_BEFORE(oldpa
, newpa
, entries
); 
4257                                 TAILQ_INSERT_AFTER(&pool
->list
, oldpa
, 
4261                 pool
->cur 
= TAILQ_FIRST(&pool
->list
); 
4262                 PF_ACPY(&pool
->counter
, &pool
->cur
->addr
.v
.a
.addr
, 
4276 pfioctl_ioc_ruleset(u_long cmd
, struct pfioc_ruleset 
*pr
, struct proc 
*p
) 
4282         case DIOCGETRULESETS
: { 
4283                 struct pf_ruleset       
*ruleset
; 
4284                 struct pf_anchor        
*anchor
; 
4286                 pr
->path
[sizeof (pr
->path
) - 1] = '\0'; 
4287                 pr
->name
[sizeof (pr
->name
) - 1] = '\0'; 
4288                 if ((ruleset 
= pf_find_ruleset(pr
->path
)) == NULL
) { 
4293                 if (ruleset
->anchor 
== NULL
) { 
4294                         /* XXX kludge for pf_main_ruleset */ 
4295                         RB_FOREACH(anchor
, pf_anchor_global
, &pf_anchors
) 
4296                                 if (anchor
->parent 
== NULL
) 
4299                         RB_FOREACH(anchor
, pf_anchor_node
, 
4300                             &ruleset
->anchor
->children
) 
4306         case DIOCGETRULESET
: { 
4307                 struct pf_ruleset       
*ruleset
; 
4308                 struct pf_anchor        
*anchor
; 
4311                 pr
->path
[sizeof (pr
->path
) - 1] = '\0'; 
4312                 if ((ruleset 
= pf_find_ruleset(pr
->path
)) == NULL
) { 
4317                 if (ruleset
->anchor 
== NULL
) { 
4318                         /* XXX kludge for pf_main_ruleset */ 
4319                         RB_FOREACH(anchor
, pf_anchor_global
, &pf_anchors
) 
4320                                 if (anchor
->parent 
== NULL 
&& nr
++ == pr
->nr
) { 
4321                                         strlcpy(pr
->name
, anchor
->name
, 
4326                         RB_FOREACH(anchor
, pf_anchor_node
, 
4327                             &ruleset
->anchor
->children
) 
4328                                 if (nr
++ == pr
->nr
) { 
4329                                         strlcpy(pr
->name
, anchor
->name
, 
4348 pfioctl_ioc_trans(u_long cmd
, struct pfioc_trans_32 
*io32
, 
4349     struct pfioc_trans_64 
*io64
, struct proc 
*p
) 
4351         int p64 
= proc_is64bit(p
); 
4352         int error 
= 0, esize
, size
; 
4355         esize 
= (p64 
? io64
->esize 
: io32
->esize
); 
4356         size 
= (p64 
? io64
->size 
: io32
->size
); 
4357         buf 
= (p64 
? io64
->array 
: io32
->array
); 
4361                 struct pfioc_trans_e    
*ioe
; 
4362                 struct pfr_table        
*table
; 
4365                 if (esize 
!= sizeof (*ioe
)) { 
4369                 ioe 
= _MALLOC(sizeof (*ioe
), M_TEMP
, M_WAITOK
); 
4370                 table 
= _MALLOC(sizeof (*table
), M_TEMP
, M_WAITOK
); 
4371                 for (i 
= 0; i 
< size
; i
++, buf 
+= sizeof (*ioe
)) { 
4372                         if (copyin(buf
, ioe
, sizeof (*ioe
))) { 
4373                                 _FREE(table
, M_TEMP
); 
4378                         ioe
->anchor
[sizeof (ioe
->anchor
) - 1] = '\0'; 
4379                         switch (ioe
->rs_num
) { 
4380                         case PF_RULESET_ALTQ
: 
4383                                         if (ioe
->anchor
[0]) { 
4384                                                 _FREE(table
, M_TEMP
); 
4389                                         error 
= pf_begin_altq(&ioe
->ticket
); 
4391                                                 _FREE(table
, M_TEMP
); 
4396 #endif /* PF_ALTQ */ 
4398                         case PF_RULESET_TABLE
: 
4399                                 bzero(table
, sizeof (*table
)); 
4400                                 strlcpy(table
->pfrt_anchor
, ioe
->anchor
, 
4401                                     sizeof (table
->pfrt_anchor
)); 
4402                                 if ((error 
= pfr_ina_begin(table
, 
4403                                     &ioe
->ticket
, NULL
, 0))) { 
4404                                         _FREE(table
, M_TEMP
); 
4410                                 if ((error 
= pf_begin_rules(&ioe
->ticket
, 
4411                                     ioe
->rs_num
, ioe
->anchor
))) { 
4412                                         _FREE(table
, M_TEMP
); 
4418                         if (copyout(ioe
, buf
, sizeof (*ioe
))) { 
4419                                 _FREE(table
, M_TEMP
); 
4425                 _FREE(table
, M_TEMP
); 
4430         case DIOCXROLLBACK
: { 
4431                 struct pfioc_trans_e    
*ioe
; 
4432                 struct pfr_table        
*table
; 
4435                 if (esize 
!= sizeof (*ioe
)) { 
4439                 ioe 
= _MALLOC(sizeof (*ioe
), M_TEMP
, M_WAITOK
); 
4440                 table 
= _MALLOC(sizeof (*table
), M_TEMP
, M_WAITOK
); 
4441                 for (i 
= 0; i 
< size
; i
++, buf 
+= sizeof (*ioe
)) { 
4442                         if (copyin(buf
, ioe
, sizeof (*ioe
))) { 
4443                                 _FREE(table
, M_TEMP
); 
4448                         ioe
->anchor
[sizeof (ioe
->anchor
) - 1] = '\0'; 
4449                         switch (ioe
->rs_num
) { 
4450                         case PF_RULESET_ALTQ
: 
4453                                         if (ioe
->anchor
[0]) { 
4454                                                 _FREE(table
, M_TEMP
); 
4459                                         error 
= pf_rollback_altq(ioe
->ticket
); 
4461                                                 _FREE(table
, M_TEMP
); 
4463                                                 goto fail
; /* really bad */ 
4466 #endif /* PF_ALTQ */ 
4468                         case PF_RULESET_TABLE
: 
4469                                 bzero(table
, sizeof (*table
)); 
4470                                 strlcpy(table
->pfrt_anchor
, ioe
->anchor
, 
4471                                     sizeof (table
->pfrt_anchor
)); 
4472                                 if ((error 
= pfr_ina_rollback(table
, 
4473                                     ioe
->ticket
, NULL
, 0))) { 
4474                                         _FREE(table
, M_TEMP
); 
4476                                         goto fail
; /* really bad */ 
4480                                 if ((error 
= pf_rollback_rules(ioe
->ticket
, 
4481                                     ioe
->rs_num
, ioe
->anchor
))) { 
4482                                         _FREE(table
, M_TEMP
); 
4484                                         goto fail
; /* really bad */ 
4489                 _FREE(table
, M_TEMP
); 
4495                 struct pfioc_trans_e    
*ioe
; 
4496                 struct pfr_table        
*table
; 
4497                 struct pf_ruleset       
*rs
; 
4498                 user_addr_t              _buf 
= buf
; 
4501                 if (esize 
!= sizeof (*ioe
)) { 
4505                 ioe 
= _MALLOC(sizeof (*ioe
), M_TEMP
, M_WAITOK
); 
4506                 table 
= _MALLOC(sizeof (*table
), M_TEMP
, M_WAITOK
); 
4507                 /* first makes sure everything will succeed */ 
4508                 for (i 
= 0; i 
< size
; i
++, buf 
+= sizeof (*ioe
)) { 
4509                         if (copyin(buf
, ioe
, sizeof (*ioe
))) { 
4510                                 _FREE(table
, M_TEMP
); 
4515                         ioe
->anchor
[sizeof (ioe
->anchor
) - 1] = '\0'; 
4516                         switch (ioe
->rs_num
) { 
4517                         case PF_RULESET_ALTQ
: 
4520                                         if (ioe
->anchor
[0]) { 
4521                                                 _FREE(table
, M_TEMP
); 
4526                                         if (!altqs_inactive_open 
|| 
4528                                             ticket_altqs_inactive
) { 
4529                                                 _FREE(table
, M_TEMP
); 
4535 #endif /* PF_ALTQ */ 
4537                         case PF_RULESET_TABLE
: 
4538                                 rs 
= pf_find_ruleset(ioe
->anchor
); 
4539                                 if (rs 
== NULL 
|| !rs
->topen 
|| ioe
->ticket 
!= 
4541                                         _FREE(table
, M_TEMP
); 
4548                                 if (ioe
->rs_num 
< 0 || ioe
->rs_num 
>= 
4550                                         _FREE(table
, M_TEMP
); 
4555                                 rs 
= pf_find_ruleset(ioe
->anchor
); 
4557                                     !rs
->rules
[ioe
->rs_num
].inactive
.open 
|| 
4558                                     rs
->rules
[ioe
->rs_num
].inactive
.ticket 
!= 
4560                                         _FREE(table
, M_TEMP
); 
4569                 /* now do the commit - no errors should happen here */ 
4570                 for (i 
= 0; i 
< size
; i
++, buf 
+= sizeof (*ioe
)) { 
4571                         if (copyin(buf
, ioe
, sizeof (*ioe
))) { 
4572                                 _FREE(table
, M_TEMP
); 
4577                         ioe
->anchor
[sizeof (ioe
->anchor
) - 1] = '\0'; 
4578                         switch (ioe
->rs_num
) { 
4579                         case PF_RULESET_ALTQ
: 
4582                                     (error 
= pf_commit_altq(ioe
->ticket
))) { 
4583                                         _FREE(table
, M_TEMP
); 
4585                                         goto fail
; /* really bad */ 
4587 #endif /* PF_ALTQ */ 
4589                         case PF_RULESET_TABLE
: 
4590                                 bzero(table
, sizeof (*table
)); 
4591                                 strlcpy(table
->pfrt_anchor
, ioe
->anchor
, 
4592                                     sizeof (table
->pfrt_anchor
)); 
4593                                 if ((error 
= pfr_ina_commit(table
, ioe
->ticket
, 
4595                                         _FREE(table
, M_TEMP
); 
4597                                         goto fail
; /* really bad */ 
4601                                 if ((error 
= pf_commit_rules(ioe
->ticket
, 
4602                                     ioe
->rs_num
, ioe
->anchor
))) { 
4603                                         _FREE(table
, M_TEMP
); 
4605                                         goto fail
; /* really bad */ 
4610                 _FREE(table
, M_TEMP
); 
4624 pfioctl_ioc_src_nodes(u_long cmd
, struct pfioc_src_nodes_32 
*psn32
, 
4625     struct pfioc_src_nodes_64 
*psn64
, struct proc 
*p
) 
4627         int p64 
= proc_is64bit(p
); 
4631         case DIOCGETSRCNODES
: { 
4632                 struct pf_src_node      
*n
, *pstore
; 
4637                 space 
= (p64 
? psn64
->psn_len 
: psn32
->psn_len
); 
4639                         RB_FOREACH(n
, pf_src_tree
, &tree_src_tracking
) 
4642                         size 
= sizeof (struct pf_src_node
) * nr
; 
4644                                 psn64
->psn_len 
= size
; 
4646                                 psn32
->psn_len 
= size
; 
4650                 pstore 
= _MALLOC(sizeof (*pstore
), M_TEMP
, M_WAITOK
); 
4651                 if (pstore 
== NULL
) { 
4655                 buf 
= (p64 
? psn64
->psn_buf 
: psn32
->psn_buf
); 
4657                 RB_FOREACH(n
, pf_src_tree
, &tree_src_tracking
) { 
4658                         uint64_t secs 
= pf_time_second(), diff
; 
4660                         if ((nr 
+ 1) * sizeof (*pstore
) > (unsigned)space
) 
4663                         bcopy(n
, pstore
, sizeof (*pstore
)); 
4664                         if (n
->rule
.ptr 
!= NULL
) 
4665                                 pstore
->rule
.nr 
= n
->rule
.ptr
->nr
; 
4666                         pstore
->creation 
= secs 
- pstore
->creation
; 
4667                         if (pstore
->expire 
> secs
) 
4668                                 pstore
->expire 
-= secs
; 
4672                         /* adjust the connection rate estimate */ 
4673                         diff 
= secs 
- n
->conn_rate
.last
; 
4674                         if (diff 
>= n
->conn_rate
.seconds
) 
4675                                 pstore
->conn_rate
.count 
= 0; 
4677                                 pstore
->conn_rate
.count 
-= 
4678                                     n
->conn_rate
.count 
* diff 
/ 
4679                                     n
->conn_rate
.seconds
; 
4681                         _RB_PARENT(pstore
, entry
) = NULL
; 
4682                         RB_LEFT(pstore
, entry
) = RB_RIGHT(pstore
, entry
) = NULL
; 
4685                         error 
= copyout(pstore
, buf
, sizeof (*pstore
)); 
4687                                 _FREE(pstore
, M_TEMP
); 
4690                         buf 
+= sizeof (*pstore
); 
4694                 size 
= sizeof (struct pf_src_node
) * nr
; 
4696                         psn64
->psn_len 
= size
; 
4698                         psn32
->psn_len 
= size
; 
4700                 _FREE(pstore
, M_TEMP
); 
4714 pfioctl_ioc_src_node_kill(u_long cmd
, struct pfioc_src_node_kill 
*psnk
, 
4721         case DIOCKILLSRCNODES
: { 
4722                 struct pf_src_node      
*sn
; 
4726                 RB_FOREACH(sn
, pf_src_tree
, &tree_src_tracking
) { 
4727                         if (PF_MATCHA(psnk
->psnk_src
.neg
, 
4728                             &psnk
->psnk_src
.addr
.v
.a
.addr
, 
4729                             &psnk
->psnk_src
.addr
.v
.a
.mask
, 
4730                             &sn
->addr
, sn
->af
) && 
4731                             PF_MATCHA(psnk
->psnk_dst
.neg
, 
4732                             &psnk
->psnk_dst
.addr
.v
.a
.addr
, 
4733                             &psnk
->psnk_dst
.addr
.v
.a
.mask
, 
4734                             &sn
->raddr
, sn
->af
)) { 
4735                                 /* Handle state to src_node linkage */ 
4736                                 if (sn
->states 
!= 0) { 
4737                                         RB_FOREACH(s
, pf_state_tree_id
, 
4739                                                 if (s
->src_node 
== sn
) 
4741                                                 if (s
->nat_src_node 
== sn
) 
4742                                                         s
->nat_src_node 
= NULL
; 
4752                         pf_purge_expired_src_nodes(); 
4754                 psnk
->psnk_af 
= killed
; 
4767 pfioctl_ioc_iface(u_long cmd
, struct pfioc_iface_32 
*io32
, 
4768     struct pfioc_iface_64 
*io64
, struct proc 
*p
) 
4770         int p64 
= proc_is64bit(p
); 
4774         case DIOCIGETIFACES
: { 
4778                 buf 
= (p64 
? io64
->pfiio_buffer 
: io32
->pfiio_buffer
); 
4779                 esize 
= (p64 
? io64
->pfiio_esize 
: io32
->pfiio_esize
); 
4781                 /* esize must be that of the user space version of pfi_kif */ 
4782                 if (esize 
!= sizeof (struct pfi_uif
)) { 
4787                         io64
->pfiio_name
[sizeof (io64
->pfiio_name
) - 1] = '\0'; 
4789                         io32
->pfiio_name
[sizeof (io32
->pfiio_name
) - 1] = '\0'; 
4790                 error 
= pfi_get_ifaces( 
4791                     p64 
? io64
->pfiio_name 
: io32
->pfiio_name
, buf
, 
4792                     p64 
? &io64
->pfiio_size 
: &io32
->pfiio_size
); 
4796         case DIOCSETIFFLAG
: { 
4798                         io64
->pfiio_name
[sizeof (io64
->pfiio_name
) - 1] = '\0'; 
4800                         io32
->pfiio_name
[sizeof (io32
->pfiio_name
) - 1] = '\0'; 
4802                 error 
= pfi_set_flags( 
4803                     p64 
? io64
->pfiio_name 
: io32
->pfiio_name
, 
4804                     p64 
? io64
->pfiio_flags 
: io32
->pfiio_flags
); 
4808         case DIOCCLRIFFLAG
: { 
4810                         io64
->pfiio_name
[sizeof (io64
->pfiio_name
) - 1] = '\0'; 
4812                         io32
->pfiio_name
[sizeof (io32
->pfiio_name
) - 1] = '\0'; 
4814                 error 
= pfi_clear_flags( 
4815                     p64 
? io64
->pfiio_name 
: io32
->pfiio_name
, 
4816                     p64 
? io64
->pfiio_flags 
: io32
->pfiio_flags
); 
4829 pf_af_hook(struct ifnet 
*ifp
, struct mbuf 
**mppn
, struct mbuf 
**mp
, 
4830     unsigned int af
, int input
, struct ip_fw_args 
*fwa
) 
4833         struct mbuf 
*nextpkt
; 
4834         net_thread_marks_t marks
; 
4835         struct ifnet 
* pf_ifp 
= ifp
; 
4837         marks 
= net_thread_marks_push(NET_THREAD_HELD_PF
); 
4839         if (marks 
!= net_thread_marks_none
) { 
4840                 lck_rw_lock_shared(pf_perim_lock
); 
4843                 lck_mtx_lock(pf_lock
); 
4846         if (mppn 
!= NULL 
&& *mppn 
!= NULL
) 
4847                 VERIFY(*mppn 
== *mp
); 
4848         if ((nextpkt 
= (*mp
)->m_nextpkt
) != NULL
) 
4849                 (*mp
)->m_nextpkt 
= NULL
; 
4852          * For packets destined to locally hosted IP address 
4853          * ip_output_list sets Mbuf's pkt header's rcvif to 
4854          * the interface hosting the IP address. 
4855          * While on the output path ifp passed to pf_af_hook 
4856          * to such local communication is the loopback interface, 
4857          * the input path derives ifp from mbuf packet header's 
4859          * This asymmetry caues issues with PF. 
4860          * To handle that case, we have a limited change here to 
4861          * pass interface as loopback if packets are looped in. 
4863         if (input 
&& ((*mp
)->m_pkthdr
.pkt_flags 
& PKTF_LOOP
)) { 
4870                 error 
= pf_inet_hook(pf_ifp
, mp
, input
, fwa
); 
4876                 error 
= pf_inet6_hook(pf_ifp
, mp
, input
, fwa
); 
4883         /* When packet valid, link to the next packet */ 
4884         if (*mp 
!= NULL 
&& nextpkt 
!= NULL
) { 
4885                 struct mbuf 
*m 
= *mp
; 
4886                 while (m
->m_nextpkt 
!= NULL
) 
4888                 m
->m_nextpkt 
= nextpkt
; 
4890         /* Fix up linkage of previous packet in the chain */ 
4898         if (marks 
!= net_thread_marks_none
) 
4899                 lck_mtx_unlock(pf_lock
); 
4902         if (marks 
!= net_thread_marks_none
) 
4903                 lck_rw_done(pf_perim_lock
); 
4905         net_thread_marks_pop(marks
); 
4912 pf_inet_hook(struct ifnet 
*ifp
, struct mbuf 
**mp
, int input
, 
4913     struct ip_fw_args 
*fwa
) 
4915         struct mbuf 
*m 
= *mp
; 
4916 #if BYTE_ORDER != BIG_ENDIAN 
4917         struct ip 
*ip 
= mtod(m
, struct ip 
*); 
4922          * If the packet is outbound, is originated locally, is flagged for 
4923          * delayed UDP/TCP checksum calculation, and is about to be processed 
4924          * for an interface that doesn't support the appropriate checksum 
4925          * offloading, then calculated the checksum here so that PF can adjust 
4928         if (!input 
&& m
->m_pkthdr
.rcvif 
== NULL
) { 
4929                 static const int mask 
= CSUM_DELAY_DATA
; 
4930                 const int flags 
= m
->m_pkthdr
.csum_flags 
& 
4931                     ~IF_HWASSIST_CSUM_FLAGS(ifp
->if_hwassist
); 
4934                         in_delayed_cksum(m
); 
4935                         m
->m_pkthdr
.csum_flags 
&= ~mask
; 
4939 #if BYTE_ORDER != BIG_ENDIAN 
4943         if (pf_test(input 
? PF_IN 
: PF_OUT
, ifp
, mp
, NULL
, fwa
) != PF_PASS
) { 
4947                         error 
= EHOSTUNREACH
; 
4952 #if BYTE_ORDER != BIG_ENDIAN 
4955                         ip 
= mtod(*mp
, struct ip 
*); 
4967 pf_inet6_hook(struct ifnet 
*ifp
, struct mbuf 
**mp
, int input
, 
4968     struct ip_fw_args 
*fwa
) 
4973          * If the packet is outbound, is originated locally, is flagged for 
4974          * delayed UDP/TCP checksum calculation, and is about to be processed 
4975          * for an interface that doesn't support the appropriate checksum 
4976          * offloading, then calculated the checksum here so that PF can adjust 
4979         if (!input 
&& (*mp
)->m_pkthdr
.rcvif 
== NULL
) { 
4980                 static const int mask 
= CSUM_DELAY_IPV6_DATA
; 
4981                 const int flags 
= (*mp
)->m_pkthdr
.csum_flags 
& 
4982                     ~IF_HWASSIST_CSUM_FLAGS(ifp
->if_hwassist
); 
4986                          * Checksum offload should not have been enabled 
4987                          * when extension headers exist, thus 0 for optlen. 
4989                         in6_delayed_cksum(*mp
); 
4990                         (*mp
)->m_pkthdr
.csum_flags 
&= ~mask
; 
4994         if (pf_test6(input 
? PF_IN 
: PF_OUT
, ifp
, mp
, NULL
, fwa
) != PF_PASS
) { 
4998                         error 
= EHOSTUNREACH
; 
5008 pf_ifaddr_hook(struct ifnet 
*ifp
) 
5010         struct pfi_kif 
*kif 
= ifp
->if_pf_kif
; 
5013                 lck_rw_lock_shared(pf_perim_lock
); 
5014                 lck_mtx_lock(pf_lock
); 
5016                 pfi_kifaddr_update(kif
); 
5018                 lck_mtx_unlock(pf_lock
); 
5019                 lck_rw_done(pf_perim_lock
); 
5025  * Caller acquires dlil lock as writer (exclusive) 
5028 pf_ifnet_hook(struct ifnet 
*ifp
, int attach
) 
5030         lck_rw_lock_shared(pf_perim_lock
); 
5031         lck_mtx_lock(pf_lock
); 
5033                 pfi_attach_ifnet(ifp
); 
5035                 pfi_detach_ifnet(ifp
); 
5036         lck_mtx_unlock(pf_lock
); 
5037         lck_rw_done(pf_perim_lock
); 
5041 pf_attach_hooks(void) 
5043         ifnet_head_lock_shared(); 
5045          * Check against ifnet_addrs[] before proceeding, in case this 
5046          * is called very early on, e.g. during dlil_init() before any 
5047          * network interface is attached. 
5049         if (ifnet_addrs 
!= NULL
) { 
5052                 for (i 
= 0; i 
<= if_index
; i
++) { 
5053                         struct ifnet 
*ifp 
= ifindex2ifnet
[i
]; 
5055                                 pfi_attach_ifnet(ifp
); 
5063 /* currently unused along with pfdetach() */ 
5065 pf_detach_hooks(void) 
5067         ifnet_head_lock_shared(); 
5068         if (ifnet_addrs 
!= NULL
) { 
5069                 for (i 
= 0; i 
<= if_index
; i
++) { 
5072                         struct ifnet 
*ifp 
= ifindex2ifnet
[i
]; 
5073                         if (ifp 
!= NULL 
&& ifp
->if_pf_kif 
!= NULL
) { 
5074                                 pfi_detach_ifnet(ifp
); 
5085  * The switch statement below does nothing at runtime, as it serves as a 
5086  * compile time check to ensure that all of the socket 'D' ioctls (those 
5087  * in the 'D' group going thru soo_ioctl) that are made available by the 
5088  * networking stack is unique.  This works as long as this routine gets 
5089  * updated each time a new interface ioctl gets added. 
5091  * Any failures at compile time indicates duplicated ioctl values. 
5093 static __attribute__((unused
)) void 
5094 pfioctl_cassert(void) 
5097          * This is equivalent to _CASSERT() and the compiler wouldn't 
5098          * generate any instructions, thus for compile time only. 
5100         switch ((u_long
)0) { 
5103         /* bsd/net/pfvar.h */ 
5107         case DIOCGETSTARTERS
: 
5114         case DIOCSETSTATUSIF
: 
5120         case DIOCCHANGERULE
: 
5121         case DIOCINSERTRULE
: 
5122         case DIOCDELETERULE
: 
5123         case DIOCSETTIMEOUT
: 
5124         case DIOCGETTIMEOUT
: 
5126         case DIOCCLRRULECTRS
: 
5129         case DIOCKILLSTATES
: 
5135         case DIOCCHANGEALTQ
: 
5137         case DIOCBEGINADDRS
: 
5141         case DIOCCHANGEADDR
: 
5142         case DIOCGETRULESETS
: 
5143         case DIOCGETRULESET
: 
5144         case DIOCRCLRTABLES
: 
5145         case DIOCRADDTABLES
: 
5146         case DIOCRDELTABLES
: 
5147         case DIOCRGETTABLES
: 
5148         case DIOCRGETTSTATS
: 
5149         case DIOCRCLRTSTATS
: 
5155         case DIOCRGETASTATS
: 
5156         case DIOCRCLRASTATS
: 
5158         case DIOCRSETTFLAGS
: 
5159         case DIOCRINADEFINE
: 
5166         case DIOCGETSRCNODES
: 
5167         case DIOCCLRSRCNODES
: 
5169         case DIOCIGETIFACES
: 
5172         case DIOCKILLSRCNODES
: