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