1/*
2 * Copyright (c) 2007-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29/*	$apfw: git commit b6bf13f8321283cd7ee82b1795e86506084b1b95 $ */
30/*	$OpenBSD: pf_ioctl.c,v 1.175 2007/02/26 22:47:43 deraadt Exp $ */
31
32/*
33 * Copyright (c) 2001 Daniel Hartmeier
34 * Copyright (c) 2002,2003 Henning Brauer
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 *
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.
47 *
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.
60 *
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.
64 *
65 */
66
67#include <machine/endian.h>
68#include <sys/param.h>
69#include <sys/systm.h>
70#include <sys/mbuf.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>
76#include <sys/time.h>
77#include <sys/proc_internal.h>
78#include <sys/malloc.h>
79#include <sys/kauth.h>
80#include <sys/conf.h>
81#include <sys/mcache.h>
82#include <sys/queue.h>
83
84#include <mach/vm_param.h>
85
86#include <net/dlil.h>
87#include <net/if.h>
88#include <net/if_types.h>
89#include <net/route.h>
90
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>
98
99#if DUMMYNET
100#include <netinet/ip_dummynet.h>
101#else
102struct ip_fw_args;
103#endif /* DUMMYNET */
104
105#include <libkern/crypto/md5.h>
106
107#include <machine/machine_routines.h>
108
109#include <miscfs/devfs/devfs.h>
110
111#include <net/pfvar.h>
112
113#if NPFSYNC
114#include <net/if_pfsync.h>
115#endif /* NPFSYNC */
116
117#if PFLOG
118#include <net/if_pflog.h>
119#endif /* PFLOG */
120
121#if INET6
122#include <netinet/ip6.h>
123#include <netinet/in_pcb.h>
124#endif /* INET6 */
125
126#if PF_ALTQ
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>
133#endif /* PF_ALTQ */
134
135#if 0
136static void pfdetach(void);
137#endif
138static int pfopen(dev_t, int, int, struct proc *);
139static int pfclose(dev_t, int, int, struct proc *);
140static int pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
141static int pfioctl_ioc_table(u_long, struct pfioc_table_32 *,
142    struct pfioc_table_64 *, struct proc *);
143static int pfioctl_ioc_tokens(u_long, struct pfioc_tokens_32 *,
144    struct pfioc_tokens_64 *, struct proc *);
145static int pfioctl_ioc_rule(u_long, int, struct pfioc_rule *, struct proc *);
146static int pfioctl_ioc_state_kill(u_long, struct pfioc_state_kill *,
147    struct proc *);
148static int pfioctl_ioc_state(u_long, struct pfioc_state *, struct proc *);
149static int pfioctl_ioc_states(u_long, struct pfioc_states_32 *,
150    struct pfioc_states_64 *, struct proc *);
151static int pfioctl_ioc_natlook(u_long, struct pfioc_natlook *, struct proc *);
152static int pfioctl_ioc_tm(u_long, struct pfioc_tm *, struct proc *);
153static int pfioctl_ioc_limit(u_long, struct pfioc_limit *, struct proc *);
154static int pfioctl_ioc_pooladdr(u_long, struct pfioc_pooladdr *, struct proc *);
155static int pfioctl_ioc_ruleset(u_long, struct pfioc_ruleset *, struct proc *);
156static int pfioctl_ioc_trans(u_long, struct pfioc_trans_32 *,
157    struct pfioc_trans_64 *, struct proc *);
158static int pfioctl_ioc_src_nodes(u_long, struct pfioc_src_nodes_32 *,
159    struct pfioc_src_nodes_64 *, struct proc *);
160static int pfioctl_ioc_src_node_kill(u_long, struct pfioc_src_node_kill *,
161    struct proc *);
162static int pfioctl_ioc_iface(u_long, struct pfioc_iface_32 *,
163    struct pfioc_iface_64 *, struct proc *);
164static struct pf_pool *pf_get_pool(char *, u_int32_t, u_int8_t, u_int32_t,
165    u_int8_t, u_int8_t, u_int8_t);
166static void pf_mv_pool(struct pf_palist *, struct pf_palist *);
167static void pf_empty_pool(struct pf_palist *);
168#if PF_ALTQ
169static int pf_begin_altq(u_int32_t *);
170static int pf_rollback_altq(u_int32_t);
171static int pf_commit_altq(u_int32_t);
172static int pf_enable_altq(struct pf_altq *);
173static int pf_disable_altq(struct pf_altq *);
174static void pf_altq_copyin(struct pf_altq *, struct pf_altq *);
175static void pf_altq_copyout(struct pf_altq *, struct pf_altq *);
176#endif /* PF_ALTQ */
177static int pf_begin_rules(u_int32_t *, int, const char *);
178static int pf_rollback_rules(u_int32_t, int, char *);
179static int pf_setup_pfsync_matching(struct pf_ruleset *);
180static void pf_hash_rule(MD5_CTX *, struct pf_rule *);
181static void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *, u_int8_t);
182static int pf_commit_rules(u_int32_t, int, char *);
183static void pf_rule_copyin(struct pf_rule *, struct pf_rule *, struct proc *,
184    int);
185static void pf_rule_copyout(struct pf_rule *, struct pf_rule *);
186static void pf_state_export(struct pfsync_state *, struct pf_state_key *,
187    struct pf_state *);
188static void pf_state_import(struct pfsync_state *, struct pf_state_key *,
189    struct pf_state *);
190static void pf_pooladdr_copyin(struct pf_pooladdr *, struct pf_pooladdr *);
191static void pf_pooladdr_copyout(struct pf_pooladdr *, struct pf_pooladdr *);
192static void pf_expire_states_and_src_nodes(struct pf_rule *);
193static void pf_delete_rule_from_ruleset(struct pf_ruleset *,
194    int, struct pf_rule *);
195static int pf_rule_setup(struct pfioc_rule *, struct pf_rule *,
196    struct pf_ruleset *);
197static void pf_delete_rule_by_owner(char *);
198static int pf_delete_rule_by_ticket(struct pfioc_rule *);
199static void pf_ruleset_cleanup(struct pf_ruleset *, int);
200static void pf_deleterule_anchor_step_out(struct pf_ruleset **,
201    int, struct pf_rule **);
202
203#define	PF_CDEV_MAJOR	(-1)
204
205static struct cdevsw pf_cdevsw = {
206	/* open */	pfopen,
207	/* close */	pfclose,
208	/* read */	eno_rdwrt,
209	/* write */	eno_rdwrt,
210	/* ioctl */	pfioctl,
211	/* stop */	eno_stop,
212	/* reset */	eno_reset,
213	/* tty */	NULL,
214	/* select */	eno_select,
215	/* mmap */	eno_mmap,
216	/* strategy */	eno_strat,
217	/* getc */	eno_getc,
218	/* putc */	eno_putc,
219	/* type */	0
220};
221
222static void pf_attach_hooks(void);
223#if 0
224/* currently unused along with pfdetach() */
225static void pf_detach_hooks(void);
226#endif
227
228/*
229 * This is set during DIOCSTART/DIOCSTOP with pf_perim_lock held as writer,
230 * and used in pf_af_hook() for performance optimization, such that packets
231 * will enter pf_test() or pf_test6() only when PF is running.
232 */
233int pf_is_enabled = 0;
234
235#if PF_ALTQ
236u_int32_t altq_allowed = 0;
237#endif /* PF_ALTQ */
238
239u_int32_t pf_hash_seed;
240
241/*
242 * These are the pf enabled reference counting variables
243 */
244static u_int64_t pf_enabled_ref_count;
245static u_int32_t nr_tokens = 0;
246static u_int64_t pffwrules;
247static u_int32_t pfdevcnt;
248
249SLIST_HEAD(list_head, pfioc_kernel_token);
250static struct list_head token_list_head;
251
252struct pf_rule		 pf_default_rule;
253#if PF_ALTQ
254static int		 pf_altq_running;
255#endif /* PF_ALTQ */
256
257#define	TAGID_MAX	 50000
258#if !PF_ALTQ
259static TAILQ_HEAD(pf_tags, pf_tagname)	pf_tags =
260    TAILQ_HEAD_INITIALIZER(pf_tags);
261#else /* PF_ALTQ */
262static TAILQ_HEAD(pf_tags, pf_tagname)
263    pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags),
264    pf_qids = TAILQ_HEAD_INITIALIZER(pf_qids);
265#endif /* PF_ALTQ */
266
267#if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
268#error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
269#endif
270static u_int16_t	 tagname2tag(struct pf_tags *, char *);
271static void		 tag2tagname(struct pf_tags *, u_int16_t, char *);
272static void		 tag_unref(struct pf_tags *, u_int16_t);
273static int		 pf_rtlabel_add(struct pf_addr_wrap *);
274static void		 pf_rtlabel_remove(struct pf_addr_wrap *);
275static void		 pf_rtlabel_copyout(struct pf_addr_wrap *);
276
277#if INET
278static int pf_inet_hook(struct ifnet *, struct mbuf **, int,
279    struct ip_fw_args *);
280#endif /* INET */
281#if INET6
282static int pf_inet6_hook(struct ifnet *, struct mbuf **, int,
283    struct ip_fw_args *);
284#endif /* INET6 */
285
286#define	DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
287
288/*
289 * Helper macros for ioctl structures which vary in size (32-bit vs. 64-bit)
290 */
291#define	PFIOCX_STRUCT_DECL(s)						\
292struct {								\
293	union {								\
294		struct s##_32	_s##_32;				\
295		struct s##_64	_s##_64;				\
296	} _u;								\
297} *s##_un = NULL							\
298
299#define	PFIOCX_STRUCT_BEGIN(a, s, _action) {				\
300	VERIFY(s##_un == NULL);						\
301	s##_un = _MALLOC(sizeof (*s##_un), M_TEMP, M_WAITOK|M_ZERO);	\
302	if (s##_un == NULL) {						\
303		_action							\
304	} else {							\
305		if (p64)						\
306			bcopy(a, &s##_un->_u._s##_64,			\
307			    sizeof (struct s##_64));			\
308		else							\
309			bcopy(a, &s##_un->_u._s##_32,			\
310			    sizeof (struct s##_32));			\
311	}								\
312}
313
314#define	PFIOCX_STRUCT_END(s, a) {					\
315	VERIFY(s##_un != NULL);						\
316	if (p64)							\
317		bcopy(&s##_un->_u._s##_64, a, sizeof (struct s##_64));	\
318	else								\
319		bcopy(&s##_un->_u._s##_32, a, sizeof (struct s##_32));	\
320	_FREE(s##_un, M_TEMP);						\
321	s##_un = NULL;							\
322}
323
324#define	PFIOCX_STRUCT_ADDR32(s)		(&s##_un->_u._s##_32)
325#define	PFIOCX_STRUCT_ADDR64(s)		(&s##_un->_u._s##_64)
326
327/*
328 * Helper macros for regular ioctl structures.
329 */
330#define	PFIOC_STRUCT_BEGIN(a, v, _action) {				\
331	VERIFY((v) == NULL);						\
332	(v) = _MALLOC(sizeof (*(v)), M_TEMP, M_WAITOK|M_ZERO);		\
333	if ((v) == NULL) {						\
334		_action							\
335	} else {							\
336		bcopy(a, v, sizeof (*(v)));				\
337	}								\
338}
339
340#define	PFIOC_STRUCT_END(v, a) {					\
341	VERIFY((v) != NULL);						\
342	bcopy(v, a, sizeof (*(v)));					\
343	_FREE(v, M_TEMP);						\
344	(v) = NULL;							\
345}
346
347#define	PFIOC_STRUCT_ADDR32(s)		(&s##_un->_u._s##_32)
348#define	PFIOC_STRUCT_ADDR64(s)		(&s##_un->_u._s##_64)
349
350static lck_attr_t *pf_perim_lock_attr;
351static lck_grp_t *pf_perim_lock_grp;
352static lck_grp_attr_t *pf_perim_lock_grp_attr;
353
354static lck_attr_t *pf_lock_attr;
355static lck_grp_t *pf_lock_grp;
356static lck_grp_attr_t *pf_lock_grp_attr;
357
358struct thread *pf_purge_thread;
359
360extern void pfi_kifaddr_update(void *);
361
362/* pf enable ref-counting helper functions */
363static u_int64_t		generate_token(struct proc *);
364static int			remove_token(struct pfioc_remove_token *);
365static void			invalidate_all_tokens(void);
366
367static u_int64_t
368generate_token(struct proc *p)
369{
370	u_int64_t token_value;
371	struct pfioc_kernel_token *new_token;
372
373	new_token = _MALLOC(sizeof (struct pfioc_kernel_token), M_TEMP,
374	    M_WAITOK|M_ZERO);
375
376	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
377
378	if (new_token == NULL) {
379		/* malloc failed! bail! */
380		printf("%s: unable to allocate pf token structure!", __func__);
381		return (0);
382	}
383
384	token_value = (u_int64_t)(uintptr_t)new_token;
385
386	new_token->token.token_value = token_value;
387	new_token->token.pid = proc_pid(p);
388	proc_name(new_token->token.pid, new_token->token.proc_name,
389	    sizeof (new_token->token.proc_name));
390	new_token->token.timestamp = pf_calendar_time_second();
391
392	SLIST_INSERT_HEAD(&token_list_head, new_token, next);
393	nr_tokens++;
394
395	return (token_value);
396}
397
398static int
399remove_token(struct pfioc_remove_token *tok)
400{
401	struct pfioc_kernel_token *entry, *tmp;
402
403	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
404
405	SLIST_FOREACH_SAFE(entry, &token_list_head, next, tmp) {
406		if (tok->token_value == entry->token.token_value) {
407			SLIST_REMOVE(&token_list_head, entry,
408			    pfioc_kernel_token, next);
409			_FREE(entry, M_TEMP);
410			nr_tokens--;
411			return (0);    /* success */
412		}
413	}
414
415	printf("pf : remove failure\n");
416	return (ESRCH);    /* failure */
417}
418
419static void
420invalidate_all_tokens(void)
421{
422	struct pfioc_kernel_token *entry, *tmp;
423
424	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
425
426	SLIST_FOREACH_SAFE(entry, &token_list_head, next, tmp) {
427		SLIST_REMOVE(&token_list_head, entry, pfioc_kernel_token, next);
428		_FREE(entry, M_TEMP);
429	}
430
431	nr_tokens = 0;
432}
433
434void
435pfinit(void)
436{
437	u_int32_t *t = pf_default_rule.timeout;
438	int maj;
439
440	pf_perim_lock_grp_attr = lck_grp_attr_alloc_init();
441	pf_perim_lock_grp = lck_grp_alloc_init("pf_perim",
442	    pf_perim_lock_grp_attr);
443	pf_perim_lock_attr = lck_attr_alloc_init();
444	lck_rw_init(pf_perim_lock, pf_perim_lock_grp, pf_perim_lock_attr);
445
446	pf_lock_grp_attr = lck_grp_attr_alloc_init();
447	pf_lock_grp = lck_grp_alloc_init("pf", pf_lock_grp_attr);
448	pf_lock_attr = lck_attr_alloc_init();
449	lck_mtx_init(pf_lock, pf_lock_grp, pf_lock_attr);
450
451	pool_init(&pf_rule_pl, sizeof (struct pf_rule), 0, 0, 0, "pfrulepl",
452	    NULL);
453	pool_init(&pf_src_tree_pl, sizeof (struct pf_src_node), 0, 0, 0,
454	    "pfsrctrpl", NULL);
455	pool_init(&pf_state_pl, sizeof (struct pf_state), 0, 0, 0, "pfstatepl",
456	    NULL);
457	pool_init(&pf_state_key_pl, sizeof (struct pf_state_key), 0, 0, 0,
458	    "pfstatekeypl", NULL);
459	pool_init(&pf_app_state_pl, sizeof (struct pf_app_state), 0, 0, 0,
460	    "pfappstatepl", NULL);
461#if PF_ALTQ
462	pool_init(&pf_altq_pl, sizeof (struct pf_altq), 0, 0, 0, "pfaltqpl",
463	    NULL);
464#endif /* PF_ALTQ */
465	pool_init(&pf_pooladdr_pl, sizeof (struct pf_pooladdr), 0, 0, 0,
466	    "pfpooladdrpl", NULL);
467	pfr_initialize();
468	pfi_initialize();
469	pf_osfp_initialize();
470
471	pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp,
472	    pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0);
473
474	if (max_mem <= 256*1024*1024)
475		pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit =
476		    PFR_KENTRY_HIWAT_SMALL;
477
478	RB_INIT(&tree_src_tracking);
479	RB_INIT(&pf_anchors);
480	pf_init_ruleset(&pf_main_ruleset);
481	TAILQ_INIT(&pf_pabuf);
482	TAILQ_INIT(&state_list);
483#if PF_ALTQ
484	TAILQ_INIT(&pf_altqs[0]);
485	TAILQ_INIT(&pf_altqs[1]);
486	pf_altqs_active = &pf_altqs[0];
487	pf_altqs_inactive = &pf_altqs[1];
488
489	PE_parse_boot_argn("altq", &altq_allowed, sizeof (altq_allowed));
490
491	_CASSERT(ALTRQ_PURGE == CLASSQRQ_PURGE);
492	_CASSERT(ALTRQ_PURGE_SC == CLASSQRQ_PURGE_SC);
493	_CASSERT(ALTRQ_EVENT == CLASSQRQ_EVENT);
494
495	_CASSERT(ALTDQ_REMOVE == CLASSQDQ_REMOVE);
496	_CASSERT(ALTDQ_POLL == CLASSQDQ_POLL);
497#endif /* PF_ALTQ */
498
499	_CASSERT((SC_BE & SCIDX_MASK) == SCIDX_BE);
500	_CASSERT((SC_BK_SYS & SCIDX_MASK) == SCIDX_BK_SYS);
501	_CASSERT((SC_BK & SCIDX_MASK) == SCIDX_BK);
502	_CASSERT((SC_RD & SCIDX_MASK) == SCIDX_RD);
503	_CASSERT((SC_OAM & SCIDX_MASK) == SCIDX_OAM);
504	_CASSERT((SC_AV & SCIDX_MASK) == SCIDX_AV);
505	_CASSERT((SC_RV & SCIDX_MASK) == SCIDX_RV);
506	_CASSERT((SC_VI & SCIDX_MASK) == SCIDX_VI);
507	_CASSERT((SC_VO & SCIDX_MASK) == SCIDX_VO);
508	_CASSERT((SC_CTL & SCIDX_MASK) == SCIDX_CTL);
509
510	/* default rule should never be garbage collected */
511	pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
512	pf_default_rule.action = PF_PASS;
513	pf_default_rule.nr = -1;
514	pf_default_rule.rtableid = IFSCOPE_NONE;
515
516	/* initialize default timeouts */
517	t[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
518	t[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
519	t[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
520	t[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
521	t[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
522	t[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
523	t[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
524	t[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
525	t[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
526	t[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
527	t[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
528	t[PFTM_GREv1_FIRST_PACKET] = PFTM_GREv1_FIRST_PACKET_VAL;
529	t[PFTM_GREv1_INITIATING] = PFTM_GREv1_INITIATING_VAL;
530	t[PFTM_GREv1_ESTABLISHED] = PFTM_GREv1_ESTABLISHED_VAL;
531	t[PFTM_ESP_FIRST_PACKET] = PFTM_ESP_FIRST_PACKET_VAL;
532	t[PFTM_ESP_INITIATING] = PFTM_ESP_INITIATING_VAL;
533	t[PFTM_ESP_ESTABLISHED] = PFTM_ESP_ESTABLISHED_VAL;
534	t[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
535	t[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
536	t[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
537	t[PFTM_FRAG] = PFTM_FRAG_VAL;
538	t[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
539	t[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
540	t[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
541	t[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
542	t[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
543
544	pf_normalize_init();
545	bzero(&pf_status, sizeof (pf_status));
546	pf_status.debug = PF_DEBUG_URGENT;
547	pf_hash_seed = random();
548
549	/* XXX do our best to avoid a conflict */
550	pf_status.hostid = random();
551
552	if (kernel_thread_start(pf_purge_thread_fn, NULL,
553	    &pf_purge_thread) != 0) {
554		printf("%s: unable to start purge thread!", __func__);
555		return;
556	}
557
558	maj = cdevsw_add(PF_CDEV_MAJOR, &pf_cdevsw);
559	if (maj == -1) {
560		printf("%s: failed to allocate major number!\n", __func__);
561		return;
562	}
563	(void) devfs_make_node(makedev(maj, PFDEV_PF), DEVFS_CHAR,
564	    UID_ROOT, GID_WHEEL, 0600, "pf", 0);
565
566	(void) devfs_make_node(makedev(maj, PFDEV_PFM), DEVFS_CHAR,
567	    UID_ROOT, GID_WHEEL, 0600, "pfm", 0);
568
569	pf_attach_hooks();
570}
571
572#if 0
573static void
574pfdetach(void)
575{
576	struct pf_anchor	*anchor;
577	struct pf_state		*state;
578	struct pf_src_node	*node;
579	struct pfioc_table	pt;
580	u_int32_t		ticket;
581	int			i;
582	char			r = '\0';
583
584	pf_detach_hooks();
585
586	pf_status.running = 0;
587	wakeup(pf_purge_thread_fn);
588
589	/* clear the rulesets */
590	for (i = 0; i < PF_RULESET_MAX; i++)
591		if (pf_begin_rules(&ticket, i, &r) == 0)
592				pf_commit_rules(ticket, i, &r);
593#if PF_ALTQ
594	if (pf_begin_altq(&ticket) == 0)
595		pf_commit_altq(ticket);
596#endif /* PF_ALTQ */
597
598	/* clear states */
599	RB_FOREACH(state, pf_state_tree_id, &tree_id) {
600		state->timeout = PFTM_PURGE;
601#if NPFSYNC
602		state->sync_flags = PFSTATE_NOSYNC;
603#endif
604	}
605	pf_purge_expired_states(pf_status.states);
606
607#if NPFSYNC
608	pfsync_clear_states(pf_status.hostid, NULL);
609#endif
610
611	/* clear source nodes */
612	RB_FOREACH(state, pf_state_tree_id, &tree_id) {
613		state->src_node = NULL;
614		state->nat_src_node = NULL;
615	}
616	RB_FOREACH(node, pf_src_tree, &tree_src_tracking) {
617		node->expire = 1;
618		node->states = 0;
619	}
620	pf_purge_expired_src_nodes();
621
622	/* clear tables */
623	memset(&pt, '\0', sizeof (pt));
624	pfr_clr_tables(&pt.pfrio_table, &pt.pfrio_ndel, pt.pfrio_flags);
625
626	/* destroy anchors */
627	while ((anchor = RB_MIN(pf_anchor_global, &pf_anchors)) != NULL) {
628		for (i = 0; i < PF_RULESET_MAX; i++)
629			if (pf_begin_rules(&ticket, i, anchor->name) == 0)
630				pf_commit_rules(ticket, i, anchor->name);
631	}
632
633	/* destroy main ruleset */
634	pf_remove_if_empty_ruleset(&pf_main_ruleset);
635
636	/* destroy the pools */
637	pool_destroy(&pf_pooladdr_pl);
638#if PF_ALTQ
639	pool_destroy(&pf_altq_pl);
640#endif /* PF_ALTQ */
641	pool_destroy(&pf_state_pl);
642	pool_destroy(&pf_rule_pl);
643	pool_destroy(&pf_src_tree_pl);
644
645	/* destroy subsystems */
646	pf_normalize_destroy();
647	pf_osfp_destroy();
648	pfr_destroy();
649	pfi_destroy();
650}
651#endif
652
653static int
654pfopen(dev_t dev, int flags, int fmt, struct proc *p)
655{
656#pragma unused(flags, fmt, p)
657	if (minor(dev) >= PFDEV_MAX)
658		return (ENXIO);
659
660	if (minor(dev) == PFDEV_PFM) {
661		lck_mtx_lock(pf_lock);
662		if (pfdevcnt != 0) {
663			lck_mtx_unlock(pf_lock);
664			return (EBUSY);
665		}
666		pfdevcnt++;
667		lck_mtx_unlock(pf_lock);
668	}
669	return (0);
670}
671
672static int
673pfclose(dev_t dev, int flags, int fmt, struct proc *p)
674{
675#pragma unused(flags, fmt, p)
676	if (minor(dev) >= PFDEV_MAX)
677		return (ENXIO);
678
679	if (minor(dev) == PFDEV_PFM) {
680		lck_mtx_lock(pf_lock);
681		VERIFY(pfdevcnt > 0);
682		pfdevcnt--;
683		lck_mtx_unlock(pf_lock);
684	}
685	return (0);
686}
687
688static struct pf_pool *
689pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
690    u_int32_t rule_number, u_int8_t r_last, u_int8_t active,
691    u_int8_t check_ticket)
692{
693	struct pf_ruleset	*ruleset;
694	struct pf_rule		*rule;
695	int			 rs_num;
696
697	ruleset = pf_find_ruleset(anchor);
698	if (ruleset == NULL)
699		return (NULL);
700	rs_num = pf_get_ruleset_number(rule_action);
701	if (rs_num >= PF_RULESET_MAX)
702		return (NULL);
703	if (active) {
704		if (check_ticket && ticket !=
705		    ruleset->rules[rs_num].active.ticket)
706			return (NULL);
707		if (r_last)
708			rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
709			    pf_rulequeue);
710		else
711			rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
712	} else {
713		if (check_ticket && ticket !=
714		    ruleset->rules[rs_num].inactive.ticket)
715			return (NULL);
716		if (r_last)
717			rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
718			    pf_rulequeue);
719		else
720			rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr);
721	}
722	if (!r_last) {
723		while ((rule != NULL) && (rule->nr != rule_number))
724			rule = TAILQ_NEXT(rule, entries);
725	}
726	if (rule == NULL)
727		return (NULL);
728
729	return (&rule->rpool);
730}
731
732static void
733pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb)
734{
735	struct pf_pooladdr	*mv_pool_pa;
736
737	while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) {
738		TAILQ_REMOVE(poola, mv_pool_pa, entries);
739		TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries);
740	}
741}
742
743static void
744pf_empty_pool(struct pf_palist *poola)
745{
746	struct pf_pooladdr	*empty_pool_pa;
747
748	while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) {
749		pfi_dynaddr_remove(&empty_pool_pa->addr);
750		pf_tbladdr_remove(&empty_pool_pa->addr);
751		pfi_kif_unref(empty_pool_pa->kif, PFI_KIF_REF_RULE);
752		TAILQ_REMOVE(poola, empty_pool_pa, entries);
753		pool_put(&pf_pooladdr_pl, empty_pool_pa);
754	}
755}
756
757void
758pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
759{
760	if (rulequeue != NULL) {
761		if (rule->states <= 0) {
762			/*
763			 * XXX - we need to remove the table *before* detaching
764			 * the rule to make sure the table code does not delete
765			 * the anchor under our feet.
766			 */
767			pf_tbladdr_remove(&rule->src.addr);
768			pf_tbladdr_remove(&rule->dst.addr);
769			if (rule->overload_tbl)
770				pfr_detach_table(rule->overload_tbl);
771		}
772		TAILQ_REMOVE(rulequeue, rule, entries);
773		rule->entries.tqe_prev = NULL;
774		rule->nr = -1;
775	}
776
777	if (rule->states > 0 || rule->src_nodes > 0 ||
778	    rule->entries.tqe_prev != NULL)
779		return;
780	pf_tag_unref(rule->tag);
781	pf_tag_unref(rule->match_tag);
782#if PF_ALTQ
783	if (altq_allowed) {
784		if (rule->pqid != rule->qid)
785			pf_qid_unref(rule->pqid);
786		pf_qid_unref(rule->qid);
787	}
788#endif /* PF_ALTQ */
789	pf_rtlabel_remove(&rule->src.addr);
790	pf_rtlabel_remove(&rule->dst.addr);
791	pfi_dynaddr_remove(&rule->src.addr);
792	pfi_dynaddr_remove(&rule->dst.addr);
793	if (rulequeue == NULL) {
794		pf_tbladdr_remove(&rule->src.addr);
795		pf_tbladdr_remove(&rule->dst.addr);
796		if (rule->overload_tbl)
797			pfr_detach_table(rule->overload_tbl);
798	}
799	pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE);
800	pf_anchor_remove(rule);
801	pf_empty_pool(&rule->rpool.list);
802	pool_put(&pf_rule_pl, rule);
803}
804
805static u_int16_t
806tagname2tag(struct pf_tags *head, char *tagname)
807{
808	struct pf_tagname	*tag, *p = NULL;
809	u_int16_t		 new_tagid = 1;
810
811	TAILQ_FOREACH(tag, head, entries)
812		if (strcmp(tagname, tag->name) == 0) {
813			tag->ref++;
814			return (tag->tag);
815		}
816
817	/*
818	 * to avoid fragmentation, we do a linear search from the beginning
819	 * and take the first free slot we find. if there is none or the list
820	 * is empty, append a new entry at the end.
821	 */
822
823	/* new entry */
824	if (!TAILQ_EMPTY(head))
825		for (p = TAILQ_FIRST(head); p != NULL &&
826		    p->tag == new_tagid; p = TAILQ_NEXT(p, entries))
827			new_tagid = p->tag + 1;
828
829	if (new_tagid > TAGID_MAX)
830		return (0);
831
832	/* allocate and fill new struct pf_tagname */
833	tag = _MALLOC(sizeof (*tag), M_TEMP, M_WAITOK|M_ZERO);
834	if (tag == NULL)
835		return (0);
836	strlcpy(tag->name, tagname, sizeof (tag->name));
837	tag->tag = new_tagid;
838	tag->ref++;
839
840	if (p != NULL)	/* insert new entry before p */
841		TAILQ_INSERT_BEFORE(p, tag, entries);
842	else	/* either list empty or no free slot in between */
843		TAILQ_INSERT_TAIL(head, tag, entries);
844
845	return (tag->tag);
846}
847
848static void
849tag2tagname(struct pf_tags *head, u_int16_t tagid, char *p)
850{
851	struct pf_tagname	*tag;
852
853	TAILQ_FOREACH(tag, head, entries)
854		if (tag->tag == tagid) {
855			strlcpy(p, tag->name, PF_TAG_NAME_SIZE);
856			return;
857		}
858}
859
860static void
861tag_unref(struct pf_tags *head, u_int16_t tag)
862{
863	struct pf_tagname	*p, *next;
864
865	if (tag == 0)
866		return;
867
868	for (p = TAILQ_FIRST(head); p != NULL; p = next) {
869		next = TAILQ_NEXT(p, entries);
870		if (tag == p->tag) {
871			if (--p->ref == 0) {
872				TAILQ_REMOVE(head, p, entries);
873				_FREE(p, M_TEMP);
874			}
875			break;
876		}
877	}
878}
879
880u_int16_t
881pf_tagname2tag(char *tagname)
882{
883	return (tagname2tag(&pf_tags, tagname));
884}
885
886void
887pf_tag2tagname(u_int16_t tagid, char *p)
888{
889	tag2tagname(&pf_tags, tagid, p);
890}
891
892void
893pf_tag_ref(u_int16_t tag)
894{
895	struct pf_tagname *t;
896
897	TAILQ_FOREACH(t, &pf_tags, entries)
898		if (t->tag == tag)
899			break;
900	if (t != NULL)
901		t->ref++;
902}
903
904void
905pf_tag_unref(u_int16_t tag)
906{
907	tag_unref(&pf_tags, tag);
908}
909
910static int
911pf_rtlabel_add(struct pf_addr_wrap *a)
912{
913#pragma unused(a)
914	return (0);
915}
916
917static void
918pf_rtlabel_remove(struct pf_addr_wrap *a)
919{
920#pragma unused(a)
921}
922
923static void
924pf_rtlabel_copyout(struct pf_addr_wrap *a)
925{
926#pragma unused(a)
927}
928
929#if PF_ALTQ
930u_int32_t
931pf_qname2qid(char *qname)
932{
933	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
934
935	return ((u_int32_t)tagname2tag(&pf_qids, qname));
936}
937
938void
939pf_qid2qname(u_int32_t qid, char *p)
940{
941	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
942
943	tag2tagname(&pf_qids, (u_int16_t)qid, p);
944}
945
946void
947pf_qid_unref(u_int32_t qid)
948{
949	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
950
951	tag_unref(&pf_qids, (u_int16_t)qid);
952}
953
954static int
955pf_begin_altq(u_int32_t *ticket)
956{
957	struct pf_altq	*altq;
958	int		 error = 0;
959
960	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
961
962	/* Purge the old altq list */
963	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
964		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
965		if (altq->qname[0] == '\0') {
966			/* detach and destroy the discipline */
967			error = altq_remove(altq);
968		} else
969			pf_qid_unref(altq->qid);
970		pool_put(&pf_altq_pl, altq);
971	}
972	if (error)
973		return (error);
974	*ticket = ++ticket_altqs_inactive;
975	altqs_inactive_open = 1;
976	return (0);
977}
978
979static int
980pf_rollback_altq(u_int32_t ticket)
981{
982	struct pf_altq	*altq;
983	int		 error = 0;
984
985	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
986
987	if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
988		return (0);
989	/* Purge the old altq list */
990	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
991		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
992		if (altq->qname[0] == '\0') {
993			/* detach and destroy the discipline */
994			error = altq_remove(altq);
995		} else
996			pf_qid_unref(altq->qid);
997		pool_put(&pf_altq_pl, altq);
998	}
999	altqs_inactive_open = 0;
1000	return (error);
1001}
1002
1003static int
1004pf_commit_altq(u_int32_t ticket)
1005{
1006	struct pf_altqqueue	*old_altqs;
1007	struct pf_altq		*altq;
1008	int			 err, error = 0;
1009
1010	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
1011
1012	if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
1013		return (EBUSY);
1014
1015	/* swap altqs, keep the old. */
1016	old_altqs = pf_altqs_active;
1017	pf_altqs_active = pf_altqs_inactive;
1018	pf_altqs_inactive = old_altqs;
1019	ticket_altqs_active = ticket_altqs_inactive;
1020
1021	/* Attach new disciplines */
1022	TAILQ_FOREACH(altq, pf_altqs_active, entries) {
1023		if (altq->qname[0] == '\0') {
1024			/* attach the discipline */
1025			error = altq_pfattach(altq);
1026			if (error == 0 && pf_altq_running)
1027				error = pf_enable_altq(altq);
1028			if (error != 0) {
1029				return (error);
1030			}
1031		}
1032	}
1033
1034	/* Purge the old altq list */
1035	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
1036		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
1037		if (altq->qname[0] == '\0') {
1038			/* detach and destroy the discipline */
1039			if (pf_altq_running)
1040				error = pf_disable_altq(altq);
1041			err = altq_pfdetach(altq);
1042			if (err != 0 && error == 0)
1043				error = err;
1044			err = altq_remove(altq);
1045			if (err != 0 && error == 0)
1046				error = err;
1047		} else
1048			pf_qid_unref(altq->qid);
1049		pool_put(&pf_altq_pl, altq);
1050	}
1051
1052	altqs_inactive_open = 0;
1053	return (error);
1054}
1055
1056static int
1057pf_enable_altq(struct pf_altq *altq)
1058{
1059	struct ifnet		*ifp;
1060	struct ifclassq		*ifq;
1061	int			 error = 0;
1062
1063	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
1064
1065	if ((ifp = ifunit(altq->ifname)) == NULL)
1066		return (EINVAL);
1067
1068	ifq = &ifp->if_snd;
1069	IFCQ_LOCK(ifq);
1070	if (IFCQ_ALTQ(ifq)->altq_type != ALTQT_NONE)
1071		error = altq_enable(IFCQ_ALTQ(ifq));
1072
1073	/* set or clear tokenbucket regulator */
1074	if (error == 0 && ifp != NULL && ALTQ_IS_ENABLED(IFCQ_ALTQ(ifq))) {
1075		struct tb_profile tb = { 0, 0, 0 };
1076
1077		if (altq->aflags & PF_ALTQF_TBR) {
1078			if (altq->bwtype != PF_ALTQ_BW_ABSOLUTE &&
1079			    altq->bwtype != PF_ALTQ_BW_PERCENT) {
1080				error = EINVAL;
1081			} else {
1082				if (altq->bwtype == PF_ALTQ_BW_ABSOLUTE)
1083					tb.rate = altq->ifbandwidth;
1084				else
1085					tb.percent = altq->ifbandwidth;
1086				tb.depth = altq->tbrsize;
1087				error = ifclassq_tbr_set(ifq, &tb, TRUE);
1088			}
1089		} else if (IFCQ_TBR_IS_ENABLED(ifq)) {
1090			error = ifclassq_tbr_set(ifq, &tb, TRUE);
1091		}
1092	}
1093	IFCQ_UNLOCK(ifq);
1094
1095	return (error);
1096}
1097
1098static int
1099pf_disable_altq(struct pf_altq *altq)
1100{
1101	struct ifnet		*ifp;
1102	struct ifclassq		*ifq;
1103	int			 error;
1104
1105	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
1106
1107	if ((ifp = ifunit(altq->ifname)) == NULL)
1108		return (EINVAL);
1109
1110	/*
1111	 * when the discipline is no longer referenced, it was overridden
1112	 * by a new one.  if so, just return.
1113	 */
1114	ifq = &ifp->if_snd;
1115	IFCQ_LOCK(ifq);
1116	if (altq->altq_disc != IFCQ_ALTQ(ifq)->altq_disc) {
1117		IFCQ_UNLOCK(ifq);
1118		return (0);
1119	}
1120
1121	error = altq_disable(IFCQ_ALTQ(ifq));
1122
1123	if (error == 0 && IFCQ_TBR_IS_ENABLED(ifq)) {
1124		/* clear tokenbucket regulator */
1125		struct tb_profile  tb = { 0, 0, 0 };
1126		error = ifclassq_tbr_set(ifq, &tb, TRUE);
1127	}
1128	IFCQ_UNLOCK(ifq);
1129
1130	return (error);
1131}
1132
1133static void
1134pf_altq_copyin(struct pf_altq *src, struct pf_altq *dst)
1135{
1136	bcopy(src, dst, sizeof (struct pf_altq));
1137
1138	dst->ifname[sizeof (dst->ifname) - 1] = '\0';
1139	dst->qname[sizeof (dst->qname) - 1] = '\0';
1140	dst->parent[sizeof (dst->parent) - 1] = '\0';
1141	dst->altq_disc = NULL;
1142	dst->entries.tqe_next = NULL;
1143	dst->entries.tqe_prev = NULL;
1144}
1145
1146static void
1147pf_altq_copyout(struct pf_altq *src, struct pf_altq *dst)
1148{
1149	struct pf_altq pa;
1150
1151	bcopy(src, &pa, sizeof (struct pf_altq));
1152	pa.altq_disc = NULL;
1153	pa.entries.tqe_next = NULL;
1154	pa.entries.tqe_prev = NULL;
1155	bcopy(&pa, dst, sizeof (struct pf_altq));
1156}
1157#endif /* PF_ALTQ */
1158
1159static int
1160pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
1161{
1162	struct pf_ruleset	*rs;
1163	struct pf_rule		*rule;
1164
1165	if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
1166		return (EINVAL);
1167	rs = pf_find_or_create_ruleset(anchor);
1168	if (rs == NULL)
1169		return (EINVAL);
1170	while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
1171		pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
1172		rs->rules[rs_num].inactive.rcount--;
1173	}
1174	*ticket = ++rs->rules[rs_num].inactive.ticket;
1175	rs->rules[rs_num].inactive.open = 1;
1176	return (0);
1177}
1178
1179static int
1180pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor)
1181{
1182	struct pf_ruleset	*rs;
1183	struct pf_rule		*rule;
1184
1185	if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
1186		return (EINVAL);
1187	rs = pf_find_ruleset(anchor);
1188	if (rs == NULL || !rs->rules[rs_num].inactive.open ||
1189	    rs->rules[rs_num].inactive.ticket != ticket)
1190		return (0);
1191	while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
1192		pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
1193		rs->rules[rs_num].inactive.rcount--;
1194	}
1195	rs->rules[rs_num].inactive.open = 0;
1196	return (0);
1197}
1198
1199#define	PF_MD5_UPD(st, elm)						\
1200	MD5Update(ctx, (u_int8_t *)&(st)->elm, sizeof ((st)->elm))
1201
1202#define	PF_MD5_UPD_STR(st, elm)						\
1203	MD5Update(ctx, (u_int8_t *)(st)->elm, strlen((st)->elm))
1204
1205#define	PF_MD5_UPD_HTONL(st, elm, stor) do {				\
1206	(stor) = htonl((st)->elm);					\
1207	MD5Update(ctx, (u_int8_t *)&(stor), sizeof (u_int32_t));	\
1208} while (0)
1209
1210#define	PF_MD5_UPD_HTONS(st, elm, stor) do {				\
1211	(stor) = htons((st)->elm);					\
1212	MD5Update(ctx, (u_int8_t *)&(stor), sizeof (u_int16_t));	\
1213} while (0)
1214
1215static void
1216pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr, u_int8_t proto)
1217{
1218	PF_MD5_UPD(pfr, addr.type);
1219	switch (pfr->addr.type) {
1220	case PF_ADDR_DYNIFTL:
1221		PF_MD5_UPD(pfr, addr.v.ifname);
1222		PF_MD5_UPD(pfr, addr.iflags);
1223		break;
1224	case PF_ADDR_TABLE:
1225		PF_MD5_UPD(pfr, addr.v.tblname);
1226		break;
1227	case PF_ADDR_ADDRMASK:
1228		/* XXX ignore af? */
1229		PF_MD5_UPD(pfr, addr.v.a.addr.addr32);
1230		PF_MD5_UPD(pfr, addr.v.a.mask.addr32);
1231		break;
1232	case PF_ADDR_RTLABEL:
1233		PF_MD5_UPD(pfr, addr.v.rtlabelname);
1234		break;
1235	}
1236
1237	switch (proto) {
1238	case IPPROTO_TCP:
1239	case IPPROTO_UDP:
1240		PF_MD5_UPD(pfr, xport.range.port[0]);
1241		PF_MD5_UPD(pfr, xport.range.port[1]);
1242		PF_MD5_UPD(pfr, xport.range.op);
1243		break;
1244
1245	default:
1246		break;
1247	}
1248
1249	PF_MD5_UPD(pfr, neg);
1250}
1251
1252static void
1253pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule)
1254{
1255	u_int16_t x;
1256	u_int32_t y;
1257
1258	pf_hash_rule_addr(ctx, &rule->src, rule->proto);
1259	pf_hash_rule_addr(ctx, &rule->dst, rule->proto);
1260	PF_MD5_UPD_STR(rule, label);
1261	PF_MD5_UPD_STR(rule, ifname);
1262	PF_MD5_UPD_STR(rule, match_tagname);
1263	PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */
1264	PF_MD5_UPD_HTONL(rule, os_fingerprint, y);
1265	PF_MD5_UPD_HTONL(rule, prob, y);
1266	PF_MD5_UPD_HTONL(rule, uid.uid[0], y);
1267	PF_MD5_UPD_HTONL(rule, uid.uid[1], y);
1268	PF_MD5_UPD(rule, uid.op);
1269	PF_MD5_UPD_HTONL(rule, gid.gid[0], y);
1270	PF_MD5_UPD_HTONL(rule, gid.gid[1], y);
1271	PF_MD5_UPD(rule, gid.op);
1272	PF_MD5_UPD_HTONL(rule, rule_flag, y);
1273	PF_MD5_UPD(rule, action);
1274	PF_MD5_UPD(rule, direction);
1275	PF_MD5_UPD(rule, af);
1276	PF_MD5_UPD(rule, quick);
1277	PF_MD5_UPD(rule, ifnot);
1278	PF_MD5_UPD(rule, match_tag_not);
1279	PF_MD5_UPD(rule, natpass);
1280	PF_MD5_UPD(rule, keep_state);
1281	PF_MD5_UPD(rule, proto);
1282	PF_MD5_UPD(rule, type);
1283	PF_MD5_UPD(rule, code);
1284	PF_MD5_UPD(rule, flags);
1285	PF_MD5_UPD(rule, flagset);
1286	PF_MD5_UPD(rule, allow_opts);
1287	PF_MD5_UPD(rule, rt);
1288	PF_MD5_UPD(rule, tos);
1289}
1290
1291static int
1292pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
1293{
1294	struct pf_ruleset	*rs;
1295	struct pf_rule		*rule, **old_array;
1296	struct pf_rulequeue	*old_rules;
1297	int			 error;
1298	u_int32_t		 old_rcount;
1299
1300	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
1301
1302	if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
1303		return (EINVAL);
1304	rs = pf_find_ruleset(anchor);
1305	if (rs == NULL || !rs->rules[rs_num].inactive.open ||
1306	    ticket != rs->rules[rs_num].inactive.ticket)
1307		return (EBUSY);
1308
1309	/* Calculate checksum for the main ruleset */
1310	if (rs == &pf_main_ruleset) {
1311		error = pf_setup_pfsync_matching(rs);
1312		if (error != 0)
1313			return (error);
1314	}
1315
1316	/* Swap rules, keep the old. */
1317	old_rules = rs->rules[rs_num].active.ptr;
1318	old_rcount = rs->rules[rs_num].active.rcount;
1319	old_array = rs->rules[rs_num].active.ptr_array;
1320
1321	rs->rules[rs_num].active.ptr =
1322	    rs->rules[rs_num].inactive.ptr;
1323	rs->rules[rs_num].active.ptr_array =
1324	    rs->rules[rs_num].inactive.ptr_array;
1325	rs->rules[rs_num].active.rcount =
1326	    rs->rules[rs_num].inactive.rcount;
1327	rs->rules[rs_num].inactive.ptr = old_rules;
1328	rs->rules[rs_num].inactive.ptr_array = old_array;
1329	rs->rules[rs_num].inactive.rcount = old_rcount;
1330
1331	rs->rules[rs_num].active.ticket =
1332	    rs->rules[rs_num].inactive.ticket;
1333	pf_calc_skip_steps(rs->rules[rs_num].active.ptr);
1334
1335
1336	/* Purge the old rule list. */
1337	while ((rule = TAILQ_FIRST(old_rules)) != NULL)
1338		pf_rm_rule(old_rules, rule);
1339	if (rs->rules[rs_num].inactive.ptr_array)
1340		_FREE(rs->rules[rs_num].inactive.ptr_array, M_TEMP);
1341	rs->rules[rs_num].inactive.ptr_array = NULL;
1342	rs->rules[rs_num].inactive.rcount = 0;
1343	rs->rules[rs_num].inactive.open = 0;
1344	pf_remove_if_empty_ruleset(rs);
1345	return (0);
1346}
1347
1348static void
1349pf_rule_copyin(struct pf_rule *src, struct pf_rule *dst, struct proc *p,
1350    int minordev)
1351{
1352	bcopy(src, dst, sizeof (struct pf_rule));
1353
1354	dst->label[sizeof (dst->label) - 1] = '\0';
1355	dst->ifname[sizeof (dst->ifname) - 1] = '\0';
1356	dst->qname[sizeof (dst->qname) - 1] = '\0';
1357	dst->pqname[sizeof (dst->pqname) - 1] = '\0';
1358	dst->tagname[sizeof (dst->tagname) - 1] = '\0';
1359	dst->match_tagname[sizeof (dst->match_tagname) - 1] = '\0';
1360	dst->overload_tblname[sizeof (dst->overload_tblname) - 1] = '\0';
1361
1362	dst->cuid = kauth_cred_getuid(p->p_ucred);
1363	dst->cpid = p->p_pid;
1364
1365	dst->anchor = NULL;
1366	dst->kif = NULL;
1367	dst->overload_tbl = NULL;
1368
1369	TAILQ_INIT(&dst->rpool.list);
1370	dst->rpool.cur = NULL;
1371
1372	/* initialize refcounting */
1373	dst->states = 0;
1374	dst->src_nodes = 0;
1375
1376	dst->entries.tqe_prev = NULL;
1377	dst->entries.tqe_next = NULL;
1378	if ((uint8_t)minordev == PFDEV_PFM)
1379		dst->rule_flag |= PFRULE_PFM;
1380}
1381
1382static void
1383pf_rule_copyout(struct pf_rule *src, struct pf_rule *dst)
1384{
1385	bcopy(src, dst, sizeof (struct pf_rule));
1386
1387	dst->anchor = NULL;
1388	dst->kif = NULL;
1389	dst->overload_tbl = NULL;
1390
1391	TAILQ_INIT(&dst->rpool.list);
1392	dst->rpool.cur = NULL;
1393
1394	dst->entries.tqe_prev = NULL;
1395	dst->entries.tqe_next = NULL;
1396}
1397
1398static void
1399pf_state_export(struct pfsync_state *sp, struct pf_state_key *sk,
1400    struct pf_state *s)
1401{
1402	uint64_t secs = pf_time_second();
1403	bzero(sp, sizeof (struct pfsync_state));
1404
1405	/* copy from state key */
1406	sp->lan.addr = sk->lan.addr;
1407	sp->lan.xport = sk->lan.xport;
1408	sp->gwy.addr = sk->gwy.addr;
1409	sp->gwy.xport = sk->gwy.xport;
1410	sp->ext.addr = sk->ext.addr;
1411	sp->ext.xport = sk->ext.xport;
1412	sp->proto_variant = sk->proto_variant;
1413	sp->tag = s->tag;
1414	sp->proto = sk->proto;
1415	sp->af = sk->af;
1416	sp->direction = sk->direction;
1417	sp->flowhash = sk->flowhash;
1418
1419	/* copy from state */
1420	memcpy(&sp->id, &s->id, sizeof (sp->id));
1421	sp->creatorid = s->creatorid;
1422	strlcpy(sp->ifname, s->kif->pfik_name, sizeof (sp->ifname));
1423	pf_state_peer_to_pfsync(&s->src, &sp->src);
1424	pf_state_peer_to_pfsync(&s->dst, &sp->dst);
1425
1426	sp->rule = s->rule.ptr->nr;
1427	sp->nat_rule = (s->nat_rule.ptr == NULL) ?
1428	    (unsigned)-1 : s->nat_rule.ptr->nr;
1429	sp->anchor = (s->anchor.ptr == NULL) ?
1430	    (unsigned)-1 : s->anchor.ptr->nr;
1431
1432	pf_state_counter_to_pfsync(s->bytes[0], sp->bytes[0]);
1433	pf_state_counter_to_pfsync(s->bytes[1], sp->bytes[1]);
1434	pf_state_counter_to_pfsync(s->packets[0], sp->packets[0]);
1435	pf_state_counter_to_pfsync(s->packets[1], sp->packets[1]);
1436	sp->creation = secs - s->creation;
1437	sp->expire = pf_state_expires(s);
1438	sp->log = s->log;
1439	sp->allow_opts = s->allow_opts;
1440	sp->timeout = s->timeout;
1441
1442	if (s->src_node)
1443		sp->sync_flags |= PFSYNC_FLAG_SRCNODE;
1444	if (s->nat_src_node)
1445		sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE;
1446
1447	if (sp->expire > secs)
1448		sp->expire -= secs;
1449	else
1450		sp->expire = 0;
1451
1452}
1453
1454static void
1455pf_state_import(struct pfsync_state *sp, struct pf_state_key *sk,
1456    struct pf_state *s)
1457{
1458	/* copy to state key */
1459	sk->lan.addr = sp->lan.addr;
1460	sk->lan.xport = sp->lan.xport;
1461	sk->gwy.addr = sp->gwy.addr;
1462	sk->gwy.xport = sp->gwy.xport;
1463	sk->ext.addr = sp->ext.addr;
1464	sk->ext.xport = sp->ext.xport;
1465	sk->proto_variant = sp->proto_variant;
1466	s->tag = sp->tag;
1467	sk->proto = sp->proto;
1468	sk->af = sp->af;
1469	sk->direction = sp->direction;
1470	sk->flowhash = pf_calc_state_key_flowhash(sk);
1471
1472	/* copy to state */
1473	memcpy(&s->id, &sp->id, sizeof (sp->id));
1474	s->creatorid = sp->creatorid;
1475	pf_state_peer_from_pfsync(&sp->src, &s->src);
1476	pf_state_peer_from_pfsync(&sp->dst, &s->dst);
1477
1478	s->rule.ptr = &pf_default_rule;
1479	s->nat_rule.ptr = NULL;
1480	s->anchor.ptr = NULL;
1481	s->rt_kif = NULL;
1482	s->creation = pf_time_second();
1483	s->expire = pf_time_second();
1484	if (sp->expire > 0)
1485		s->expire -= pf_default_rule.timeout[sp->timeout] - sp->expire;
1486	s->pfsync_time = 0;
1487	s->packets[0] = s->packets[1] = 0;
1488	s->bytes[0] = s->bytes[1] = 0;
1489}
1490
1491static void
1492pf_pooladdr_copyin(struct pf_pooladdr *src, struct pf_pooladdr *dst)
1493{
1494	bcopy(src, dst, sizeof (struct pf_pooladdr));
1495
1496	dst->entries.tqe_prev = NULL;
1497	dst->entries.tqe_next = NULL;
1498	dst->ifname[sizeof (dst->ifname) - 1] = '\0';
1499	dst->kif = NULL;
1500}
1501
1502static void
1503pf_pooladdr_copyout(struct pf_pooladdr *src, struct pf_pooladdr *dst)
1504{
1505	bcopy(src, dst, sizeof (struct pf_pooladdr));
1506
1507	dst->entries.tqe_prev = NULL;
1508	dst->entries.tqe_next = NULL;
1509	dst->kif = NULL;
1510}
1511
1512static int
1513pf_setup_pfsync_matching(struct pf_ruleset *rs)
1514{
1515	MD5_CTX			 ctx;
1516	struct pf_rule		*rule;
1517	int			 rs_cnt;
1518	u_int8_t		 digest[PF_MD5_DIGEST_LENGTH];
1519
1520	MD5Init(&ctx);
1521	for (rs_cnt = 0; rs_cnt < PF_RULESET_MAX; rs_cnt++) {
1522		/* XXX PF_RULESET_SCRUB as well? */
1523		if (rs_cnt == PF_RULESET_SCRUB)
1524			continue;
1525
1526		if (rs->rules[rs_cnt].inactive.ptr_array)
1527			_FREE(rs->rules[rs_cnt].inactive.ptr_array, M_TEMP);
1528		rs->rules[rs_cnt].inactive.ptr_array = NULL;
1529
1530		if (rs->rules[rs_cnt].inactive.rcount) {
1531			rs->rules[rs_cnt].inactive.ptr_array =
1532			    _MALLOC(sizeof (caddr_t) *
1533			    rs->rules[rs_cnt].inactive.rcount,
1534			    M_TEMP, M_WAITOK);
1535
1536			if (!rs->rules[rs_cnt].inactive.ptr_array)
1537				return (ENOMEM);
1538		}
1539
1540		TAILQ_FOREACH(rule, rs->rules[rs_cnt].inactive.ptr,
1541		    entries) {
1542			pf_hash_rule(&ctx, rule);
1543			(rs->rules[rs_cnt].inactive.ptr_array)[rule->nr] = rule;
1544		}
1545	}
1546
1547	MD5Final(digest, &ctx);
1548	memcpy(pf_status.pf_chksum, digest, sizeof (pf_status.pf_chksum));
1549	return (0);
1550}
1551
1552static void
1553pf_start(void)
1554{
1555	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
1556
1557	VERIFY(pf_is_enabled == 0);
1558
1559	pf_is_enabled = 1;
1560	pf_status.running = 1;
1561	pf_status.since = pf_calendar_time_second();
1562	if (pf_status.stateid == 0) {
1563		pf_status.stateid = pf_time_second();
1564		pf_status.stateid = pf_status.stateid << 32;
1565	}
1566	wakeup(pf_purge_thread_fn);
1567	DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
1568}
1569
1570static void
1571pf_stop(void)
1572{
1573	lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
1574
1575	VERIFY(pf_is_enabled);
1576
1577	pf_status.running = 0;
1578	pf_is_enabled = 0;
1579	pf_status.since = pf_calendar_time_second();
1580	wakeup(pf_purge_thread_fn);
1581	DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
1582}
1583
1584static int
1585pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
1586{
1587#pragma unused(dev)
1588	int p64 = proc_is64bit(p);
1589	int error = 0;
1590	int minordev = minor(dev);
1591
1592	if (kauth_cred_issuser(kauth_cred_get()) == 0)
1593		return (EPERM);
1594
1595	/* XXX keep in sync with switch() below */
1596	if (securelevel > 1)
1597		switch (cmd) {
1598		case DIOCGETRULES:
1599		case DIOCGETRULE:
1600		case DIOCGETADDRS:
1601		case DIOCGETADDR:
1602		case DIOCGETSTATE:
1603		case DIOCSETSTATUSIF:
1604		case DIOCGETSTATUS:
1605		case DIOCCLRSTATUS:
1606		case DIOCNATLOOK:
1607		case DIOCSETDEBUG:
1608		case DIOCGETSTATES:
1609		case DIOCINSERTRULE:
1610		case DIOCDELETERULE:
1611		case DIOCGETTIMEOUT:
1612		case DIOCCLRRULECTRS:
1613		case DIOCGETLIMIT:
1614		case DIOCGETALTQS:
1615		case DIOCGETALTQ:
1616		case DIOCGETQSTATS:
1617		case DIOCGETRULESETS:
1618		case DIOCGETRULESET:
1619		case DIOCRGETTABLES:
1620		case DIOCRGETTSTATS:
1621		case DIOCRCLRTSTATS:
1622		case DIOCRCLRADDRS:
1623		case DIOCRADDADDRS:
1624		case DIOCRDELADDRS:
1625		case DIOCRSETADDRS:
1626		case DIOCRGETADDRS:
1627		case DIOCRGETASTATS:
1628		case DIOCRCLRASTATS:
1629		case DIOCRTSTADDRS:
1630		case DIOCOSFPGET:
1631		case DIOCGETSRCNODES:
1632		case DIOCCLRSRCNODES:
1633		case DIOCIGETIFACES:
1634		case DIOCGIFSPEED:
1635		case DIOCSETIFFLAG:
1636		case DIOCCLRIFFLAG:
1637			break;
1638		case DIOCRCLRTABLES:
1639		case DIOCRADDTABLES:
1640		case DIOCRDELTABLES:
1641		case DIOCRSETTFLAGS: {
1642			int pfrio_flags;
1643
1644			bcopy(&((struct pfioc_table *)(void *)addr)->
1645			    pfrio_flags, &pfrio_flags, sizeof (pfrio_flags));
1646
1647			if (pfrio_flags & PFR_FLAG_DUMMY)
1648				break; /* dummy operation ok */
1649			return (EPERM);
1650		}
1651		default:
1652			return (EPERM);
1653		}
1654
1655	if (!(flags & FWRITE))
1656		switch (cmd) {
1657		case DIOCSTART:
1658		case DIOCSTARTREF:
1659		case DIOCSTOP:
1660		case DIOCSTOPREF:
1661		case DIOCGETSTARTERS:
1662		case DIOCGETRULES:
1663		case DIOCGETADDRS:
1664		case DIOCGETADDR:
1665		case DIOCGETSTATE:
1666		case DIOCGETSTATUS:
1667		case DIOCGETSTATES:
1668		case DIOCINSERTRULE:
1669		case DIOCDELETERULE:
1670		case DIOCGETTIMEOUT:
1671		case DIOCGETLIMIT:
1672		case DIOCGETALTQS:
1673		case DIOCGETALTQ:
1674		case DIOCGETQSTATS:
1675		case DIOCGETRULESETS:
1676		case DIOCGETRULESET:
1677		case DIOCNATLOOK:
1678		case DIOCRGETTABLES:
1679		case DIOCRGETTSTATS:
1680		case DIOCRGETADDRS:
1681		case DIOCRGETASTATS:
1682		case DIOCRTSTADDRS:
1683		case DIOCOSFPGET:
1684		case DIOCGETSRCNODES:
1685		case DIOCIGETIFACES:
1686		case DIOCGIFSPEED:
1687			break;
1688		case DIOCRCLRTABLES:
1689		case DIOCRADDTABLES:
1690		case DIOCRDELTABLES:
1691		case DIOCRCLRTSTATS:
1692		case DIOCRCLRADDRS:
1693		case DIOCRADDADDRS:
1694		case DIOCRDELADDRS:
1695		case DIOCRSETADDRS:
1696		case DIOCRSETTFLAGS: {
1697			int pfrio_flags;
1698
1699			bcopy(&((struct pfioc_table *)(void *)addr)->
1700			    pfrio_flags, &pfrio_flags, sizeof (pfrio_flags));
1701
1702			if (pfrio_flags & PFR_FLAG_DUMMY) {
1703				flags |= FWRITE; /* need write lock for dummy */
1704				break; /* dummy operation ok */
1705			}
1706			return (EACCES);
1707		}
1708		case DIOCGETRULE: {
1709			u_int32_t action;
1710
1711			bcopy(&((struct pfioc_rule *)(void *)addr)->action,
1712			    &action, sizeof (action));
1713
1714			if (action == PF_GET_CLR_CNTR)
1715				return (EACCES);
1716			break;
1717		}
1718		default:
1719			return (EACCES);
1720		}
1721
1722#if PF_ALTQ
1723	switch (cmd) {
1724	case DIOCSTARTALTQ:
1725	case DIOCSTOPALTQ:
1726	case DIOCADDALTQ:
1727	case DIOCGETALTQS:
1728	case DIOCGETALTQ:
1729	case DIOCCHANGEALTQ:
1730	case DIOCGETQSTATS:
1731		/* fail if ALTQ is disabled */
1732		if (!altq_allowed)
1733			return (ENODEV);
1734		break;
1735	}
1736#endif /* PF_ALTQ */
1737
1738	if (flags & FWRITE)
1739		lck_rw_lock_exclusive(pf_perim_lock);
1740	else
1741		lck_rw_lock_shared(pf_perim_lock);
1742
1743	lck_mtx_lock(pf_lock);
1744
1745	switch (cmd) {
1746
1747	case DIOCSTART:
1748		if (pf_status.running) {
1749			/*
1750			 * Increment the reference for a simple -e enable, so
1751			 * that even if other processes drop their references,
1752			 * pf will still be available to processes that turned
1753			 * it on without taking a reference
1754			 */
1755			if (nr_tokens == pf_enabled_ref_count) {
1756				pf_enabled_ref_count++;
1757				VERIFY(pf_enabled_ref_count != 0);
1758			}
1759			error = EEXIST;
1760		} else if (pf_purge_thread == NULL) {
1761			error = ENOMEM;
1762		} else {
1763			pf_start();
1764			pf_enabled_ref_count++;
1765			VERIFY(pf_enabled_ref_count != 0);
1766		}
1767		break;
1768
1769	case DIOCSTARTREF:		/* u_int64_t */
1770		if (pf_purge_thread == NULL) {
1771			error = ENOMEM;
1772		} else {
1773			u_int64_t token;
1774
1775			/* small enough to be on stack */
1776			if ((token = generate_token(p)) != 0) {
1777				if (pf_is_enabled == 0) {
1778					pf_start();
1779				}
1780				pf_enabled_ref_count++;
1781				VERIFY(pf_enabled_ref_count != 0);
1782			} else {
1783				error = ENOMEM;
1784				DPFPRINTF(PF_DEBUG_URGENT,
1785				    ("pf: unable to generate token\n"));
1786			}
1787			bcopy(&token, addr, sizeof (token));
1788		}
1789		break;
1790
1791	case DIOCSTOP:
1792		if (!pf_status.running) {
1793			error = ENOENT;
1794		} else {
1795			pf_stop();
1796			pf_enabled_ref_count = 0;
1797			invalidate_all_tokens();
1798		}
1799		break;
1800
1801	case DIOCSTOPREF:		/* struct pfioc_remove_token */
1802		if (!pf_status.running) {
1803			error = ENOENT;
1804		} else {
1805			struct pfioc_remove_token pfrt;
1806
1807			/* small enough to be on stack */
1808			bcopy(addr, &pfrt, sizeof (pfrt));
1809			if ((error = remove_token(&pfrt)) == 0) {
1810				VERIFY(pf_enabled_ref_count != 0);
1811				pf_enabled_ref_count--;
1812				/* return currently held references */
1813				pfrt.refcount = pf_enabled_ref_count;
1814				DPFPRINTF(PF_DEBUG_MISC,
1815				    ("pf: enabled refcount decremented\n"));
1816			} else {
1817				error = EINVAL;
1818				DPFPRINTF(PF_DEBUG_URGENT,
1819				    ("pf: token mismatch\n"));
1820			}
1821			bcopy(&pfrt, addr, sizeof (pfrt));
1822
1823			if (error == 0 && pf_enabled_ref_count == 0)
1824				pf_stop();
1825		}
1826		break;
1827
1828	case DIOCGETSTARTERS: {		/* struct pfioc_tokens */
1829		PFIOCX_STRUCT_DECL(pfioc_tokens);
1830
1831		PFIOCX_STRUCT_BEGIN(addr, pfioc_tokens, error = ENOMEM; break;);
1832		error = pfioctl_ioc_tokens(cmd,
1833		    PFIOCX_STRUCT_ADDR32(pfioc_tokens),
1834		    PFIOCX_STRUCT_ADDR64(pfioc_tokens), p);
1835		PFIOCX_STRUCT_END(pfioc_tokens, addr);
1836		break;
1837	}
1838
1839	case DIOCADDRULE:		/* struct pfioc_rule */
1840	case DIOCGETRULES:		/* struct pfioc_rule */
1841	case DIOCGETRULE:		/* struct pfioc_rule */
1842	case DIOCCHANGERULE:		/* struct pfioc_rule */
1843	case DIOCINSERTRULE:		/* struct pfioc_rule */
1844	case DIOCDELETERULE: {		/* struct pfioc_rule */
1845		struct pfioc_rule *pr = NULL;
1846
1847		PFIOC_STRUCT_BEGIN(addr, pr, error = ENOMEM; break;);
1848		error = pfioctl_ioc_rule(cmd, minordev, pr, p);
1849		PFIOC_STRUCT_END(pr, addr);
1850		break;
1851	}
1852
1853	case DIOCCLRSTATES:		/* struct pfioc_state_kill */
1854	case DIOCKILLSTATES: {		/* struct pfioc_state_kill */
1855		struct pfioc_state_kill *psk = NULL;
1856
1857		PFIOC_STRUCT_BEGIN(addr, psk, error = ENOMEM; break;);
1858		error = pfioctl_ioc_state_kill(cmd, psk, p);
1859		PFIOC_STRUCT_END(psk, addr);
1860		break;
1861	}
1862
1863	case DIOCADDSTATE:		/* struct pfioc_state */
1864	case DIOCGETSTATE: {		/* struct pfioc_state */
1865		struct pfioc_state *ps = NULL;
1866
1867		PFIOC_STRUCT_BEGIN(addr, ps, error = ENOMEM; break;);
1868		error = pfioctl_ioc_state(cmd, ps, p);
1869		PFIOC_STRUCT_END(ps, addr);
1870		break;
1871	}
1872
1873	case DIOCGETSTATES: {		/* struct pfioc_states */
1874		PFIOCX_STRUCT_DECL(pfioc_states);
1875
1876		PFIOCX_STRUCT_BEGIN(addr, pfioc_states, error = ENOMEM; break;);
1877		error = pfioctl_ioc_states(cmd,
1878		    PFIOCX_STRUCT_ADDR32(pfioc_states),
1879		    PFIOCX_STRUCT_ADDR64(pfioc_states), p);
1880		PFIOCX_STRUCT_END(pfioc_states, addr);
1881		break;
1882	}
1883
1884	case DIOCGETSTATUS: {		/* struct pf_status */
1885		struct pf_status *s = NULL;
1886
1887		PFIOC_STRUCT_BEGIN(&pf_status, s, error = ENOMEM; break;);
1888		pfi_update_status(s->ifname, s);
1889		PFIOC_STRUCT_END(s, addr);
1890		break;
1891	}
1892
1893	case DIOCSETSTATUSIF: {		/* struct pfioc_if */
1894		struct pfioc_if	*pi = (struct pfioc_if *)(void *)addr;
1895
1896		/* OK for unaligned accesses */
1897		if (pi->ifname[0] == 0) {
1898			bzero(pf_status.ifname, IFNAMSIZ);
1899			break;
1900		}
1901		strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ);
1902		break;
1903	}
1904
1905	case DIOCCLRSTATUS: {
1906		bzero(pf_status.counters, sizeof (pf_status.counters));
1907		bzero(pf_status.fcounters, sizeof (pf_status.fcounters));
1908		bzero(pf_status.scounters, sizeof (pf_status.scounters));
1909		pf_status.since = pf_calendar_time_second();
1910		if (*pf_status.ifname)
1911			pfi_update_status(pf_status.ifname, NULL);
1912		break;
1913	}
1914
1915	case DIOCNATLOOK: {		/* struct pfioc_natlook */
1916		struct pfioc_natlook *pnl = NULL;
1917
1918		PFIOC_STRUCT_BEGIN(addr, pnl, error = ENOMEM; break;);
1919		error = pfioctl_ioc_natlook(cmd, pnl, p);
1920		PFIOC_STRUCT_END(pnl, addr);
1921		break;
1922	}
1923
1924	case DIOCSETTIMEOUT:		/* struct pfioc_tm */
1925	case DIOCGETTIMEOUT: {		/* struct pfioc_tm */
1926		struct pfioc_tm	pt;
1927
1928		/* small enough to be on stack */
1929		bcopy(addr, &pt, sizeof (pt));
1930		error = pfioctl_ioc_tm(cmd, &pt, p);
1931		bcopy(&pt, addr, sizeof (pt));
1932		break;
1933	}
1934
1935	case DIOCGETLIMIT:		/* struct pfioc_limit */
1936	case DIOCSETLIMIT: {		/* struct pfioc_limit */
1937		struct pfioc_limit pl;
1938
1939		/* small enough to be on stack */
1940		bcopy(addr, &pl, sizeof (pl));
1941		error = pfioctl_ioc_limit(cmd, &pl, p);
1942		bcopy(&pl, addr, sizeof (pl));
1943		break;
1944	}
1945
1946	case DIOCSETDEBUG: {		/* u_int32_t */
1947		bcopy(addr, &pf_status.debug, sizeof (u_int32_t));
1948		break;
1949	}
1950
1951	case DIOCCLRRULECTRS: {
1952		/* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */
1953		struct pf_ruleset	*ruleset = &pf_main_ruleset;
1954		struct pf_rule		*rule;
1955
1956		TAILQ_FOREACH(rule,
1957		    ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) {
1958			rule->evaluations = 0;
1959			rule->packets[0] = rule->packets[1] = 0;
1960			rule->bytes[0] = rule->bytes[1] = 0;
1961		}
1962		break;
1963	}
1964
1965	case DIOCGIFSPEED: {
1966		struct pf_ifspeed *psp = (struct pf_ifspeed *)(void *)addr;
1967		struct pf_ifspeed ps;
1968		struct ifnet *ifp;
1969		u_int64_t baudrate;
1970
1971		if (psp->ifname[0] != '\0') {
1972			/* Can we completely trust user-land? */
1973			strlcpy(ps.ifname, psp->ifname, IFNAMSIZ);
1974			ps.ifname[IFNAMSIZ - 1] = '\0';
1975			ifp = ifunit(ps.ifname);
1976			if (ifp != NULL) {
1977				baudrate = ifp->if_output_bw.max_bw;
1978				bcopy(&baudrate, &psp->baudrate,
1979				    sizeof (baudrate));
1980			} else {
1981				error = EINVAL;
1982			}
1983		} else {
1984			error = EINVAL;
1985		}
1986		break;
1987	}
1988
1989#if PF_ALTQ
1990	case DIOCSTARTALTQ: {
1991		struct pf_altq		*altq;
1992
1993		VERIFY(altq_allowed);
1994		/* enable all altq interfaces on active list */
1995		TAILQ_FOREACH(altq, pf_altqs_active, entries) {
1996			if (altq->qname[0] == '\0') {
1997				error = pf_enable_altq(altq);
1998				if (error != 0)
1999					break;
2000			}
2001		}
2002		if (error == 0)
2003			pf_altq_running = 1;
2004		DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
2005		break;
2006	}
2007
2008	case DIOCSTOPALTQ: {
2009		struct pf_altq		*altq;
2010
2011		VERIFY(altq_allowed);
2012		/* disable all altq interfaces on active list */
2013		TAILQ_FOREACH(altq, pf_altqs_active, entries) {
2014			if (altq->qname[0] == '\0') {
2015				error = pf_disable_altq(altq);
2016				if (error != 0)
2017					break;
2018			}
2019		}
2020		if (error == 0)
2021			pf_altq_running = 0;
2022		DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
2023		break;
2024	}
2025
2026	case DIOCADDALTQ: {		/* struct pfioc_altq */
2027		struct pfioc_altq	*pa = (struct pfioc_altq *)(void *)addr;
2028		struct pf_altq		*altq, *a;
2029		u_int32_t		ticket;
2030
2031		VERIFY(altq_allowed);
2032		bcopy(&pa->ticket, &ticket, sizeof (ticket));
2033		if (ticket != ticket_altqs_inactive) {
2034			error = EBUSY;
2035			break;
2036		}
2037		altq = pool_get(&pf_altq_pl, PR_WAITOK);
2038		if (altq == NULL) {
2039			error = ENOMEM;
2040			break;
2041		}
2042		pf_altq_copyin(&pa->altq, altq);
2043
2044		/*
2045		 * if this is for a queue, find the discipline and
2046		 * copy the necessary fields
2047		 */
2048		if (altq->qname[0] != '\0') {
2049			if ((altq->qid = pf_qname2qid(altq->qname)) == 0) {
2050				error = EBUSY;
2051				pool_put(&pf_altq_pl, altq);
2052				break;
2053			}
2054			altq->altq_disc = NULL;
2055			TAILQ_FOREACH(a, pf_altqs_inactive, entries) {
2056				if (strncmp(a->ifname, altq->ifname,
2057				    IFNAMSIZ) == 0 && a->qname[0] == '\0') {
2058					altq->altq_disc = a->altq_disc;
2059					break;
2060				}
2061			}
2062		}
2063
2064		error = altq_add(altq);
2065		if (error) {
2066			pool_put(&pf_altq_pl, altq);
2067			break;
2068		}
2069
2070		TAILQ_INSERT_TAIL(pf_altqs_inactive, altq, entries);
2071		pf_altq_copyout(altq, &pa->altq);
2072		break;
2073	}
2074
2075	case DIOCGETALTQS: {
2076		struct pfioc_altq	*pa = (struct pfioc_altq *)(void *)addr;
2077		struct pf_altq		*altq;
2078		u_int32_t		nr;
2079
2080		VERIFY(altq_allowed);
2081		nr = 0;
2082		TAILQ_FOREACH(altq, pf_altqs_active, entries)
2083			nr++;
2084		bcopy(&nr, &pa->nr, sizeof (nr));
2085		bcopy(&ticket_altqs_active, &pa->ticket, sizeof (pa->ticket));
2086		break;
2087	}
2088
2089	case DIOCGETALTQ: {
2090		struct pfioc_altq	*pa = (struct pfioc_altq *)(void *)addr;
2091		struct pf_altq		*altq;
2092		u_int32_t		 nr, pa_nr, ticket;
2093
2094		VERIFY(altq_allowed);
2095		bcopy(&pa->ticket, &ticket, sizeof (ticket));
2096		if (ticket != ticket_altqs_active) {
2097			error = EBUSY;
2098			break;
2099		}
2100		bcopy(&pa->nr, &pa_nr, sizeof (pa_nr));
2101		nr = 0;
2102		altq = TAILQ_FIRST(pf_altqs_active);
2103		while ((altq != NULL) && (nr < pa_nr)) {
2104			altq = TAILQ_NEXT(altq, entries);
2105			nr++;
2106		}
2107		if (altq == NULL) {
2108			error = EBUSY;
2109			break;
2110		}
2111		pf_altq_copyout(altq, &pa->altq);
2112		break;
2113	}
2114
2115	case DIOCCHANGEALTQ:
2116		VERIFY(altq_allowed);
2117		/* CHANGEALTQ not supported yet! */
2118		error = ENODEV;
2119		break;
2120
2121	case DIOCGETQSTATS: {
2122		struct pfioc_qstats *pq = (struct pfioc_qstats *)(void *)addr;
2123		struct pf_altq		*altq;
2124		u_int32_t		 nr, pq_nr, ticket;
2125		int			 nbytes;
2126
2127		VERIFY(altq_allowed);
2128		bcopy(&pq->ticket, &ticket, sizeof (ticket));
2129		if (ticket != ticket_altqs_active) {
2130			error = EBUSY;
2131			break;
2132		}
2133		bcopy(&pq->nr, &pq_nr, sizeof (pq_nr));
2134		nr = 0;
2135		altq = TAILQ_FIRST(pf_altqs_active);
2136		while ((altq != NULL) && (nr < pq_nr)) {
2137			altq = TAILQ_NEXT(altq, entries);
2138			nr++;
2139		}
2140		if (altq == NULL) {
2141			error = EBUSY;
2142			break;
2143		}
2144		bcopy(&pq->nbytes, &nbytes, sizeof (nbytes));
2145		error = altq_getqstats(altq, pq->buf, &nbytes);
2146		if (error == 0) {
2147			pq->scheduler = altq->scheduler;
2148			bcopy(&nbytes, &pq->nbytes, sizeof (nbytes));
2149		}
2150		break;
2151	}
2152#endif /* PF_ALTQ */
2153
2154	case DIOCBEGINADDRS:		/* struct pfioc_pooladdr */
2155	case DIOCADDADDR:		/* struct pfioc_pooladdr */
2156	case DIOCGETADDRS:		/* struct pfioc_pooladdr */
2157	case DIOCGETADDR:		/* struct pfioc_pooladdr */
2158	case DIOCCHANGEADDR: {		/* struct pfioc_pooladdr */
2159		struct pfioc_pooladdr *pp = NULL;
2160
2161		PFIOC_STRUCT_BEGIN(addr, pp, error = ENOMEM; break;)
2162		error = pfioctl_ioc_pooladdr(cmd, pp, p);
2163		PFIOC_STRUCT_END(pp, addr);
2164		break;
2165	}
2166
2167	case DIOCGETRULESETS:		/* struct pfioc_ruleset */
2168	case DIOCGETRULESET: {		/* struct pfioc_ruleset */
2169		struct pfioc_ruleset *pr = NULL;
2170
2171		PFIOC_STRUCT_BEGIN(addr, pr, error = ENOMEM; break;);
2172		error = pfioctl_ioc_ruleset(cmd, pr, p);
2173		PFIOC_STRUCT_END(pr, addr);
2174		break;
2175	}
2176
2177	case DIOCRCLRTABLES:		/* struct pfioc_table */
2178	case DIOCRADDTABLES:		/* struct pfioc_table */
2179	case DIOCRDELTABLES:		/* struct pfioc_table */
2180	case DIOCRGETTABLES:		/* struct pfioc_table */
2181	case DIOCRGETTSTATS:		/* struct pfioc_table */
2182	case DIOCRCLRTSTATS:		/* struct pfioc_table */
2183	case DIOCRSETTFLAGS:		/* struct pfioc_table */
2184	case DIOCRCLRADDRS:		/* struct pfioc_table */
2185	case DIOCRADDADDRS:		/* struct pfioc_table */
2186	case DIOCRDELADDRS:		/* struct pfioc_table */
2187	case DIOCRSETADDRS:		/* struct pfioc_table */
2188	case DIOCRGETADDRS:		/* struct pfioc_table */
2189	case DIOCRGETASTATS:		/* struct pfioc_table */
2190	case DIOCRCLRASTATS:		/* struct pfioc_table */
2191	case DIOCRTSTADDRS:		/* struct pfioc_table */
2192	case DIOCRINADEFINE: {		/* struct pfioc_table */
2193		PFIOCX_STRUCT_DECL(pfioc_table);
2194
2195		PFIOCX_STRUCT_BEGIN(addr, pfioc_table, error = ENOMEM; break;);
2196		error = pfioctl_ioc_table(cmd,
2197		    PFIOCX_STRUCT_ADDR32(pfioc_table),
2198		    PFIOCX_STRUCT_ADDR64(pfioc_table), p);
2199		PFIOCX_STRUCT_END(pfioc_table, addr);
2200		break;
2201	}
2202
2203	case DIOCOSFPADD:		/* struct pf_osfp_ioctl */
2204	case DIOCOSFPGET: {		/* struct pf_osfp_ioctl */
2205		struct pf_osfp_ioctl *io = NULL;
2206
2207		PFIOC_STRUCT_BEGIN(addr, io, error = ENOMEM; break;);
2208		if (cmd == DIOCOSFPADD) {
2209			error = pf_osfp_add(io);
2210		} else {
2211			VERIFY(cmd == DIOCOSFPGET);
2212			error = pf_osfp_get(io);
2213		}
2214		PFIOC_STRUCT_END(io, addr);
2215		break;
2216	}
2217
2218	case DIOCXBEGIN:		/* struct pfioc_trans */
2219	case DIOCXROLLBACK:		/* struct pfioc_trans */
2220	case DIOCXCOMMIT: {		/* struct pfioc_trans */
2221		PFIOCX_STRUCT_DECL(pfioc_trans);
2222
2223		PFIOCX_STRUCT_BEGIN(addr, pfioc_trans, error = ENOMEM; break;);
2224		error = pfioctl_ioc_trans(cmd,
2225		    PFIOCX_STRUCT_ADDR32(pfioc_trans),
2226		    PFIOCX_STRUCT_ADDR64(pfioc_trans), p);
2227		PFIOCX_STRUCT_END(pfioc_trans, addr);
2228		break;
2229	}
2230
2231	case DIOCGETSRCNODES: {		/* struct pfioc_src_nodes */
2232		PFIOCX_STRUCT_DECL(pfioc_src_nodes);
2233
2234		PFIOCX_STRUCT_BEGIN(addr, pfioc_src_nodes,
2235		    error = ENOMEM; break;);
2236		error = pfioctl_ioc_src_nodes(cmd,
2237		    PFIOCX_STRUCT_ADDR32(pfioc_src_nodes),
2238		    PFIOCX_STRUCT_ADDR64(pfioc_src_nodes), p);
2239		PFIOCX_STRUCT_END(pfioc_src_nodes, addr);
2240		break;
2241	}
2242
2243	case DIOCCLRSRCNODES: {
2244		struct pf_src_node	*n;
2245		struct pf_state		*state;
2246
2247		RB_FOREACH(state, pf_state_tree_id, &tree_id) {
2248			state->src_node = NULL;
2249			state->nat_src_node = NULL;
2250		}
2251		RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
2252			n->expire = 1;
2253			n->states = 0;
2254		}
2255		pf_purge_expired_src_nodes();
2256		pf_status.src_nodes = 0;
2257		break;
2258	}
2259
2260	case DIOCKILLSRCNODES: {	/* struct pfioc_src_node_kill */
2261		struct pfioc_src_node_kill *psnk = NULL;
2262
2263		PFIOC_STRUCT_BEGIN(addr, psnk, error = ENOMEM; break;);
2264		error = pfioctl_ioc_src_node_kill(cmd, psnk, p);
2265		PFIOC_STRUCT_END(psnk, addr);
2266		break;
2267	}
2268
2269	case DIOCSETHOSTID: {		/* u_int32_t */
2270		u_int32_t hid;
2271
2272		/* small enough to be on stack */
2273		bcopy(addr, &hid, sizeof (hid));
2274		if (hid == 0)
2275			pf_status.hostid = random();
2276		else
2277			pf_status.hostid = hid;
2278		break;
2279	}
2280
2281	case DIOCOSFPFLUSH:
2282		pf_osfp_flush();
2283		break;
2284
2285	case DIOCIGETIFACES:		/* struct pfioc_iface */
2286	case DIOCSETIFFLAG:		/* struct pfioc_iface */
2287	case DIOCCLRIFFLAG: {		/* struct pfioc_iface */
2288		PFIOCX_STRUCT_DECL(pfioc_iface);
2289
2290		PFIOCX_STRUCT_BEGIN(addr, pfioc_iface, error = ENOMEM; break;);
2291		error = pfioctl_ioc_iface(cmd,
2292		    PFIOCX_STRUCT_ADDR32(pfioc_iface),
2293		    PFIOCX_STRUCT_ADDR64(pfioc_iface), p);
2294		PFIOCX_STRUCT_END(pfioc_iface, addr);
2295		break;
2296	}
2297
2298	default:
2299		error = ENODEV;
2300		break;
2301	}
2302
2303	lck_mtx_unlock(pf_lock);
2304	lck_rw_done(pf_perim_lock);
2305
2306	return (error);
2307}
2308
2309static int
2310pfioctl_ioc_table(u_long cmd, struct pfioc_table_32 *io32,
2311    struct pfioc_table_64 *io64, struct proc *p)
2312{
2313	int p64 = proc_is64bit(p);
2314	int error = 0;
2315
2316	if (!p64)
2317		goto struct32;
2318
2319	/*
2320	 * 64-bit structure processing
2321	 */
2322	switch (cmd) {
2323	case DIOCRCLRTABLES:
2324		if (io64->pfrio_esize != 0) {
2325			error = ENODEV;
2326			break;
2327		}
2328		pfr_table_copyin_cleanup(&io64->pfrio_table);
2329		error = pfr_clr_tables(&io64->pfrio_table, &io64->pfrio_ndel,
2330		    io64->pfrio_flags | PFR_FLAG_USERIOCTL);
2331		break;
2332
2333	case DIOCRADDTABLES:
2334		if (io64->pfrio_esize != sizeof (struct pfr_table)) {
2335			error = ENODEV;
2336			break;
2337		}
2338		error = pfr_add_tables(io64->pfrio_buffer, io64->pfrio_size,
2339		    &io64->pfrio_nadd, io64->pfrio_flags | PFR_FLAG_USERIOCTL);
2340		break;
2341
2342	case DIOCRDELTABLES:
2343		if (io64->pfrio_esize != sizeof (struct pfr_table)) {
2344			error = ENODEV;
2345			break;
2346		}
2347		error = pfr_del_tables(io64->pfrio_buffer, io64->pfrio_size,
2348		    &io64->pfrio_ndel, io64->pfrio_flags | PFR_FLAG_USERIOCTL);
2349		break;
2350
2351	case DIOCRGETTABLES:
2352		if (io64->pfrio_esize != sizeof (struct pfr_table)) {
2353			error = ENODEV;
2354			break;
2355		}
2356		pfr_table_copyin_cleanup(&io64->pfrio_table);
2357		error = pfr_get_tables(&io64->pfrio_table, io64->pfrio_buffer,
2358		    &io64->pfrio_size, io64->pfrio_flags | PFR_FLAG_USERIOCTL);
2359		break;
2360
2361	case DIOCRGETTSTATS:
2362		if (io64->pfrio_esize != sizeof (struct pfr_tstats)) {
2363			error = ENODEV;
2364			break;
2365		}
2366		pfr_table_copyin_cleanup(&io64->pfrio_table);
2367		error = pfr_get_tstats(&io64->pfrio_table, io64->pfrio_buffer,
2368		    &io64->pfrio_size, io64->pfrio_flags | PFR_FLAG_USERIOCTL);
2369		break;
2370
2371	case DIOCRCLRTSTATS:
2372		if (io64->pfrio_esize != sizeof (struct pfr_table)) {
2373			error = ENODEV;
2374			break;
2375		}
2376		error = pfr_clr_tstats(io64->pfrio_buffer, io64->pfrio_size,
2377		    &io64->pfrio_nzero, io64->pfrio_flags | PFR_FLAG_USERIOCTL);
2378		break;
2379
2380	case DIOCRSETTFLAGS:
2381		if (io64->pfrio_esize != sizeof (struct pfr_table)) {
2382			error = ENODEV;
2383			break;
2384		}
2385		error = pfr_set_tflags(io64->pfrio_buffer, io64->pfrio_size,
2386		    io64->pfrio_setflag, io64->pfrio_clrflag,
2387		    &io64->pfrio_nchange, &io64->pfrio_ndel,
2388		    io64->pfrio_flags | PFR_FLAG_USERIOCTL);
2389		break;
2390
2391	case DIOCRCLRADDRS:
2392		if (io64->pfrio_esize != 0) {
2393			error = ENODEV;
2394			break;
2395		}
2396		pfr_table_copyin_cleanup(&io64->pfrio_table);
2397		error = pfr_clr_addrs(&io64->pfrio_table, &io64->pfrio_ndel,
2398		    io64->pfrio_flags | PFR_FLAG_USERIOCTL);
2399		break;
2400
2401	case DIOCRADDADDRS:
2402		if (io64->pfrio_esize != sizeof (struct pfr_addr)) {
2403			error = ENODEV;
2404			break;
2405		}
2406		pfr_table_copyin_cleanup(&io64->pfrio_table);
2407		error = pfr_add_addrs(&io64->pfrio_table, io64->pfrio_buffer,
2408		    io64->pfrio_size, &io64->pfrio_nadd, io64->pfrio_flags |
2409		    PFR_FLAG_USERIOCTL);
2410		break;
2411
2412	case DIOCRDELADDRS:
2413		if (io64->pfrio_esize != sizeof (struct pfr_addr)) {
2414			error = ENODEV;
2415			break;
2416		}
2417		pfr_table_copyin_cleanup(&io64->pfrio_table);
2418		error = pfr_del_addrs(&io64->pfrio_table, io64->pfrio_buffer,
2419		    io64->pfrio_size, &io64->pfrio_ndel, io64->pfrio_flags |
2420		    PFR_FLAG_USERIOCTL);
2421		break;
2422
2423	case DIOCRSETADDRS:
2424		if (io64->pfrio_esize != sizeof (struct pfr_addr)) {
2425			error = ENODEV;
2426			break;
2427		}
2428		pfr_table_copyin_cleanup(&io64->pfrio_table);
2429		error = pfr_set_addrs(&io64->pfrio_table, io64->pfrio_buffer,
2430		    io64->pfrio_size, &io64->pfrio_size2, &io64->pfrio_nadd,
2431		    &io64->pfrio_ndel, &io64->pfrio_nchange, io64->pfrio_flags |
2432		    PFR_FLAG_USERIOCTL, 0);
2433		break;
2434
2435	case DIOCRGETADDRS:
2436		if (io64->pfrio_esize != sizeof (struct pfr_addr)) {
2437			error = ENODEV;
2438			break;
2439		}
2440		pfr_table_copyin_cleanup(&io64->pfrio_table);
2441		error = pfr_get_addrs(&io64->pfrio_table, io64->pfrio_buffer,
2442		    &io64->pfrio_size, io64->pfrio_flags | PFR_FLAG_USERIOCTL);
2443		break;
2444
2445	case DIOCRGETASTATS:
2446		if (io64->pfrio_esize != sizeof (struct pfr_astats)) {
2447			error = ENODEV;
2448			break;
2449		}
2450		pfr_table_copyin_cleanup(&io64->pfrio_table);
2451		error = pfr_get_astats(&io64->pfrio_table, io64->pfrio_buffer,
2452		    &io64->pfrio_size, io64->pfrio_flags | PFR_FLAG_USERIOCTL);
2453		break;
2454
2455	case DIOCRCLRASTATS:
2456		if (io64->pfrio_esize != sizeof (struct pfr_addr)) {
2457			error = ENODEV;
2458			break;
2459		}
2460		pfr_table_copyin_cleanup(&io64->pfrio_table);
2461		error = pfr_clr_astats(&io64->pfrio_table, io64->pfrio_buffer,
2462		    io64->pfrio_size, &io64->pfrio_nzero, io64->pfrio_flags |
2463		    PFR_FLAG_USERIOCTL);
2464		break;
2465
2466	case DIOCRTSTADDRS:
2467		if (io64->pfrio_esize != sizeof (struct pfr_addr)) {
2468			error = ENODEV;
2469			break;
2470		}
2471		pfr_table_copyin_cleanup(&io64->pfrio_table);
2472		error = pfr_tst_addrs(&io64->pfrio_table, io64->pfrio_buffer,
2473		    io64->pfrio_size, &io64->pfrio_nmatch, io64->pfrio_flags |
2474		    PFR_FLAG_USERIOCTL);
2475		break;
2476
2477	case DIOCRINADEFINE:
2478		if (io64->pfrio_esize != sizeof (struct pfr_addr)) {
2479			error = ENODEV;
2480			break;
2481		}
2482		pfr_table_copyin_cleanup(&io64->pfrio_table);
2483		error = pfr_ina_define(&io64->pfrio_table, io64->pfrio_buffer,
2484		    io64->pfrio_size, &io64->pfrio_nadd, &io64->pfrio_naddr,
2485		    io64->pfrio_ticket, io64->pfrio_flags | PFR_FLAG_USERIOCTL);
2486		break;
2487
2488	default:
2489		VERIFY(0);
2490		/* NOTREACHED */
2491	}
2492	goto done;
2493
2494struct32:
2495	/*
2496	 * 32-bit structure processing
2497	 */
2498	switch (cmd) {
2499	case DIOCRCLRTABLES:
2500		if (io32->pfrio_esize != 0) {
2501			error = ENODEV;
2502			break;
2503		}
2504		pfr_table_copyin_cleanup(&io32->pfrio_table);
2505		error = pfr_clr_tables(&io32->pfrio_table, &io32->pfrio_ndel,
2506		    io32->pfrio_flags | PFR_FLAG_USERIOCTL);
2507		break;
2508
2509	case DIOCRADDTABLES:
2510		if (io32->pfrio_esize != sizeof (struct pfr_table)) {
2511			error = ENODEV;
2512			break;
2513		}
2514		error = pfr_add_tables(io32->pfrio_buffer, io32->pfrio_size,
2515		    &io32->pfrio_nadd, io32->pfrio_flags | PFR_FLAG_USERIOCTL);
2516		break;
2517
2518	case DIOCRDELTABLES:
2519		if (io32->pfrio_esize != sizeof (struct pfr_table)) {
2520			error = ENODEV;
2521			break;
2522		}
2523		error = pfr_del_tables(io32->pfrio_buffer, io32->pfrio_size,
2524		    &io32->pfrio_ndel, io32->pfrio_flags | PFR_FLAG_USERIOCTL);
2525		break;
2526
2527	case DIOCRGETTABLES:
2528		if (io32->pfrio_esize != sizeof (struct pfr_table)) {
2529			error = ENODEV;
2530			break;
2531		}
2532		pfr_table_copyin_cleanup(&io32->pfrio_table);
2533		error = pfr_get_tables(&io32->pfrio_table, io32->pfrio_buffer,
2534		    &io32->pfrio_size, io32->pfrio_flags | PFR_FLAG_USERIOCTL);
2535		break;
2536
2537	case DIOCRGETTSTATS:
2538		if (io32->pfrio_esize != sizeof (struct pfr_tstats)) {
2539			error = ENODEV;
2540			break;
2541		}
2542		pfr_table_copyin_cleanup(&io32->pfrio_table);
2543		error = pfr_get_tstats(&io32->pfrio_table, io32->pfrio_buffer,
2544		    &io32->pfrio_size, io32->pfrio_flags | PFR_FLAG_USERIOCTL);
2545		break;
2546
2547	case DIOCRCLRTSTATS:
2548		if (io32->pfrio_esize != sizeof (struct pfr_table)) {
2549			error = ENODEV;
2550			break;
2551		}
2552		error = pfr_clr_tstats(io32->pfrio_buffer, io32->pfrio_size,
2553		    &io32->pfrio_nzero, io32->pfrio_flags | PFR_FLAG_USERIOCTL);
2554		break;
2555
2556	case DIOCRSETTFLAGS:
2557		if (io32->pfrio_esize != sizeof (struct pfr_table)) {
2558			error = ENODEV;
2559			break;
2560		}
2561		error = pfr_set_tflags(io32->pfrio_buffer, io32->pfrio_size,
2562		    io32->pfrio_setflag, io32->pfrio_clrflag,
2563		    &io32->pfrio_nchange, &io32->pfrio_ndel,
2564		    io32->pfrio_flags | PFR_FLAG_USERIOCTL);
2565		break;
2566
2567	case DIOCRCLRADDRS:
2568		if (io32->pfrio_esize != 0) {
2569			error = ENODEV;
2570			break;
2571		}
2572		pfr_table_copyin_cleanup(&io32->pfrio_table);
2573		error = pfr_clr_addrs(&io32->pfrio_table, &io32->pfrio_ndel,
2574		    io32->pfrio_flags | PFR_FLAG_USERIOCTL);
2575		break;
2576
2577	case DIOCRADDADDRS:
2578		if (io32->pfrio_esize != sizeof (struct pfr_addr)) {
2579			error = ENODEV;
2580			break;
2581		}
2582		pfr_table_copyin_cleanup(&io32->pfrio_table);
2583		error = pfr_add_addrs(&io32->pfrio_table, io32->pfrio_buffer,
2584		    io32->pfrio_size, &io32->pfrio_nadd, io32->pfrio_flags |
2585		    PFR_FLAG_USERIOCTL);
2586		break;
2587
2588	case DIOCRDELADDRS:
2589		if (io32->pfrio_esize != sizeof (struct pfr_addr)) {
2590			error = ENODEV;
2591			break;
2592		}
2593		pfr_table_copyin_cleanup(&io32->pfrio_table);
2594		error = pfr_del_addrs(&io32->pfrio_table, io32->pfrio_buffer,
2595		    io32->pfrio_size, &io32->pfrio_ndel, io32->pfrio_flags |
2596		    PFR_FLAG_USERIOCTL);
2597		break;
2598
2599	case DIOCRSETADDRS:
2600		if (io32->pfrio_esize != sizeof (struct pfr_addr)) {
2601			error = ENODEV;
2602			break;
2603		}
2604		pfr_table_copyin_cleanup(&io32->pfrio_table);
2605		error = pfr_set_addrs(&io32->pfrio_table, io32->pfrio_buffer,
2606		    io32->pfrio_size, &io32->pfrio_size2, &io32->pfrio_nadd,
2607		    &io32->pfrio_ndel, &io32->pfrio_nchange, io32->pfrio_flags |
2608		    PFR_FLAG_USERIOCTL, 0);
2609		break;
2610
2611	case DIOCRGETADDRS:
2612		if (io32->pfrio_esize != sizeof (struct pfr_addr)) {
2613			error = ENODEV;
2614			break;
2615		}
2616		pfr_table_copyin_cleanup(&io32->pfrio_table);
2617		error = pfr_get_addrs(&io32->pfrio_table, io32->pfrio_buffer,
2618		    &io32->pfrio_size, io32->pfrio_flags | PFR_FLAG_USERIOCTL);
2619		break;
2620
2621	case DIOCRGETASTATS:
2622		if (io32->pfrio_esize != sizeof (struct pfr_astats)) {
2623			error = ENODEV;
2624			break;
2625		}
2626		pfr_table_copyin_cleanup(&io32->pfrio_table);
2627		error = pfr_get_astats(&io32->pfrio_table, io32->pfrio_buffer,
2628		    &io32->pfrio_size, io32->pfrio_flags | PFR_FLAG_USERIOCTL);
2629		break;
2630
2631	case DIOCRCLRASTATS:
2632		if (io32->pfrio_esize != sizeof (struct pfr_addr)) {
2633			error = ENODEV;
2634			break;
2635		}
2636		pfr_table_copyin_cleanup(&io32->pfrio_table);
2637		error = pfr_clr_astats(&io32->pfrio_table, io32->pfrio_buffer,
2638		    io32->pfrio_size, &io32->pfrio_nzero, io32->pfrio_flags |
2639		    PFR_FLAG_USERIOCTL);
2640		break;
2641
2642	case DIOCRTSTADDRS:
2643		if (io32->pfrio_esize != sizeof (struct pfr_addr)) {
2644			error = ENODEV;
2645			break;
2646		}
2647		pfr_table_copyin_cleanup(&io32->pfrio_table);
2648		error = pfr_tst_addrs(&io32->pfrio_table, io32->pfrio_buffer,
2649		    io32->pfrio_size, &io32->pfrio_nmatch, io32->pfrio_flags |
2650		    PFR_FLAG_USERIOCTL);
2651		break;
2652
2653	case DIOCRINADEFINE:
2654		if (io32->pfrio_esize != sizeof (struct pfr_addr)) {
2655			error = ENODEV;
2656			break;
2657		}
2658		pfr_table_copyin_cleanup(&io32->pfrio_table);
2659		error = pfr_ina_define(&io32->pfrio_table, io32->pfrio_buffer,
2660		    io32->pfrio_size, &io32->pfrio_nadd, &io32->pfrio_naddr,
2661		    io32->pfrio_ticket, io32->pfrio_flags | PFR_FLAG_USERIOCTL);
2662		break;
2663
2664	default:
2665		VERIFY(0);
2666		/* NOTREACHED */
2667	}
2668
2669done:
2670	return (error);
2671}
2672
2673static int
2674pfioctl_ioc_tokens(u_long cmd, struct pfioc_tokens_32 *tok32,
2675    struct pfioc_tokens_64 *tok64, struct proc *p)
2676{
2677	struct pfioc_token *tokens;
2678	struct pfioc_kernel_token *entry, *tmp;
2679	user_addr_t token_buf;
2680	int ocnt, cnt, error = 0, p64 = proc_is64bit(p);
2681	char *ptr;
2682
2683	switch (cmd) {
2684	case DIOCGETSTARTERS: {
2685		int size;
2686
2687		if (nr_tokens == 0) {
2688			error = ENOENT;
2689			break;
2690		}
2691
2692		size = sizeof (struct pfioc_token) * nr_tokens;
2693		ocnt = cnt = (p64 ? tok64->size : tok32->size);
2694		if (cnt == 0) {
2695			if (p64)
2696				tok64->size = size;
2697			else
2698				tok32->size = size;
2699			break;
2700		}
2701
2702		token_buf = (p64 ? tok64->pgt_buf : tok32->pgt_buf);
2703		tokens = _MALLOC(size, M_TEMP, M_WAITOK|M_ZERO);
2704		if (tokens == NULL) {
2705			error = ENOMEM;
2706			break;
2707		}
2708
2709		ptr = (void *)tokens;
2710		SLIST_FOREACH_SAFE(entry, &token_list_head, next, tmp) {
2711			struct pfioc_token *t;
2712
2713			if ((unsigned)cnt < sizeof (*tokens))
2714				break;    /* no more buffer space left */
2715
2716			t = (struct pfioc_token *)(void *)ptr;
2717			t->token_value	= entry->token.token_value;
2718			t->timestamp	= entry->token.timestamp;
2719			t->pid		= entry->token.pid;
2720			bcopy(entry->token.proc_name, t->proc_name,
2721			    PFTOK_PROCNAME_LEN);
2722			ptr += sizeof (struct pfioc_token);
2723
2724			cnt -= sizeof (struct pfioc_token);
2725		}
2726
2727		if (cnt < ocnt)
2728			error = copyout(tokens, token_buf, ocnt - cnt);
2729
2730		if (p64)
2731			tok64->size = ocnt - cnt;
2732		else
2733			tok32->size = ocnt - cnt;
2734
2735		_FREE(tokens, M_TEMP);
2736		break;
2737	}
2738
2739	default:
2740		VERIFY(0);
2741		/* NOTREACHED */
2742	}
2743
2744	return (error);
2745}
2746
2747static void
2748pf_expire_states_and_src_nodes(struct pf_rule *rule)
2749{
2750	struct pf_state		*state;
2751	struct pf_src_node	*sn;
2752	int			 killed = 0;
2753
2754	/* expire the states */
2755	state = TAILQ_FIRST(&state_list);
2756	while (state) {
2757		if (state->rule.ptr == rule)
2758			state->timeout = PFTM_PURGE;
2759		state = TAILQ_NEXT(state, entry_list);
2760	}
2761	pf_purge_expired_states(pf_status.states);
2762
2763	/* expire the src_nodes */
2764	RB_FOREACH(sn, pf_src_tree, &tree_src_tracking) {
2765		if (sn->rule.ptr != rule)
2766			continue;
2767		if (sn->states != 0) {
2768			RB_FOREACH(state, pf_state_tree_id,
2769			    &tree_id) {
2770				if (state->src_node == sn)
2771					state->src_node = NULL;
2772				if (state->nat_src_node == sn)
2773					state->nat_src_node = NULL;
2774			}
2775			sn->states = 0;
2776		}
2777		sn->expire = 1;
2778		killed++;
2779	}
2780	if (killed)
2781		pf_purge_expired_src_nodes();
2782}
2783
2784static void
2785pf_delete_rule_from_ruleset(struct pf_ruleset *ruleset, int rs_num,
2786    struct pf_rule *rule)
2787{
2788	struct pf_rule *r;
2789	int nr = 0;
2790
2791	pf_expire_states_and_src_nodes(rule);
2792
2793	pf_rm_rule(ruleset->rules[rs_num].active.ptr, rule);
2794	if (ruleset->rules[rs_num].active.rcount-- == 0)
2795		panic("%s: rcount value broken!", __func__);
2796	r = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
2797
2798	while (r) {
2799		r->nr = nr++;
2800		r = TAILQ_NEXT(r, entries);
2801	}
2802}
2803
2804
2805static void
2806pf_ruleset_cleanup(struct pf_ruleset *ruleset, int rs)
2807{
2808	pf_calc_skip_steps(ruleset->rules[rs].active.ptr);
2809	ruleset->rules[rs].active.ticket =
2810	    ++ruleset->rules[rs].inactive.ticket;
2811}
2812
2813static int
2814pf_delete_rule_by_ticket(struct pfioc_rule *pr)
2815{
2816	struct pf_ruleset	*ruleset;
2817	struct pf_rule		*rule;
2818	int			 rs_num;
2819	int			 is_anchor;
2820	int			 error;
2821
2822	is_anchor = (pr->anchor_call[0] != '\0');
2823	if ((ruleset = pf_find_ruleset_with_owner(pr->anchor,
2824	    pr->rule.owner, is_anchor, &error)) == NULL)
2825		return (error);
2826
2827	rs_num = pf_get_ruleset_number(pr->rule.action);
2828	if (rs_num >= PF_RULESET_MAX) {
2829		return (EINVAL);
2830	}
2831
2832	if (pr->rule.ticket) {
2833		rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
2834		while (rule && (rule->ticket != pr->rule.ticket))
2835			rule = TAILQ_NEXT(rule, entries);
2836		if (rule == NULL)
2837			return (ENOENT);
2838
2839		if (strcmp(rule->owner, pr->rule.owner))
2840			return (EACCES);
2841
2842delete_rule:
2843		if (rule->anchor && (ruleset != &pf_main_ruleset) &&
2844		    ((strcmp(ruleset->anchor->owner, "")) == 0) &&
2845		    ((ruleset->rules[rs_num].active.rcount - 1) == 0)) {
2846			/* set rule & ruleset to parent and repeat */
2847			struct pf_rule *delete_rule = rule;
2848			struct pf_ruleset *delete_ruleset = ruleset;
2849
2850#define	parent_ruleset		ruleset->anchor->parent->ruleset
2851			if (ruleset->anchor->parent == NULL)
2852				ruleset = &pf_main_ruleset;
2853			else
2854				ruleset = &parent_ruleset;
2855
2856			rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
2857			while (rule &&
2858			    (rule->anchor != delete_ruleset->anchor))
2859				rule = TAILQ_NEXT(rule, entries);
2860			if (rule == NULL)
2861				panic("%s: rule not found!", __func__);
2862
2863			if (delete_rule->rule_flag & PFRULE_PFM)
2864				pffwrules--;
2865
2866			pf_delete_rule_from_ruleset(delete_ruleset,
2867			    rs_num, delete_rule);
2868			delete_ruleset->rules[rs_num].active.ticket =
2869			    ++delete_ruleset->rules[rs_num].inactive.ticket;
2870
2871			goto delete_rule;
2872		} else {
2873			if (rule->rule_flag & PFRULE_PFM)
2874				pffwrules--;
2875			pf_delete_rule_from_ruleset(ruleset, rs_num,
2876			    rule);
2877			pf_ruleset_cleanup(ruleset, rs_num);
2878		}
2879	}
2880
2881	return (0);
2882}
2883
2884static void
2885pf_delete_rule_by_owner(char *owner)
2886{
2887	struct pf_ruleset	*ruleset;
2888	struct pf_rule		*rule, *next;
2889	int			 deleted = 0;
2890
2891	for (int rs = 0; rs < PF_RULESET_MAX; rs++) {
2892		rule = TAILQ_FIRST(pf_main_ruleset.rules[rs].active.ptr);
2893		ruleset = &pf_main_ruleset;
2894		while (rule) {
2895			next = TAILQ_NEXT(rule, entries);
2896			if (rule->anchor) {
2897				if (((strcmp(rule->owner, owner)) == 0) ||
2898				    ((strcmp(rule->owner, "")) == 0)) {
2899					if (rule->anchor->ruleset.rules[rs].active.rcount > 0) {
2900						if (deleted) {
2901							pf_ruleset_cleanup(ruleset, rs);
2902							deleted = 0;
2903						}
2904						/* step into anchor */
2905						ruleset =
2906						    &rule->anchor->ruleset;
2907						rule = TAILQ_FIRST(ruleset->rules[rs].active.ptr);
2908						continue;
2909					} else {
2910						if (rule->rule_flag &
2911						    PFRULE_PFM)
2912							pffwrules--;
2913						pf_delete_rule_from_ruleset(ruleset, rs, rule);
2914						deleted = 1;
2915						rule = next;
2916					}
2917				} else
2918					rule = next;
2919			} else {
2920				if (((strcmp(rule->owner, owner)) == 0)) {
2921					/* delete rule */
2922					if (rule->rule_flag & PFRULE_PFM)
2923						pffwrules--;
2924					pf_delete_rule_from_ruleset(ruleset,
2925					    rs, rule);
2926					deleted = 1;
2927				}
2928				rule = next;
2929			}
2930			if (rule == NULL) {
2931				if (deleted) {
2932					pf_ruleset_cleanup(ruleset, rs);
2933					deleted = 0;
2934				}
2935				if (ruleset != &pf_main_ruleset)
2936					pf_deleterule_anchor_step_out(&ruleset,
2937					    rs, &rule);
2938			}
2939		}
2940	}
2941}
2942
2943static void
2944pf_deleterule_anchor_step_out(struct pf_ruleset **ruleset_ptr,
2945    int rs, struct pf_rule **rule_ptr)
2946{
2947	struct pf_ruleset *ruleset = *ruleset_ptr;
2948	struct pf_rule *rule = *rule_ptr;
2949
2950	/* step out of anchor */
2951	struct pf_ruleset *rs_copy = ruleset;
2952	ruleset = ruleset->anchor->parent?
2953	    &ruleset->anchor->parent->ruleset:&pf_main_ruleset;
2954
2955	rule = TAILQ_FIRST(ruleset->rules[rs].active.ptr);
2956	while (rule && (rule->anchor != rs_copy->anchor))
2957		rule = TAILQ_NEXT(rule, entries);
2958	if (rule == NULL)
2959		panic("%s: parent rule of anchor not found!", __func__);
2960	if (rule->anchor->ruleset.rules[rs].active.rcount > 0)
2961		rule = TAILQ_NEXT(rule, entries);
2962
2963	*ruleset_ptr = ruleset;
2964	*rule_ptr = rule;
2965}
2966
2967static int
2968pf_rule_setup(struct pfioc_rule *pr, struct pf_rule *rule,
2969    struct pf_ruleset *ruleset) {
2970	struct pf_pooladdr 	*apa;
2971	int			 error = 0;
2972
2973	if (rule->ifname[0]) {
2974		rule->kif = pfi_kif_get(rule->ifname);
2975		if (rule->kif == NULL) {
2976			pool_put(&pf_rule_pl, rule);
2977			return (EINVAL);
2978		}
2979		pfi_kif_ref(rule->kif, PFI_KIF_REF_RULE);
2980	}
2981#if PF_ALTQ
2982	/* set queue IDs */
2983	if (altq_allowed && rule->qname[0] != '\0') {
2984		if ((rule->qid = pf_qname2qid(rule->qname)) == 0)
2985			error = EBUSY;
2986		else if (rule->pqname[0] != '\0') {
2987			if ((rule->pqid =
2988			    pf_qname2qid(rule->pqname)) == 0)
2989				error = EBUSY;
2990		} else
2991			rule->pqid = rule->qid;
2992	}
2993#endif /* PF_ALTQ */
2994	if (rule->tagname[0])
2995		if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
2996			error = EBUSY;
2997	if (rule->match_tagname[0])
2998		if ((rule->match_tag =
2999		    pf_tagname2tag(rule->match_tagname)) == 0)
3000			error = EBUSY;
3001	if (rule->rt && !rule->direction)
3002		error = EINVAL;
3003#if PFLOG
3004	if (!rule->log)
3005		rule->logif = 0;
3006	if (rule->logif >= PFLOGIFS_MAX)
3007		error = EINVAL;
3008#endif /* PFLOG */
3009	if (pf_rtlabel_add(&rule->src.addr) ||
3010	    pf_rtlabel_add(&rule->dst.addr))
3011		error = EBUSY;
3012	if (pfi_dynaddr_setup(&rule->src.addr, rule->af))
3013		error = EINVAL;
3014	if (pfi_dynaddr_setup(&rule->dst.addr, rule->af))
3015		error = EINVAL;
3016	if (pf_tbladdr_setup(ruleset, &rule->src.addr))
3017		error = EINVAL;
3018	if (pf_tbladdr_setup(ruleset, &rule->dst.addr))
3019		error = EINVAL;
3020	if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
3021		error = EINVAL;
3022	TAILQ_FOREACH(apa, &pf_pabuf, entries)
3023		if (pf_tbladdr_setup(ruleset, &apa->addr))
3024			error = EINVAL;
3025
3026	if (rule->overload_tblname[0]) {
3027		if ((rule->overload_tbl = pfr_attach_table(ruleset,
3028		    rule->overload_tblname)) == NULL)
3029			error = EINVAL;
3030		else
3031			rule->overload_tbl->pfrkt_flags |=
3032			    PFR_TFLAG_ACTIVE;
3033	}
3034
3035	pf_mv_pool(&pf_pabuf, &rule->rpool.list);
3036	if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
3037	    (rule->action == PF_BINAT)) && rule->anchor == NULL) ||
3038	    (rule->rt > PF_FASTROUTE)) &&
3039	    (TAILQ_FIRST(&rule->rpool.list) == NULL))
3040		error = EINVAL;
3041
3042	if (error) {
3043		pf_rm_rule(NULL, rule);
3044		return (error);
3045	}
3046	rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
3047	rule->evaluations = rule->packets[0] = rule->packets[1] =
3048	    rule->bytes[0] = rule->bytes[1] = 0;
3049
3050	return (0);
3051}
3052
3053static int
3054pfioctl_ioc_rule(u_long cmd, int minordev, struct pfioc_rule *pr, struct proc *p)
3055{
3056	int error = 0;
3057
3058	switch (cmd) {
3059	case DIOCADDRULE: {
3060		struct pf_ruleset	*ruleset;
3061		struct pf_rule		*rule, *tail;
3062		int			rs_num;
3063
3064		pr->anchor[sizeof (pr->anchor) - 1] = '\0';
3065		pr->anchor_call[sizeof (pr->anchor_call) - 1] = '\0';
3066		ruleset = pf_find_ruleset(pr->anchor);
3067		if (ruleset == NULL) {
3068			error = EINVAL;
3069			break;
3070		}
3071		rs_num = pf_get_ruleset_number(pr->rule.action);
3072		if (rs_num >= PF_RULESET_MAX) {
3073			error = EINVAL;
3074			break;
3075		}
3076		if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
3077			error = EINVAL;
3078			break;
3079		}
3080		if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) {
3081			error = EBUSY;
3082			break;
3083		}
3084		if (pr->pool_ticket != ticket_pabuf) {
3085			error = EBUSY;
3086			break;
3087		}
3088		rule = pool_get(&pf_rule_pl, PR_WAITOK);
3089		if (rule == NULL) {
3090			error = ENOMEM;
3091			break;
3092		}
3093		pf_rule_copyin(&pr->rule, rule, p, minordev);
3094#if !INET
3095		if (rule->af == AF_INET) {
3096			pool_put(&pf_rule_pl, rule);
3097			error = EAFNOSUPPORT;
3098			break;
3099		}
3100#endif /* INET */
3101#if !INET6
3102		if (rule->af == AF_INET6) {
3103			pool_put(&pf_rule_pl, rule);
3104			error = EAFNOSUPPORT;
3105			break;
3106		}
3107#endif /* INET6 */
3108		tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
3109		    pf_rulequeue);
3110		if (tail)
3111			rule->nr = tail->nr + 1;
3112		else
3113			rule->nr = 0;
3114
3115		if ((error = pf_rule_setup(pr, rule, ruleset)))
3116			break;
3117
3118		TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr,
3119		    rule, entries);
3120		ruleset->rules[rs_num].inactive.rcount++;
3121		if (rule->rule_flag & PFRULE_PFM)
3122			pffwrules++;
3123		break;
3124	}
3125
3126	case DIOCGETRULES: {
3127		struct pf_ruleset	*ruleset;
3128		struct pf_rule		*tail;
3129		int			 rs_num;
3130
3131		pr->anchor[sizeof (pr->anchor) - 1] = '\0';
3132		pr->anchor_call[sizeof (pr->anchor_call) - 1] = '\0';
3133		ruleset = pf_find_ruleset(pr->anchor);
3134		if (ruleset == NULL) {
3135			error = EINVAL;
3136			break;
3137		}
3138		rs_num = pf_get_ruleset_number(pr->rule.action);
3139		if (rs_num >= PF_RULESET_MAX) {
3140			error = EINVAL;
3141			break;
3142		}
3143		tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
3144		    pf_rulequeue);
3145		if (tail)
3146			pr->nr = tail->nr + 1;
3147		else
3148			pr->nr = 0;
3149		pr->ticket = ruleset->rules[rs_num].active.ticket;
3150		break;
3151	}
3152
3153	case DIOCGETRULE: {
3154		struct pf_ruleset	*ruleset;
3155		struct pf_rule		*rule;
3156		int			 rs_num, i;
3157
3158		pr->anchor[sizeof (pr->anchor) - 1] = '\0';
3159		pr->anchor_call[sizeof (pr->anchor_call) - 1] = '\0';
3160		ruleset = pf_find_ruleset(pr->anchor);
3161		if (ruleset == NULL) {
3162			error = EINVAL;
3163			break;
3164		}
3165		rs_num = pf_get_ruleset_number(pr->rule.action);
3166		if (rs_num >= PF_RULESET_MAX) {
3167			error = EINVAL;
3168			break;
3169		}
3170		if (pr->ticket != ruleset->rules[rs_num].active.ticket) {
3171			error = EBUSY;
3172			break;
3173		}
3174		rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
3175		while ((rule != NULL) && (rule->nr != pr->nr))
3176			rule = TAILQ_NEXT(rule, entries);
3177		if (rule == NULL) {
3178			error = EBUSY;
3179			break;
3180		}
3181		pf_rule_copyout(rule, &pr->rule);
3182		if (pf_anchor_copyout(ruleset, rule, pr)) {
3183			error = EBUSY;
3184			break;
3185		}
3186		pfi_dynaddr_copyout(&pr->rule.src.addr);
3187		pfi_dynaddr_copyout(&pr->rule.dst.addr);
3188		pf_tbladdr_copyout(&pr->rule.src.addr);
3189		pf_tbladdr_copyout(&pr->rule.dst.addr);
3190		pf_rtlabel_copyout(&pr->rule.src.addr);
3191		pf_rtlabel_copyout(&pr->rule.dst.addr);
3192		for (i = 0; i < PF_SKIP_COUNT; ++i)
3193			if (rule->skip[i].ptr == NULL)
3194				pr->rule.skip[i].nr = -1;
3195			else
3196				pr->rule.skip[i].nr =
3197				    rule->skip[i].ptr->nr;
3198
3199		if (pr->action == PF_GET_CLR_CNTR) {
3200			rule->evaluations = 0;
3201			rule->packets[0] = rule->packets[1] = 0;
3202			rule->bytes[0] = rule->bytes[1] = 0;
3203		}
3204		break;
3205	}
3206
3207	case DIOCCHANGERULE: {
3208		struct pfioc_rule	*pcr = pr;
3209		struct pf_ruleset	*ruleset;
3210		struct pf_rule		*oldrule = NULL, *newrule = NULL;
3211		struct pf_pooladdr	*pa;
3212		u_int32_t		 nr = 0;
3213		int			 rs_num;
3214
3215		if (!(pcr->action == PF_CHANGE_REMOVE ||
3216		    pcr->action == PF_CHANGE_GET_TICKET) &&
3217		    pcr->pool_ticket != ticket_pabuf) {
3218			error = EBUSY;
3219			break;
3220		}
3221
3222		if (pcr->action < PF_CHANGE_ADD_HEAD ||
3223		    pcr->action > PF_CHANGE_GET_TICKET) {
3224			error = EINVAL;
3225			break;
3226		}
3227		pcr->anchor[sizeof (pcr->anchor) - 1] = '\0';
3228		pcr->anchor_call[sizeof (pcr->anchor_call) - 1] = '\0';
3229		ruleset = pf_find_ruleset(pcr->anchor);
3230		if (ruleset == NULL) {
3231			error = EINVAL;
3232			break;
3233		}
3234		rs_num = pf_get_ruleset_number(pcr->rule.action);
3235		if (rs_num >= PF_RULESET_MAX) {
3236			error = EINVAL;
3237			break;
3238		}
3239
3240		if (pcr->action == PF_CHANGE_GET_TICKET) {
3241			pcr->ticket = ++ruleset->rules[rs_num].active.ticket;
3242			break;
3243		} else {
3244			if (pcr->ticket !=
3245			    ruleset->rules[rs_num].active.ticket) {
3246				error = EINVAL;
3247				break;
3248			}
3249			if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
3250				error = EINVAL;
3251				break;
3252			}
3253		}
3254
3255		if (pcr->action != PF_CHANGE_REMOVE) {
3256			newrule = pool_get(&pf_rule_pl, PR_WAITOK);
3257			if (newrule == NULL) {
3258				error = ENOMEM;
3259				break;
3260			}
3261			pf_rule_copyin(&pcr->rule, newrule, p, minordev);
3262#if !INET
3263			if (newrule->af == AF_INET) {
3264				pool_put(&pf_rule_pl, newrule);
3265				error = EAFNOSUPPORT;
3266				break;
3267			}
3268#endif /* INET */
3269#if !INET6
3270			if (newrule->af == AF_INET6) {
3271				pool_put(&pf_rule_pl, newrule);
3272				error = EAFNOSUPPORT;
3273				break;
3274			}
3275#endif /* INET6 */
3276			if (newrule->ifname[0]) {
3277				newrule->kif = pfi_kif_get(newrule->ifname);
3278				if (newrule->kif == NULL) {
3279					pool_put(&pf_rule_pl, newrule);
3280					error = EINVAL;
3281					break;
3282				}
3283				pfi_kif_ref(newrule->kif, PFI_KIF_REF_RULE);
3284			} else
3285				newrule->kif = NULL;
3286
3287#if PF_ALTQ
3288			/* set queue IDs */
3289			if (altq_allowed && newrule->qname[0] != '\0') {
3290				if ((newrule->qid =
3291				    pf_qname2qid(newrule->qname)) == 0)
3292					error = EBUSY;
3293				else if (newrule->pqname[0] != '\0') {
3294					if ((newrule->pqid =
3295					    pf_qname2qid(newrule->pqname)) == 0)
3296						error = EBUSY;
3297				} else
3298					newrule->pqid = newrule->qid;
3299			}
3300#endif /* PF_ALTQ */
3301			if (newrule->tagname[0])
3302				if ((newrule->tag =
3303				    pf_tagname2tag(newrule->tagname)) == 0)
3304					error = EBUSY;
3305			if (newrule->match_tagname[0])
3306				if ((newrule->match_tag = pf_tagname2tag(
3307				    newrule->match_tagname)) == 0)
3308					error = EBUSY;
3309			if (newrule->rt && !newrule->direction)
3310				error = EINVAL;
3311#if PFLOG
3312			if (!newrule->log)
3313				newrule->logif = 0;
3314			if (newrule->logif >= PFLOGIFS_MAX)
3315				error = EINVAL;
3316#endif /* PFLOG */
3317			if (pf_rtlabel_add(&newrule->src.addr) ||
3318			    pf_rtlabel_add(&newrule->dst.addr))
3319				error = EBUSY;
3320			if (pfi_dynaddr_setup(&newrule->src.addr, newrule->af))
3321				error = EINVAL;
3322			if (pfi_dynaddr_setup(&newrule->dst.addr, newrule->af))
3323				error = EINVAL;
3324			if (pf_tbladdr_setup(ruleset, &newrule->src.addr))
3325				error = EINVAL;
3326			if (pf_tbladdr_setup(ruleset, &newrule->dst.addr))
3327				error = EINVAL;
3328			if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
3329				error = EINVAL;
3330			TAILQ_FOREACH(pa, &pf_pabuf, entries)
3331				if (pf_tbladdr_setup(ruleset, &pa->addr))
3332					error = EINVAL;
3333
3334			if (newrule->overload_tblname[0]) {
3335				if ((newrule->overload_tbl = pfr_attach_table(
3336				    ruleset, newrule->overload_tblname)) ==
3337				    NULL)
3338					error = EINVAL;
3339				else
3340					newrule->overload_tbl->pfrkt_flags |=
3341					    PFR_TFLAG_ACTIVE;
3342			}
3343
3344			pf_mv_pool(&pf_pabuf, &newrule->rpool.list);
3345			if (((((newrule->action == PF_NAT) ||
3346			    (newrule->action == PF_RDR) ||
3347			    (newrule->action == PF_BINAT) ||
3348			    (newrule->rt > PF_FASTROUTE)) &&
3349			    !newrule->anchor)) &&
3350			    (TAILQ_FIRST(&newrule->rpool.list) == NULL))
3351				error = EINVAL;
3352
3353			if (error) {
3354				pf_rm_rule(NULL, newrule);
3355				break;
3356			}
3357			newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list);
3358			newrule->evaluations = 0;
3359			newrule->packets[0] = newrule->packets[1] = 0;
3360			newrule->bytes[0] = newrule->bytes[1] = 0;
3361		}
3362		pf_empty_pool(&pf_pabuf);
3363
3364		if (pcr->action == PF_CHANGE_ADD_HEAD)
3365			oldrule = TAILQ_FIRST(
3366			    ruleset->rules[rs_num].active.ptr);
3367		else if (pcr->action == PF_CHANGE_ADD_TAIL)
3368			oldrule = TAILQ_LAST(
3369			    ruleset->rules[rs_num].active.ptr, pf_rulequeue);
3370		else {
3371			oldrule = TAILQ_FIRST(
3372			    ruleset->rules[rs_num].active.ptr);
3373			while ((oldrule != NULL) && (oldrule->nr != pcr->nr))
3374				oldrule = TAILQ_NEXT(oldrule, entries);
3375			if (oldrule == NULL) {
3376				if (newrule != NULL)
3377					pf_rm_rule(NULL, newrule);
3378				error = EINVAL;
3379				break;
3380			}
3381		}
3382
3383		if (pcr->action == PF_CHANGE_REMOVE) {
3384			pf_rm_rule(ruleset->rules[rs_num].active.ptr, oldrule);
3385			ruleset->rules[rs_num].active.rcount--;
3386		} else {
3387			if (oldrule == NULL)
3388				TAILQ_INSERT_TAIL(
3389				    ruleset->rules[rs_num].active.ptr,
3390				    newrule, entries);
3391			else if (pcr->action == PF_CHANGE_ADD_HEAD ||
3392			    pcr->action == PF_CHANGE_ADD_BEFORE)
3393				TAILQ_INSERT_BEFORE(oldrule, newrule, entries);
3394			else
3395				TAILQ_INSERT_AFTER(
3396				    ruleset->rules[rs_num].active.ptr,
3397				    oldrule, newrule, entries);
3398			ruleset->rules[rs_num].active.rcount++;
3399		}
3400
3401		nr = 0;
3402		TAILQ_FOREACH(oldrule,
3403		    ruleset->rules[rs_num].active.ptr, entries)
3404			oldrule->nr = nr++;
3405
3406		ruleset->rules[rs_num].active.ticket++;
3407
3408		pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
3409		pf_remove_if_empty_ruleset(ruleset);
3410
3411		break;
3412	}
3413
3414	case DIOCINSERTRULE: {
3415		struct pf_ruleset	*ruleset;
3416		struct pf_rule		*rule, *tail, *r;
3417		int			rs_num;
3418		int			is_anchor;
3419
3420		pr->anchor[sizeof (pr->anchor) - 1] = '\0';
3421		pr->anchor_call[sizeof (pr->anchor_call) - 1] = '\0';
3422		is_anchor = (pr->anchor_call[0] != '\0');
3423
3424		if ((ruleset = pf_find_ruleset_with_owner(pr->anchor,
3425		    pr->rule.owner, is_anchor, &error)) == NULL)
3426			break;
3427
3428		rs_num = pf_get_ruleset_number(pr->rule.action);
3429		if (rs_num >= PF_RULESET_MAX) {
3430			error = EINVAL;
3431			break;
3432		}
3433		if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
3434			error = EINVAL;
3435			break;
3436		}
3437
3438		/* make sure this anchor rule doesn't exist already */
3439		if (is_anchor) {
3440			r = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
3441			while (r) {
3442				if (r->anchor &&
3443				    ((strcmp(r->anchor->name,
3444				    pr->anchor_call)) == 0)) {
3445					if (((strcmp(pr->rule.owner,
3446					    r->owner)) == 0) ||
3447					    ((strcmp(r->owner, "")) == 0))
3448						error = EEXIST;
3449					else
3450						error = EPERM;
3451					break;
3452				}
3453				r = TAILQ_NEXT(r, entries);
3454			}
3455		}
3456
3457		rule = pool_get(&pf_rule_pl, PR_WAITOK);
3458		if (rule == NULL) {
3459			error = ENOMEM;
3460			break;
3461		}
3462		pf_rule_copyin(&pr->rule, rule, p, minordev);
3463#if !INET
3464		if (rule->af == AF_INET) {
3465			pool_put(&pf_rule_pl, rule);
3466			error = EAFNOSUPPORT;
3467			break;
3468		}
3469#endif /* INET */
3470#if !INET6
3471		if (rule->af == AF_INET6) {
3472			pool_put(&pf_rule_pl, rule);
3473			error = EAFNOSUPPORT;
3474			break;
3475		}
3476
3477#endif /* INET6 */
3478		r = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
3479		while ((r != NULL) && (rule->priority >= (unsigned)r->priority))
3480			r = TAILQ_NEXT(r, entries);
3481		if (r == NULL) {
3482			if ((tail =
3483			    TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
3484			    pf_rulequeue)) != NULL)
3485				rule->nr = tail->nr + 1;
3486			else
3487				rule->nr = 0;
3488		} else {
3489			rule->nr = r->nr;
3490		}
3491
3492		if ((error = pf_rule_setup(pr, rule, ruleset)))
3493			break;
3494
3495		if (rule->anchor != NULL)
3496			strncpy(rule->anchor->owner, rule->owner,
3497			    PF_OWNER_NAME_SIZE);
3498
3499		if (r) {
3500			TAILQ_INSERT_BEFORE(r, rule, entries);
3501			while (r && ++r->nr)
3502				r = TAILQ_NEXT(r, entries);
3503		} else
3504			TAILQ_INSERT_TAIL(ruleset->rules[rs_num].active.ptr,
3505			    rule, entries);
3506		ruleset->rules[rs_num].active.rcount++;
3507
3508		/* Calculate checksum for the main ruleset */
3509		if (ruleset == &pf_main_ruleset)
3510			error = pf_setup_pfsync_matching(ruleset);
3511
3512		pf_ruleset_cleanup(ruleset, rs_num);
3513		rule->ticket = ruleset->rules[rs_num].active.ticket;
3514
3515		pr->rule.ticket = rule->ticket;
3516		pf_rule_copyout(rule, &pr->rule);
3517		if (rule->rule_flag & PFRULE_PFM)
3518			pffwrules++;
3519		break;
3520	}
3521
3522	case DIOCDELETERULE: {
3523		pr->anchor[sizeof (pr->anchor) - 1] = '\0';
3524		pr->anchor_call[sizeof (pr->anchor_call) - 1] = '\0';
3525
3526		if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
3527			error = EINVAL;
3528			break;
3529		}
3530
3531		if (pr->rule.ticket) {
3532			if ((error = pf_delete_rule_by_ticket(pr)))
3533				break;
3534		} else
3535			pf_delete_rule_by_owner(pr->rule.owner);
3536		pr->nr = pffwrules;
3537		break;
3538	}
3539
3540	default:
3541		VERIFY(0);
3542		/* NOTREACHED */
3543	}
3544
3545	return (error);
3546}
3547
3548static int
3549pfioctl_ioc_state_kill(u_long cmd, struct pfioc_state_kill *psk, struct proc *p)
3550{
3551#pragma unused(p)
3552	int error = 0;
3553
3554	switch (cmd) {
3555	case DIOCCLRSTATES: {
3556		struct pf_state		*s, *nexts;
3557		int			 killed = 0;
3558
3559		psk->psk_ifname[sizeof (psk->psk_ifname) - 1] = '\0';
3560		for (s = RB_MIN(pf_state_tree_id, &tree_id); s; s = nexts) {
3561			nexts = RB_NEXT(pf_state_tree_id, &tree_id, s);
3562
3563			if (!psk->psk_ifname[0] || strcmp(psk->psk_ifname,
3564			    s->kif->pfik_name) == 0) {
3565#if NPFSYNC
3566				/* don't send out individual delete messages */
3567				s->sync_flags = PFSTATE_NOSYNC;
3568#endif
3569				pf_unlink_state(s);
3570				killed++;
3571			}
3572		}
3573		psk->psk_af = killed;
3574#if NPFSYNC
3575		pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
3576#endif
3577		break;
3578	}
3579
3580	case DIOCKILLSTATES: {
3581		struct pf_state		*s, *nexts;
3582		struct pf_state_key	*sk;
3583		struct pf_state_host	*src, *dst;
3584		int			 killed = 0;
3585
3586		for (s = RB_MIN(pf_state_tree_id, &tree_id); s;
3587		    s = nexts) {
3588			nexts = RB_NEXT(pf_state_tree_id, &tree_id, s);
3589			sk = s->state_key;
3590
3591			if (sk->direction == PF_OUT) {
3592				src = &sk->lan;
3593				dst = &sk->ext;
3594			} else {
3595				src = &sk->ext;
3596				dst = &sk->lan;
3597			}
3598			if ((!psk->psk_af || sk->af == psk->psk_af) &&
3599			    (!psk->psk_proto || psk->psk_proto == sk->proto) &&
3600			    PF_MATCHA(psk->psk_src.neg,
3601			    &psk->psk_src.addr.v.a.addr,
3602			    &psk->psk_src.addr.v.a.mask,
3603			    &src->addr, sk->af) &&
3604			    PF_MATCHA(psk->psk_dst.neg,
3605			    &psk->psk_dst.addr.v.a.addr,
3606			    &psk->psk_dst.addr.v.a.mask,
3607			    &dst->addr, sk->af) &&
3608			    (pf_match_xport(psk->psk_proto,
3609			    psk->psk_proto_variant, &psk->psk_src.xport,
3610			    &src->xport)) &&
3611			    (pf_match_xport(psk->psk_proto,
3612			    psk->psk_proto_variant, &psk->psk_dst.xport,
3613			    &dst->xport)) &&
3614			    (!psk->psk_ifname[0] || strcmp(psk->psk_ifname,
3615			    s->kif->pfik_name) == 0)) {
3616#if NPFSYNC
3617				/* send immediate delete of state */
3618				pfsync_delete_state(s);
3619				s->sync_flags |= PFSTATE_NOSYNC;
3620#endif
3621				pf_unlink_state(s);
3622				killed++;
3623			}
3624		}
3625		psk->psk_af = killed;
3626		break;
3627	}
3628
3629	default:
3630		VERIFY(0);
3631		/* NOTREACHED */
3632	}
3633
3634	return (error);
3635}
3636
3637static int
3638pfioctl_ioc_state(u_long cmd, struct pfioc_state *ps, struct proc *p)
3639{
3640#pragma unused(p)
3641	int error = 0;
3642
3643	switch (cmd) {
3644	case DIOCADDSTATE: {
3645		struct pfsync_state	*sp = &ps->state;
3646		struct pf_state		*s;
3647		struct pf_state_key	*sk;
3648		struct pfi_kif		*kif;
3649
3650		if (sp->timeout >= PFTM_MAX &&
3651		    sp->timeout != PFTM_UNTIL_PACKET) {
3652			error = EINVAL;
3653			break;
3654		}
3655		s = pool_get(&pf_state_pl, PR_WAITOK);
3656		if (s == NULL) {
3657			error = ENOMEM;
3658			break;
3659		}
3660		bzero(s, sizeof (struct pf_state));
3661		if ((sk = pf_alloc_state_key(s, NULL)) == NULL) {
3662			pool_put(&pf_state_pl, s);
3663			error = ENOMEM;
3664			break;
3665		}
3666		pf_state_import(sp, sk, s);
3667		kif = pfi_kif_get(sp->ifname);
3668		if (kif == NULL) {
3669			pool_put(&pf_state_pl, s);
3670			pool_put(&pf_state_key_pl, sk);
3671			error = ENOENT;
3672			break;
3673		}
3674		TAILQ_INIT(&s->unlink_hooks);
3675		s->state_key->app_state = 0;
3676		if (pf_insert_state(kif, s)) {
3677			pfi_kif_unref(kif, PFI_KIF_REF_NONE);
3678			pool_put(&pf_state_pl, s);
3679			error = EEXIST;
3680			break;
3681		}
3682		pf_default_rule.states++;
3683		VERIFY(pf_default_rule.states != 0);
3684		break;
3685	}
3686
3687	case DIOCGETSTATE: {
3688		struct pf_state		*s;
3689		struct pf_state_cmp	 id_key;
3690
3691		bcopy(ps->state.id, &id_key.id, sizeof (id_key.id));
3692		id_key.creatorid = ps->state.creatorid;
3693
3694		s = pf_find_state_byid(&id_key);
3695		if (s == NULL) {
3696			error = ENOENT;
3697			break;
3698		}
3699
3700		pf_state_export(&ps->state, s->state_key, s);
3701		break;
3702	}
3703
3704	default:
3705		VERIFY(0);
3706		/* NOTREACHED */
3707	}
3708
3709	return (error);
3710}
3711
3712static int
3713pfioctl_ioc_states(u_long cmd, struct pfioc_states_32 *ps32,
3714    struct pfioc_states_64 *ps64, struct proc *p)
3715{
3716	int p64 = proc_is64bit(p);
3717	int error = 0;
3718
3719	switch (cmd) {
3720	case DIOCGETSTATES: {		/* struct pfioc_states */
3721		struct pf_state		*state;
3722		struct pfsync_state	*pstore;
3723		user_addr_t		 buf;
3724		u_int32_t		 nr = 0;
3725		int			 len, size;
3726
3727		len = (p64 ? ps64->ps_len : ps32->ps_len);
3728		if (len == 0) {
3729			size = sizeof (struct pfsync_state) * pf_status.states;
3730			if (p64)
3731				ps64->ps_len = size;
3732			else
3733				ps32->ps_len = size;
3734			break;
3735		}
3736
3737		pstore = _MALLOC(sizeof (*pstore), M_TEMP, M_WAITOK);
3738		if (pstore == NULL) {
3739			error = ENOMEM;
3740			break;
3741		}
3742		buf = (p64 ? ps64->ps_buf : ps32->ps_buf);
3743
3744		state = TAILQ_FIRST(&state_list);
3745		while (state) {
3746			if (state->timeout != PFTM_UNLINKED) {
3747				if ((nr + 1) * sizeof (*pstore) > (unsigned)len)
3748					break;
3749
3750				pf_state_export(pstore,
3751				    state->state_key, state);
3752				error = copyout(pstore, buf, sizeof (*pstore));
3753				if (error) {
3754					_FREE(pstore, M_TEMP);
3755					goto fail;
3756				}
3757				buf += sizeof (*pstore);
3758				nr++;
3759			}
3760			state = TAILQ_NEXT(state, entry_list);
3761		}
3762
3763		size = sizeof (struct pfsync_state) * nr;
3764		if (p64)
3765			ps64->ps_len = size;
3766		else
3767			ps32->ps_len = size;
3768
3769		_FREE(pstore, M_TEMP);
3770		break;
3771	}
3772
3773	default:
3774		VERIFY(0);
3775		/* NOTREACHED */
3776	}
3777fail:
3778	return (error);
3779}
3780
3781static int
3782pfioctl_ioc_natlook(u_long cmd, struct pfioc_natlook *pnl, struct proc *p)
3783{
3784#pragma unused(p)
3785	int error = 0;
3786
3787	switch (cmd) {
3788	case DIOCNATLOOK: {
3789		struct pf_state_key	*sk;
3790		struct pf_state		*state;
3791		struct pf_state_key_cmp	 key;
3792		int			 m = 0, direction = pnl->direction;
3793
3794		key.af = pnl->af;
3795		key.proto = pnl->proto;
3796		key.proto_variant = pnl->proto_variant;
3797
3798		if (!pnl->proto ||
3799		    PF_AZERO(&pnl->saddr, pnl->af) ||
3800		    PF_AZERO(&pnl->daddr, pnl->af) ||
3801		    ((pnl->proto == IPPROTO_TCP ||
3802		    pnl->proto == IPPROTO_UDP) &&
3803		    (!pnl->dxport.port || !pnl->sxport.port)))
3804			error = EINVAL;
3805		else {
3806			/*
3807			 * userland gives us source and dest of connection,
3808			 * reverse the lookup so we ask for what happens with
3809			 * the return traffic, enabling us to find it in the
3810			 * state tree.
3811			 */
3812			if (direction == PF_IN) {
3813				PF_ACPY(&key.ext.addr, &pnl->daddr, pnl->af);
3814				memcpy(&key.ext.xport, &pnl->dxport,
3815				    sizeof (key.ext.xport));
3816				PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af);
3817				memcpy(&key.gwy.xport, &pnl->sxport,
3818				    sizeof (key.gwy.xport));
3819				state = pf_find_state_all(&key, PF_IN, &m);
3820			} else {
3821				PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af);
3822				memcpy(&key.lan.xport, &pnl->dxport,
3823				    sizeof (key.lan.xport));
3824				PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af);
3825				memcpy(&key.ext.xport, &pnl->sxport,
3826				    sizeof (key.ext.xport));
3827				state = pf_find_state_all(&key, PF_OUT, &m);
3828			}
3829			if (m > 1)
3830				error = E2BIG;	/* more than one state */
3831			else if (state != NULL) {
3832				sk = state->state_key;
3833				if (direction == PF_IN) {
3834					PF_ACPY(&pnl->rsaddr, &sk->lan.addr,
3835					    sk->af);
3836					memcpy(&pnl->rsxport, &sk->lan.xport,
3837					    sizeof (pnl->rsxport));
3838					PF_ACPY(&pnl->rdaddr, &pnl->daddr,
3839					    pnl->af);
3840					memcpy(&pnl->rdxport, &pnl->dxport,
3841					    sizeof (pnl->rdxport));
3842				} else {
3843					PF_ACPY(&pnl->rdaddr, &sk->gwy.addr,
3844					    sk->af);
3845					memcpy(&pnl->rdxport, &sk->gwy.xport,
3846					    sizeof (pnl->rdxport));
3847					PF_ACPY(&pnl->rsaddr, &pnl->saddr,
3848					    pnl->af);
3849					memcpy(&pnl->rsxport, &pnl->sxport,
3850					    sizeof (pnl->rsxport));
3851				}
3852			} else
3853				error = ENOENT;
3854		}
3855		break;
3856	}
3857
3858	default:
3859		VERIFY(0);
3860		/* NOTREACHED */
3861	}
3862
3863	return (error);
3864}
3865
3866static int
3867pfioctl_ioc_tm(u_long cmd, struct pfioc_tm *pt, struct proc *p)
3868{
3869#pragma unused(p)
3870	int error = 0;
3871
3872	switch (cmd) {
3873	case DIOCSETTIMEOUT: {
3874		int old;
3875
3876		if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
3877		    pt->seconds < 0) {
3878			error = EINVAL;
3879			goto fail;
3880		}
3881		old = pf_default_rule.timeout[pt->timeout];
3882		if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0)
3883			pt->seconds = 1;
3884		pf_default_rule.timeout[pt->timeout] = pt->seconds;
3885		if (pt->timeout == PFTM_INTERVAL && pt->seconds < old)
3886			wakeup(pf_purge_thread_fn);
3887		pt->seconds = old;
3888		break;
3889	}
3890
3891	case DIOCGETTIMEOUT: {
3892		if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
3893			error = EINVAL;
3894			goto fail;
3895		}
3896		pt->seconds = pf_default_rule.timeout[pt->timeout];
3897		break;
3898	}
3899
3900	default:
3901		VERIFY(0);
3902		/* NOTREACHED */
3903	}
3904fail:
3905	return (error);
3906}
3907
3908static int
3909pfioctl_ioc_limit(u_long cmd, struct pfioc_limit *pl, struct proc *p)
3910{
3911#pragma unused(p)
3912	int error = 0;
3913
3914	switch (cmd) {
3915	case DIOCGETLIMIT: {
3916
3917		if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
3918			error = EINVAL;
3919			goto fail;
3920		}
3921		pl->limit = pf_pool_limits[pl->index].limit;
3922		break;
3923	}
3924
3925	case DIOCSETLIMIT: {
3926		int old_limit;
3927
3928		if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
3929		    pf_pool_limits[pl->index].pp == NULL) {
3930			error = EINVAL;
3931			goto fail;
3932		}
3933		pool_sethardlimit(pf_pool_limits[pl->index].pp,
3934		    pl->limit, NULL, 0);
3935		old_limit = pf_pool_limits[pl->index].limit;
3936		pf_pool_limits[pl->index].limit = pl->limit;
3937		pl->limit = old_limit;
3938		break;
3939	}
3940
3941	default:
3942		VERIFY(0);
3943		/* NOTREACHED */
3944	}
3945fail:
3946	return (error);
3947}
3948
3949static int
3950pfioctl_ioc_pooladdr(u_long cmd, struct pfioc_pooladdr *pp, struct proc *p)
3951{
3952#pragma unused(p)
3953	struct pf_pooladdr *pa = NULL;
3954	struct pf_pool *pool = NULL;
3955	int error = 0;
3956
3957	switch (cmd) {
3958	case DIOCBEGINADDRS: {
3959		pf_empty_pool(&pf_pabuf);
3960		pp->ticket = ++ticket_pabuf;
3961		break;
3962	}
3963
3964	case DIOCADDADDR: {
3965		pp->anchor[sizeof (pp->anchor) - 1] = '\0';
3966		if (pp->ticket != ticket_pabuf) {
3967			error = EBUSY;
3968			break;
3969		}
3970#if !INET
3971		if (pp->af == AF_INET) {
3972			error = EAFNOSUPPORT;
3973			break;
3974		}
3975#endif /* INET */
3976#if !INET6
3977		if (pp->af == AF_INET6) {
3978			error = EAFNOSUPPORT;
3979			break;
3980		}
3981#endif /* INET6 */
3982		if (pp->addr.addr.type != PF_ADDR_ADDRMASK &&
3983		    pp->addr.addr.type != PF_ADDR_DYNIFTL &&
3984		    pp->addr.addr.type != PF_ADDR_TABLE) {
3985			error = EINVAL;
3986			break;
3987		}
3988		pa = pool_get(&pf_pooladdr_pl, PR_WAITOK);
3989		if (pa == NULL) {
3990			error = ENOMEM;
3991			break;
3992		}
3993		pf_pooladdr_copyin(&pp->addr, pa);
3994		if (pa->ifname[0]) {
3995			pa->kif = pfi_kif_get(pa->ifname);
3996			if (pa->kif == NULL) {
3997				pool_put(&pf_pooladdr_pl, pa);
3998				error = EINVAL;
3999				break;
4000			}
4001			pfi_kif_ref(pa->kif, PFI_KIF_REF_RULE);
4002		}
4003		if (pfi_dynaddr_setup(&pa->addr, pp->af)) {
4004			pfi_dynaddr_remove(&pa->addr);
4005			pfi_kif_unref(pa->kif, PFI_KIF_REF_RULE);
4006			pool_put(&pf_pooladdr_pl, pa);
4007			error = EINVAL;
4008			break;
4009		}
4010		TAILQ_INSERT_TAIL(&pf_pabuf, pa, entries);
4011		break;
4012	}
4013
4014	case DIOCGETADDRS: {
4015		pp->nr = 0;
4016		pp->anchor[sizeof (pp->anchor) - 1] = '\0';
4017		pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
4018		    pp->r_num, 0, 1, 0);
4019		if (pool == NULL) {
4020			error = EBUSY;
4021			break;
4022		}
4023		TAILQ_FOREACH(pa, &pool->list, entries)
4024			pp->nr++;
4025		break;
4026	}
4027
4028	case DIOCGETADDR: {
4029		u_int32_t		 nr = 0;
4030
4031		pp->anchor[sizeof (pp->anchor) - 1] = '\0';
4032		pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
4033		    pp->r_num, 0, 1, 1);
4034		if (pool == NULL) {
4035			error = EBUSY;
4036			break;
4037		}
4038		pa = TAILQ_FIRST(&pool->list);
4039		while ((pa != NULL) && (nr < pp->nr)) {
4040			pa = TAILQ_NEXT(pa, entries);
4041			nr++;
4042		}
4043		if (pa == NULL) {
4044			error = EBUSY;
4045			break;
4046		}
4047		pf_pooladdr_copyout(pa, &pp->addr);
4048		pfi_dynaddr_copyout(&pp->addr.addr);
4049		pf_tbladdr_copyout(&pp->addr.addr);
4050		pf_rtlabel_copyout(&pp->addr.addr);
4051		break;
4052	}
4053
4054	case DIOCCHANGEADDR: {
4055		struct pfioc_pooladdr	*pca = pp;
4056		struct pf_pooladdr	*oldpa = NULL, *newpa = NULL;
4057		struct pf_ruleset	*ruleset;
4058
4059		if (pca->action < PF_CHANGE_ADD_HEAD ||
4060		    pca->action > PF_CHANGE_REMOVE) {
4061			error = EINVAL;
4062			break;
4063		}
4064		if (pca->addr.addr.type != PF_ADDR_ADDRMASK &&
4065		    pca->addr.addr.type != PF_ADDR_DYNIFTL &&
4066		    pca->addr.addr.type != PF_ADDR_TABLE) {
4067			error = EINVAL;
4068			break;
4069		}
4070
4071		pca->anchor[sizeof (pca->anchor) - 1] = '\0';
4072		ruleset = pf_find_ruleset(pca->anchor);
4073		if (ruleset == NULL) {
4074			error = EBUSY;
4075			break;
4076		}
4077		pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action,
4078		    pca->r_num, pca->r_last, 1, 1);
4079		if (pool == NULL) {
4080			error = EBUSY;
4081			break;
4082		}
4083		if (pca->action != PF_CHANGE_REMOVE) {
4084			newpa = pool_get(&pf_pooladdr_pl, PR_WAITOK);
4085			if (newpa == NULL) {
4086				error = ENOMEM;
4087				break;
4088			}
4089			pf_pooladdr_copyin(&pca->addr, newpa);
4090#if !INET
4091			if (pca->af == AF_INET) {
4092				pool_put(&pf_pooladdr_pl, newpa);
4093				error = EAFNOSUPPORT;
4094				break;
4095			}
4096#endif /* INET */
4097#if !INET6
4098			if (pca->af == AF_INET6) {
4099				pool_put(&pf_pooladdr_pl, newpa);
4100				error = EAFNOSUPPORT;
4101				break;
4102			}
4103#endif /* INET6 */
4104			if (newpa->ifname[0]) {
4105				newpa->kif = pfi_kif_get(newpa->ifname);
4106				if (newpa->kif == NULL) {
4107					pool_put(&pf_pooladdr_pl, newpa);
4108					error = EINVAL;
4109					break;
4110				}
4111				pfi_kif_ref(newpa->kif, PFI_KIF_REF_RULE);
4112			} else
4113				newpa->kif = NULL;
4114			if (pfi_dynaddr_setup(&newpa->addr, pca->af) ||
4115			    pf_tbladdr_setup(ruleset, &newpa->addr)) {
4116				pfi_dynaddr_remove(&newpa->addr);
4117				pfi_kif_unref(newpa->kif, PFI_KIF_REF_RULE);
4118				pool_put(&pf_pooladdr_pl, newpa);
4119				error = EINVAL;
4120				break;
4121			}
4122		}
4123
4124		if (pca->action == PF_CHANGE_ADD_HEAD)
4125			oldpa = TAILQ_FIRST(&pool->list);
4126		else if (pca->action == PF_CHANGE_ADD_TAIL)
4127			oldpa = TAILQ_LAST(&pool->list, pf_palist);
4128		else {
4129			int	i = 0;
4130
4131			oldpa = TAILQ_FIRST(&pool->list);
4132			while ((oldpa != NULL) && (i < (int)pca->nr)) {
4133				oldpa = TAILQ_NEXT(oldpa, entries);
4134				i++;
4135			}
4136			if (oldpa == NULL) {
4137				error = EINVAL;
4138				break;
4139			}
4140		}
4141
4142		if (pca->action == PF_CHANGE_REMOVE) {
4143			TAILQ_REMOVE(&pool->list, oldpa, entries);
4144			pfi_dynaddr_remove(&oldpa->addr);
4145			pf_tbladdr_remove(&oldpa->addr);
4146			pfi_kif_unref(oldpa->kif, PFI_KIF_REF_RULE);
4147			pool_put(&pf_pooladdr_pl, oldpa);
4148		} else {
4149			if (oldpa == NULL)
4150				TAILQ_INSERT_TAIL(&pool->list, newpa, entries);
4151			else if (pca->action == PF_CHANGE_ADD_HEAD ||
4152			    pca->action == PF_CHANGE_ADD_BEFORE)
4153				TAILQ_INSERT_BEFORE(oldpa, newpa, entries);
4154			else
4155				TAILQ_INSERT_AFTER(&pool->list, oldpa,
4156				    newpa, entries);
4157		}
4158
4159		pool->cur = TAILQ_FIRST(&pool->list);
4160		PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr,
4161		    pca->af);
4162		break;
4163	}
4164
4165	default:
4166		VERIFY(0);
4167		/* NOTREACHED */
4168	}
4169
4170	return (error);
4171}
4172
4173static int
4174pfioctl_ioc_ruleset(u_long cmd, struct pfioc_ruleset *pr, struct proc *p)
4175{
4176#pragma unused(p)
4177	int error = 0;
4178
4179	switch (cmd) {
4180	case DIOCGETRULESETS: {
4181		struct pf_ruleset	*ruleset;
4182		struct pf_anchor	*anchor;
4183
4184		pr->path[sizeof (pr->path) - 1] = '\0';
4185		pr->name[sizeof (pr->name) - 1] = '\0';
4186		if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
4187			error = EINVAL;
4188			break;
4189		}
4190		pr->nr = 0;
4191		if (ruleset->anchor == NULL) {
4192			/* XXX kludge for pf_main_ruleset */
4193			RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
4194				if (anchor->parent == NULL)
4195					pr->nr++;
4196		} else {
4197			RB_FOREACH(anchor, pf_anchor_node,
4198			    &ruleset->anchor->children)
4199				pr->nr++;
4200		}
4201		break;
4202	}
4203
4204	case DIOCGETRULESET: {
4205		struct pf_ruleset	*ruleset;
4206		struct pf_anchor	*anchor;
4207		u_int32_t		 nr = 0;
4208
4209		pr->path[sizeof (pr->path) - 1] = '\0';
4210		if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
4211			error = EINVAL;
4212			break;
4213		}
4214		pr->name[0] = 0;
4215		if (ruleset->anchor == NULL) {
4216			/* XXX kludge for pf_main_ruleset */
4217			RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
4218				if (anchor->parent == NULL && nr++ == pr->nr) {
4219					strlcpy(pr->name, anchor->name,
4220					    sizeof (pr->name));
4221					break;
4222				}
4223		} else {
4224			RB_FOREACH(anchor, pf_anchor_node,
4225			    &ruleset->anchor->children)
4226				if (nr++ == pr->nr) {
4227					strlcpy(pr->name, anchor->name,
4228					    sizeof (pr->name));
4229					break;
4230				}
4231		}
4232		if (!pr->name[0])
4233			error = EBUSY;
4234		break;
4235	}
4236
4237	default:
4238		VERIFY(0);
4239		/* NOTREACHED */
4240	}
4241
4242	return (error);
4243}
4244
4245static int
4246pfioctl_ioc_trans(u_long cmd, struct pfioc_trans_32 *io32,
4247    struct pfioc_trans_64 *io64, struct proc *p)
4248{
4249	int p64 = proc_is64bit(p);
4250	int error = 0, esize, size;
4251	user_addr_t buf;
4252
4253	esize = (p64 ? io64->esize : io32->esize);
4254	size = (p64 ? io64->size : io32->size);
4255	buf = (p64 ? io64->array : io32->array);
4256
4257	switch (cmd) {
4258	case DIOCXBEGIN: {
4259		struct pfioc_trans_e	*ioe;
4260		struct pfr_table	*table;
4261		int			 i;
4262
4263		if (esize != sizeof (*ioe)) {
4264			error = ENODEV;
4265			goto fail;
4266		}
4267		ioe = _MALLOC(sizeof (*ioe), M_TEMP, M_WAITOK);
4268		table = _MALLOC(sizeof (*table), M_TEMP, M_WAITOK);
4269		for (i = 0; i < size; i++, buf += sizeof (*ioe)) {
4270			if (copyin(buf, ioe, sizeof (*ioe))) {
4271				_FREE(table, M_TEMP);
4272				_FREE(ioe, M_TEMP);
4273				error = EFAULT;
4274				goto fail;
4275			}
4276			ioe->anchor[sizeof (ioe->anchor) - 1] = '\0';
4277			switch (ioe->rs_num) {
4278			case PF_RULESET_ALTQ:
4279#if PF_ALTQ
4280				if (altq_allowed) {
4281					if (ioe->anchor[0]) {
4282						_FREE(table, M_TEMP);
4283						_FREE(ioe, M_TEMP);
4284						error = EINVAL;
4285						goto fail;
4286					}
4287					error = pf_begin_altq(&ioe->ticket);
4288					if (error != 0) {
4289						_FREE(table, M_TEMP);
4290						_FREE(ioe, M_TEMP);
4291						goto fail;
4292					}
4293				}
4294#endif /* PF_ALTQ */
4295				break;
4296			case PF_RULESET_TABLE:
4297				bzero(table, sizeof (*table));
4298				strlcpy(table->pfrt_anchor, ioe->anchor,
4299				    sizeof (table->pfrt_anchor));
4300				if ((error = pfr_ina_begin(table,
4301				    &ioe->ticket, NULL, 0))) {
4302					_FREE(table, M_TEMP);
4303					_FREE(ioe, M_TEMP);
4304					goto fail;
4305				}
4306				break;
4307			default:
4308				if ((error = pf_begin_rules(&ioe->ticket,
4309				    ioe->rs_num, ioe->anchor))) {
4310					_FREE(table, M_TEMP);
4311					_FREE(ioe, M_TEMP);
4312					goto fail;
4313				}
4314				break;
4315			}
4316			if (copyout(ioe, buf, sizeof (*ioe))) {
4317				_FREE(table, M_TEMP);
4318				_FREE(ioe, M_TEMP);
4319				error = EFAULT;
4320				goto fail;
4321			}
4322		}
4323		_FREE(table, M_TEMP);
4324		_FREE(ioe, M_TEMP);
4325		break;
4326	}
4327
4328	case DIOCXROLLBACK: {
4329		struct pfioc_trans_e	*ioe;
4330		struct pfr_table	*table;
4331		int			 i;
4332
4333		if (esize != sizeof (*ioe)) {
4334			error = ENODEV;
4335			goto fail;
4336		}
4337		ioe = _MALLOC(sizeof (*ioe), M_TEMP, M_WAITOK);
4338		table = _MALLOC(sizeof (*table), M_TEMP, M_WAITOK);
4339		for (i = 0; i < size; i++, buf += sizeof (*ioe)) {
4340			if (copyin(buf, ioe, sizeof (*ioe))) {
4341				_FREE(table, M_TEMP);
4342				_FREE(ioe, M_TEMP);
4343				error = EFAULT;
4344				goto fail;
4345			}
4346			ioe->anchor[sizeof (ioe->anchor) - 1] = '\0';
4347			switch (ioe->rs_num) {
4348			case PF_RULESET_ALTQ:
4349#if PF_ALTQ
4350				if (altq_allowed) {
4351					if (ioe->anchor[0]) {
4352						_FREE(table, M_TEMP);
4353						_FREE(ioe, M_TEMP);
4354						error = EINVAL;
4355						goto fail;
4356					}
4357					error = pf_rollback_altq(ioe->ticket);
4358					if (error != 0) {
4359						_FREE(table, M_TEMP);
4360						_FREE(ioe, M_TEMP);
4361						goto fail; /* really bad */
4362					}
4363				}
4364#endif /* PF_ALTQ */
4365				break;
4366			case PF_RULESET_TABLE:
4367				bzero(table, sizeof (*table));
4368				strlcpy(table->pfrt_anchor, ioe->anchor,
4369				    sizeof (table->pfrt_anchor));
4370				if ((error = pfr_ina_rollback(table,
4371				    ioe->ticket, NULL, 0))) {
4372					_FREE(table, M_TEMP);
4373					_FREE(ioe, M_TEMP);
4374					goto fail; /* really bad */
4375				}
4376				break;
4377			default:
4378				if ((error = pf_rollback_rules(ioe->ticket,
4379				    ioe->rs_num, ioe->anchor))) {
4380					_FREE(table, M_TEMP);
4381					_FREE(ioe, M_TEMP);
4382					goto fail; /* really bad */
4383				}
4384				break;
4385			}
4386		}
4387		_FREE(table, M_TEMP);
4388		_FREE(ioe, M_TEMP);
4389		break;
4390	}
4391
4392	case DIOCXCOMMIT: {
4393		struct pfioc_trans_e	*ioe;
4394		struct pfr_table	*table;
4395		struct pf_ruleset	*rs;
4396		user_addr_t		 _buf = buf;
4397		int			 i;
4398
4399		if (esize != sizeof (*ioe)) {
4400			error = ENODEV;
4401			goto fail;
4402		}
4403		ioe = _MALLOC(sizeof (*ioe), M_TEMP, M_WAITOK);
4404		table = _MALLOC(sizeof (*table), M_TEMP, M_WAITOK);
4405		/* first makes sure everything will succeed */
4406		for (i = 0; i < size; i++, buf += sizeof (*ioe)) {
4407			if (copyin(buf, ioe, sizeof (*ioe))) {
4408				_FREE(table, M_TEMP);
4409				_FREE(ioe, M_TEMP);
4410				error = EFAULT;
4411				goto fail;
4412			}
4413			ioe->anchor[sizeof (ioe->anchor) - 1] = '\0';
4414			switch (ioe->rs_num) {
4415			case PF_RULESET_ALTQ:
4416#if PF_ALTQ
4417				if (altq_allowed) {
4418					if (ioe->anchor[0]) {
4419						_FREE(table, M_TEMP);
4420						_FREE(ioe, M_TEMP);
4421						error = EINVAL;
4422						goto fail;
4423					}
4424					if (!altqs_inactive_open ||
4425					    ioe->ticket !=
4426					    ticket_altqs_inactive) {
4427						_FREE(table, M_TEMP);
4428						_FREE(ioe, M_TEMP);
4429						error = EBUSY;
4430						goto fail;
4431					}
4432				}
4433#endif /* PF_ALTQ */
4434				break;
4435			case PF_RULESET_TABLE:
4436				rs = pf_find_ruleset(ioe->anchor);
4437				if (rs == NULL || !rs->topen || ioe->ticket !=
4438				    rs->tticket) {
4439					_FREE(table, M_TEMP);
4440					_FREE(ioe, M_TEMP);
4441					error = EBUSY;
4442					goto fail;
4443				}
4444				break;
4445			default:
4446				if (ioe->rs_num < 0 || ioe->rs_num >=
4447				    PF_RULESET_MAX) {
4448					_FREE(table, M_TEMP);
4449					_FREE(ioe, M_TEMP);
4450					error = EINVAL;
4451					goto fail;
4452				}
4453				rs = pf_find_ruleset(ioe->anchor);
4454				if (rs == NULL ||
4455				    !rs->rules[ioe->rs_num].inactive.open ||
4456				    rs->rules[ioe->rs_num].inactive.ticket !=
4457				    ioe->ticket) {
4458					_FREE(table, M_TEMP);
4459					_FREE(ioe, M_TEMP);
4460					error = EBUSY;
4461					goto fail;
4462				}
4463				break;
4464			}
4465		}
4466		buf = _buf;
4467		/* now do the commit - no errors should happen here */
4468		for (i = 0; i < size; i++, buf += sizeof (*ioe)) {
4469			if (copyin(buf, ioe, sizeof (*ioe))) {
4470				_FREE(table, M_TEMP);
4471				_FREE(ioe, M_TEMP);
4472				error = EFAULT;
4473				goto fail;
4474			}
4475			ioe->anchor[sizeof (ioe->anchor) - 1] = '\0';
4476			switch (ioe->rs_num) {
4477			case PF_RULESET_ALTQ:
4478#if PF_ALTQ
4479				if (altq_allowed &&
4480				    (error = pf_commit_altq(ioe->ticket))) {
4481					_FREE(table, M_TEMP);
4482					_FREE(ioe, M_TEMP);
4483					goto fail; /* really bad */
4484				}
4485#endif /* PF_ALTQ */
4486				break;
4487			case PF_RULESET_TABLE:
4488				bzero(table, sizeof (*table));
4489				strlcpy(table->pfrt_anchor, ioe->anchor,
4490				    sizeof (table->pfrt_anchor));
4491				if ((error = pfr_ina_commit(table, ioe->ticket,
4492				    NULL, NULL, 0))) {
4493					_FREE(table, M_TEMP);
4494					_FREE(ioe, M_TEMP);
4495					goto fail; /* really bad */
4496				}
4497				break;
4498			default:
4499				if ((error = pf_commit_rules(ioe->ticket,
4500				    ioe->rs_num, ioe->anchor))) {
4501					_FREE(table, M_TEMP);
4502					_FREE(ioe, M_TEMP);
4503					goto fail; /* really bad */
4504				}
4505				break;
4506			}
4507		}
4508		_FREE(table, M_TEMP);
4509		_FREE(ioe, M_TEMP);
4510		break;
4511	}
4512
4513	default:
4514		VERIFY(0);
4515		/* NOTREACHED */
4516	}
4517fail:
4518	return (error);
4519}
4520
4521static int
4522pfioctl_ioc_src_nodes(u_long cmd, struct pfioc_src_nodes_32 *psn32,
4523    struct pfioc_src_nodes_64 *psn64, struct proc *p)
4524{
4525	int p64 = proc_is64bit(p);
4526	int error = 0;
4527
4528	switch (cmd) {
4529	case DIOCGETSRCNODES: {
4530		struct pf_src_node	*n, *pstore;
4531		user_addr_t		 buf;
4532		u_int32_t		 nr = 0;
4533		int			 space, size;
4534
4535		space = (p64 ? psn64->psn_len : psn32->psn_len);
4536		if (space == 0) {
4537			RB_FOREACH(n, pf_src_tree, &tree_src_tracking)
4538				nr++;
4539
4540			size = sizeof (struct pf_src_node) * nr;
4541			if (p64)
4542				psn64->psn_len = size;
4543			else
4544				psn32->psn_len = size;
4545			break;
4546		}
4547
4548		pstore = _MALLOC(sizeof (*pstore), M_TEMP, M_WAITOK);
4549		if (pstore == NULL) {
4550			error = ENOMEM;
4551			break;
4552		}
4553		buf = (p64 ? psn64->psn_buf : psn32->psn_buf);
4554
4555		RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
4556			uint64_t secs = pf_time_second(), diff;
4557
4558			if ((nr + 1) * sizeof (*pstore) > (unsigned)space)
4559				break;
4560
4561			bcopy(n, pstore, sizeof (*pstore));
4562			if (n->rule.ptr != NULL)
4563				pstore->rule.nr = n->rule.ptr->nr;
4564			pstore->creation = secs - pstore->creation;
4565			if (pstore->expire > secs)
4566				pstore->expire -= secs;
4567			else
4568				pstore->expire = 0;
4569
4570			/* adjust the connection rate estimate */
4571			diff = secs - n->conn_rate.last;
4572			if (diff >= n->conn_rate.seconds)
4573				pstore->conn_rate.count = 0;
4574			else
4575				pstore->conn_rate.count -=
4576				    n->conn_rate.count * diff /
4577				    n->conn_rate.seconds;
4578
4579			_RB_PARENT(pstore, entry) = NULL;
4580			RB_LEFT(pstore, entry) = RB_RIGHT(pstore, entry) = NULL;
4581			pstore->kif = NULL;
4582
4583			error = copyout(pstore, buf, sizeof (*pstore));
4584			if (error) {
4585				_FREE(pstore, M_TEMP);
4586				goto fail;
4587			}
4588			buf += sizeof (*pstore);
4589			nr++;
4590		}
4591
4592		size = sizeof (struct pf_src_node) * nr;
4593		if (p64)
4594			psn64->psn_len = size;
4595		else
4596			psn32->psn_len = size;
4597
4598		_FREE(pstore, M_TEMP);
4599		break;
4600	}
4601
4602	default:
4603		VERIFY(0);
4604		/* NOTREACHED */
4605	}
4606fail:
4607	return (error);
4608
4609}
4610
4611static int
4612pfioctl_ioc_src_node_kill(u_long cmd, struct pfioc_src_node_kill *psnk,
4613    struct proc *p)
4614{
4615#pragma unused(p)
4616	int error = 0;
4617
4618	switch (cmd) {
4619	case DIOCKILLSRCNODES: {
4620		struct pf_src_node	*sn;
4621		struct pf_state		*s;
4622		int			killed = 0;
4623
4624		RB_FOREACH(sn, pf_src_tree, &tree_src_tracking) {
4625			if (PF_MATCHA(psnk->psnk_src.neg,
4626			    &psnk->psnk_src.addr.v.a.addr,
4627			    &psnk->psnk_src.addr.v.a.mask,
4628			    &sn->addr, sn->af) &&
4629			    PF_MATCHA(psnk->psnk_dst.neg,
4630			    &psnk->psnk_dst.addr.v.a.addr,
4631			    &psnk->psnk_dst.addr.v.a.mask,
4632			    &sn->raddr, sn->af)) {
4633				/* Handle state to src_node linkage */
4634				if (sn->states != 0) {
4635					RB_FOREACH(s, pf_state_tree_id,
4636					    &tree_id) {
4637						if (s->src_node == sn)
4638							s->src_node = NULL;
4639						if (s->nat_src_node == sn)
4640							s->nat_src_node = NULL;
4641					}
4642					sn->states = 0;
4643				}
4644				sn->expire = 1;
4645				killed++;
4646			}
4647		}
4648
4649		if (killed > 0)
4650			pf_purge_expired_src_nodes();
4651
4652		psnk->psnk_af = killed;
4653		break;
4654	}
4655
4656	default:
4657		VERIFY(0);
4658		/* NOTREACHED */
4659	}
4660
4661	return (error);
4662}
4663
4664static int
4665pfioctl_ioc_iface(u_long cmd, struct pfioc_iface_32 *io32,
4666    struct pfioc_iface_64 *io64, struct proc *p)
4667{
4668	int p64 = proc_is64bit(p);
4669	int error = 0;
4670
4671	switch (cmd) {
4672	case DIOCIGETIFACES: {
4673		user_addr_t buf;
4674		int esize;
4675
4676		buf = (p64 ? io64->pfiio_buffer : io32->pfiio_buffer);
4677		esize = (p64 ? io64->pfiio_esize : io32->pfiio_esize);
4678
4679		/* esize must be that of the user space version of pfi_kif */
4680		if (esize != sizeof (struct pfi_uif)) {
4681			error = ENODEV;
4682			break;
4683		}
4684		if (p64)
4685			io64->pfiio_name[sizeof (io64->pfiio_name) - 1] = '\0';
4686		else
4687			io32->pfiio_name[sizeof (io32->pfiio_name) - 1] = '\0';
4688		error = pfi_get_ifaces(
4689		    p64 ? io64->pfiio_name : io32->pfiio_name, buf,
4690		    p64 ? &io64->pfiio_size : &io32->pfiio_size);
4691		break;
4692	}
4693
4694	case DIOCSETIFFLAG: {
4695		if (p64)
4696			io64->pfiio_name[sizeof (io64->pfiio_name) - 1] = '\0';
4697		else
4698			io32->pfiio_name[sizeof (io32->pfiio_name) - 1] = '\0';
4699
4700		error = pfi_set_flags(
4701		    p64 ? io64->pfiio_name : io32->pfiio_name,
4702		    p64 ? io64->pfiio_flags : io32->pfiio_flags);
4703		break;
4704	}
4705
4706	case DIOCCLRIFFLAG: {
4707		if (p64)
4708			io64->pfiio_name[sizeof (io64->pfiio_name) - 1] = '\0';
4709		else
4710			io32->pfiio_name[sizeof (io32->pfiio_name) - 1] = '\0';
4711
4712		error = pfi_clear_flags(
4713		    p64 ? io64->pfiio_name : io32->pfiio_name,
4714		    p64 ? io64->pfiio_flags : io32->pfiio_flags);
4715		break;
4716	}
4717
4718	default:
4719		VERIFY(0);
4720		/* NOTREACHED */
4721	}
4722
4723	return (error);
4724}
4725
4726int
4727pf_af_hook(struct ifnet *ifp, struct mbuf **mppn, struct mbuf **mp,
4728    unsigned int af, int input, struct ip_fw_args *fwa)
4729{
4730	int error = 0, reentry;
4731	struct mbuf *nextpkt;
4732
4733	reentry = net_thread_check_lock(NET_THREAD_HELD_PF);
4734	if (!reentry) {
4735		lck_rw_lock_shared(pf_perim_lock);
4736		if (!pf_is_enabled)
4737			goto done;
4738
4739		lck_mtx_lock(pf_lock);
4740		net_thread_set_lock(NET_THREAD_HELD_PF);
4741	}
4742
4743	if (mppn != NULL && *mppn != NULL)
4744		VERIFY(*mppn == *mp);
4745	if ((nextpkt = (*mp)->m_nextpkt) != NULL)
4746		(*mp)->m_nextpkt = NULL;
4747
4748	switch (af) {
4749#if INET
4750	case AF_INET: {
4751		error = pf_inet_hook(ifp, mp, input, fwa);
4752		break;
4753	}
4754#endif /* INET */
4755#if INET6
4756	case AF_INET6:
4757		error = pf_inet6_hook(ifp, mp, input, fwa);
4758		break;
4759#endif /* INET6 */
4760	default:
4761		break;
4762	}
4763
4764	/* When packet valid, link to the next packet */
4765	if (*mp != NULL && nextpkt != NULL) {
4766		struct mbuf *m = *mp;
4767		while (m->m_nextpkt != NULL)
4768			m = m->m_nextpkt;
4769		m->m_nextpkt = nextpkt;
4770	}
4771	/* Fix up linkage of previous packet in the chain */
4772	if (mppn != NULL) {
4773		if (*mp != NULL)
4774			*mppn = *mp;
4775		else
4776			*mppn = nextpkt;
4777	}
4778	if (!reentry) {
4779		net_thread_unset_lock(NET_THREAD_HELD_PF);
4780		lck_mtx_unlock(pf_lock);
4781	}
4782done:
4783	if (!reentry)
4784		lck_rw_done(pf_perim_lock);
4785
4786	return (error);
4787}
4788
4789
4790#if INET
4791static int
4792pf_inet_hook(struct ifnet *ifp, struct mbuf **mp, int input,
4793    struct ip_fw_args *fwa)
4794{
4795	struct mbuf *m = *mp;
4796#if BYTE_ORDER != BIG_ENDIAN
4797	struct ip *ip = mtod(m, struct ip *);
4798#endif
4799	int error = 0;
4800
4801	/*
4802	 * If the packet is outbound, is originated locally, is flagged for
4803	 * delayed UDP/TCP checksum calculation, and is about to be processed
4804	 * for an interface that doesn't support the appropriate checksum
4805	 * offloading, then calculated the checksum here so that PF can adjust
4806	 * it properly.
4807	 */
4808	if (!input && m->m_pkthdr.rcvif == NULL) {
4809		static const int mask = CSUM_DELAY_DATA;
4810		const int flags = m->m_pkthdr.csum_flags &
4811		    ~IF_HWASSIST_CSUM_FLAGS(ifp->if_hwassist);
4812
4813		if (flags & mask) {
4814			in_delayed_cksum(m);
4815			m->m_pkthdr.csum_flags &= ~mask;
4816		}
4817	}
4818
4819#if BYTE_ORDER != BIG_ENDIAN
4820	HTONS(ip->ip_len);
4821	HTONS(ip->ip_off);
4822#endif
4823	if (pf_test(input ? PF_IN : PF_OUT, ifp, mp, NULL, fwa) != PF_PASS) {
4824		if (*mp != NULL) {
4825			m_freem(*mp);
4826			*mp = NULL;
4827			error = EHOSTUNREACH;
4828		} else {
4829			error = ENOBUFS;
4830		}
4831	}
4832#if BYTE_ORDER != BIG_ENDIAN
4833	else {
4834		if (*mp != NULL) {
4835			ip = mtod(*mp, struct ip *);
4836			NTOHS(ip->ip_len);
4837			NTOHS(ip->ip_off);
4838		}
4839	}
4840#endif
4841	return (error);
4842}
4843#endif /* INET */
4844
4845#if INET6
4846int
4847pf_inet6_hook(struct ifnet *ifp, struct mbuf **mp, int input,
4848    struct ip_fw_args *fwa)
4849{
4850	int error = 0;
4851
4852	/*
4853	 * If the packet is outbound, is originated locally, is flagged for
4854	 * delayed UDP/TCP checksum calculation, and is about to be processed
4855	 * for an interface that doesn't support the appropriate checksum
4856	 * offloading, then calculated the checksum here so that PF can adjust
4857	 * it properly.
4858	 */
4859	if (!input && (*mp)->m_pkthdr.rcvif == NULL) {
4860		static const int mask = CSUM_DELAY_IPV6_DATA;
4861		const int flags = (*mp)->m_pkthdr.csum_flags &
4862		    ~IF_HWASSIST_CSUM_FLAGS(ifp->if_hwassist);
4863
4864		if (flags & mask) {
4865			in6_delayed_cksum(*mp, sizeof(struct ip6_hdr));
4866			(*mp)->m_pkthdr.csum_flags &= ~mask;
4867		}
4868	}
4869
4870	if (pf_test6(input ? PF_IN : PF_OUT, ifp, mp, NULL, fwa) != PF_PASS) {
4871		if (*mp != NULL) {
4872			m_freem(*mp);
4873			*mp = NULL;
4874			error = EHOSTUNREACH;
4875		} else {
4876			error = ENOBUFS;
4877		}
4878	}
4879	return (error);
4880}
4881#endif /* INET6 */
4882
4883int
4884pf_ifaddr_hook(struct ifnet *ifp, unsigned long cmd)
4885{
4886	lck_rw_lock_shared(pf_perim_lock);
4887	lck_mtx_lock(pf_lock);
4888
4889	switch (cmd) {
4890	case SIOCSIFADDR:
4891	case SIOCAIFADDR:
4892	case SIOCDIFADDR:
4893#if INET6
4894	case SIOCAIFADDR_IN6_32:
4895	case SIOCAIFADDR_IN6_64:
4896	case SIOCDIFADDR_IN6:
4897#endif /* INET6 */
4898		if (ifp->if_pf_kif != NULL)
4899			pfi_kifaddr_update(ifp->if_pf_kif);
4900		break;
4901	default:
4902		panic("%s: unexpected ioctl %lu", __func__, cmd);
4903		/* NOTREACHED */
4904	}
4905
4906	lck_mtx_unlock(pf_lock);
4907	lck_rw_done(pf_perim_lock);
4908	return (0);
4909}
4910
4911/*
4912 * Caller acquires dlil lock as writer (exclusive)
4913 */
4914void
4915pf_ifnet_hook(struct ifnet *ifp, int attach)
4916{
4917	lck_rw_lock_shared(pf_perim_lock);
4918	lck_mtx_lock(pf_lock);
4919	if (attach)
4920		pfi_attach_ifnet(ifp);
4921	else
4922		pfi_detach_ifnet(ifp);
4923	lck_mtx_unlock(pf_lock);
4924	lck_rw_done(pf_perim_lock);
4925}
4926
4927static void
4928pf_attach_hooks(void)
4929{
4930	ifnet_head_lock_shared();
4931	/*
4932	 * Check against ifnet_addrs[] before proceeding, in case this
4933	 * is called very early on, e.g. during dlil_init() before any
4934	 * network interface is attached.
4935	 */
4936	if (ifnet_addrs != NULL) {
4937		int i;
4938
4939		for (i = 0; i <= if_index; i++) {
4940			struct ifnet *ifp = ifindex2ifnet[i];
4941			if (ifp != NULL) {
4942				pfi_attach_ifnet(ifp);
4943			}
4944		}
4945	}
4946	ifnet_head_done();
4947}
4948
4949#if 0
4950/* currently unused along with pfdetach() */
4951static void
4952pf_detach_hooks(void)
4953{
4954	ifnet_head_lock_shared();
4955	if (ifnet_addrs != NULL) {
4956		for (i = 0; i <= if_index; i++) {
4957			int i;
4958
4959			struct ifnet *ifp = ifindex2ifnet[i];
4960			if (ifp != NULL && ifp->if_pf_kif != NULL) {
4961				pfi_detach_ifnet(ifp);
4962			}
4963		}
4964	}
4965	ifnet_head_done();
4966}
4967#endif
4968