xref: /openbsd-src/sys/net/pf_ioctl.c (revision 850e275390052b330d93020bf619a739a3c277ac)
1 /*	$OpenBSD: pf_ioctl.c,v 1.209 2008/06/29 08:42:15 mcbride 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 #include "pfsync.h"
39 #include "pflog.h"
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/mbuf.h>
44 #include <sys/filio.h>
45 #include <sys/fcntl.h>
46 #include <sys/socket.h>
47 #include <sys/socketvar.h>
48 #include <sys/kernel.h>
49 #include <sys/time.h>
50 #include <sys/timeout.h>
51 #include <sys/pool.h>
52 #include <sys/proc.h>
53 #include <sys/malloc.h>
54 #include <sys/kthread.h>
55 #include <sys/rwlock.h>
56 #include <uvm/uvm_extern.h>
57 
58 #include <net/if.h>
59 #include <net/if_types.h>
60 #include <net/route.h>
61 
62 #include <netinet/in.h>
63 #include <netinet/in_var.h>
64 #include <netinet/in_systm.h>
65 #include <netinet/ip.h>
66 #include <netinet/ip_var.h>
67 #include <netinet/ip_icmp.h>
68 
69 #include <dev/rndvar.h>
70 #include <crypto/md5.h>
71 #include <net/pfvar.h>
72 
73 #if NPFSYNC > 0
74 #include <net/if_pfsync.h>
75 #endif /* NPFSYNC > 0 */
76 
77 #if NPFLOG > 0
78 #include <net/if_pflog.h>
79 #endif /* NPFLOG > 0 */
80 
81 #ifdef INET6
82 #include <netinet/ip6.h>
83 #include <netinet/in_pcb.h>
84 #endif /* INET6 */
85 
86 #ifdef ALTQ
87 #include <altq/altq.h>
88 #endif
89 
90 void			 pfattach(int);
91 void			 pf_thread_create(void *);
92 int			 pfopen(dev_t, int, int, struct proc *);
93 int			 pfclose(dev_t, int, int, struct proc *);
94 struct pf_pool		*pf_get_pool(char *, u_int32_t, u_int8_t, u_int32_t,
95 			    u_int8_t, u_int8_t, u_int8_t);
96 
97 void			 pf_mv_pool(struct pf_palist *, struct pf_palist *);
98 void			 pf_empty_pool(struct pf_palist *);
99 int			 pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
100 #ifdef ALTQ
101 int			 pf_begin_altq(u_int32_t *);
102 int			 pf_rollback_altq(u_int32_t);
103 int			 pf_commit_altq(u_int32_t);
104 int			 pf_enable_altq(struct pf_altq *);
105 int			 pf_disable_altq(struct pf_altq *);
106 #endif /* ALTQ */
107 int			 pf_begin_rules(u_int32_t *, int, const char *);
108 int			 pf_rollback_rules(u_int32_t, int, char *);
109 int			 pf_setup_pfsync_matching(struct pf_ruleset *);
110 void			 pf_hash_rule(MD5_CTX *, struct pf_rule *);
111 void			 pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
112 int			 pf_commit_rules(u_int32_t, int, char *);
113 int			 pf_addr_setup(struct pf_ruleset *,
114 			    struct pf_addr_wrap *, sa_family_t);
115 void			 pf_addr_copyout(struct pf_addr_wrap *);
116 
117 struct pf_rule		 pf_default_rule;
118 struct rwlock		 pf_consistency_lock = RWLOCK_INITIALIZER("pfcnslk");
119 #ifdef ALTQ
120 static int		 pf_altq_running;
121 #endif
122 
123 #define	TAGID_MAX	 50000
124 TAILQ_HEAD(pf_tags, pf_tagname)	pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags),
125 				pf_qids = TAILQ_HEAD_INITIALIZER(pf_qids);
126 
127 #if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
128 #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
129 #endif
130 u_int16_t		 tagname2tag(struct pf_tags *, char *);
131 void			 tag2tagname(struct pf_tags *, u_int16_t, char *);
132 void			 tag_unref(struct pf_tags *, u_int16_t);
133 int			 pf_rtlabel_add(struct pf_addr_wrap *);
134 void			 pf_rtlabel_remove(struct pf_addr_wrap *);
135 void			 pf_rtlabel_copyout(struct pf_addr_wrap *);
136 
137 #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
138 
139 void
140 pfattach(int num)
141 {
142 	u_int32_t *timeout = pf_default_rule.timeout;
143 
144 	pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
145 	    &pool_allocator_nointr);
146 	pool_init(&pf_src_tree_pl, sizeof(struct pf_src_node), 0, 0, 0,
147 	    "pfsrctrpl", NULL);
148 	pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
149 	    NULL);
150 	pool_init(&pf_state_key_pl, sizeof(struct pf_state_key), 0, 0, 0,
151 	    "pfstatekeypl", NULL);
152 	pool_init(&pf_state_item_pl, sizeof(struct pf_state_item), 0, 0, 0,
153 	    "pfstateitempl", NULL);
154 	pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl",
155 	    &pool_allocator_nointr);
156 	pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0,
157 	    "pfpooladdrpl", &pool_allocator_nointr);
158 	pfr_initialize();
159 	pfi_initialize();
160 	pf_osfp_initialize();
161 
162 	pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp,
163 	    pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0);
164 
165 	if (physmem <= atop(100*1024*1024))
166 		pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit =
167 		    PFR_KENTRY_HIWAT_SMALL;
168 
169 	RB_INIT(&tree_src_tracking);
170 	RB_INIT(&pf_anchors);
171 	pf_init_ruleset(&pf_main_ruleset);
172 	TAILQ_INIT(&pf_altqs[0]);
173 	TAILQ_INIT(&pf_altqs[1]);
174 	TAILQ_INIT(&pf_pabuf);
175 	pf_altqs_active = &pf_altqs[0];
176 	pf_altqs_inactive = &pf_altqs[1];
177 	TAILQ_INIT(&state_list);
178 
179 	/* default rule should never be garbage collected */
180 	pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
181 	pf_default_rule.action = PF_PASS;
182 	pf_default_rule.nr = -1;
183 	pf_default_rule.rtableid = -1;
184 
185 	/* initialize default timeouts */
186 	timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
187 	timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
188 	timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
189 	timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
190 	timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
191 	timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
192 	timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
193 	timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
194 	timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
195 	timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
196 	timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
197 	timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
198 	timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
199 	timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
200 	timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
201 	timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
202 	timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
203 	timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
204 	timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
205 	timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
206 
207 	pf_normalize_init();
208 	bzero(&pf_status, sizeof(pf_status));
209 	pf_status.debug = PF_DEBUG_URGENT;
210 
211 	/* XXX do our best to avoid a conflict */
212 	pf_status.hostid = arc4random();
213 
214 	/* require process context to purge states, so perform in a thread */
215 	kthread_create_deferred(pf_thread_create, NULL);
216 }
217 
218 void
219 pf_thread_create(void *v)
220 {
221 	if (kthread_create(pf_purge_thread, NULL, NULL, "pfpurge"))
222 		panic("pfpurge thread");
223 }
224 
225 int
226 pfopen(dev_t dev, int flags, int fmt, struct proc *p)
227 {
228 	if (minor(dev) >= 1)
229 		return (ENXIO);
230 	return (0);
231 }
232 
233 int
234 pfclose(dev_t dev, int flags, int fmt, struct proc *p)
235 {
236 	if (minor(dev) >= 1)
237 		return (ENXIO);
238 	return (0);
239 }
240 
241 struct pf_pool *
242 pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
243     u_int32_t rule_number, u_int8_t r_last, u_int8_t active,
244     u_int8_t check_ticket)
245 {
246 	struct pf_ruleset	*ruleset;
247 	struct pf_rule		*rule;
248 	int			 rs_num;
249 
250 	ruleset = pf_find_ruleset(anchor);
251 	if (ruleset == NULL)
252 		return (NULL);
253 	rs_num = pf_get_ruleset_number(rule_action);
254 	if (rs_num >= PF_RULESET_MAX)
255 		return (NULL);
256 	if (active) {
257 		if (check_ticket && ticket !=
258 		    ruleset->rules[rs_num].active.ticket)
259 			return (NULL);
260 		if (r_last)
261 			rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
262 			    pf_rulequeue);
263 		else
264 			rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
265 	} else {
266 		if (check_ticket && ticket !=
267 		    ruleset->rules[rs_num].inactive.ticket)
268 			return (NULL);
269 		if (r_last)
270 			rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
271 			    pf_rulequeue);
272 		else
273 			rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr);
274 	}
275 	if (!r_last) {
276 		while ((rule != NULL) && (rule->nr != rule_number))
277 			rule = TAILQ_NEXT(rule, entries);
278 	}
279 	if (rule == NULL)
280 		return (NULL);
281 
282 	return (&rule->rpool);
283 }
284 
285 void
286 pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb)
287 {
288 	struct pf_pooladdr	*mv_pool_pa;
289 
290 	while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) {
291 		TAILQ_REMOVE(poola, mv_pool_pa, entries);
292 		TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries);
293 	}
294 }
295 
296 void
297 pf_empty_pool(struct pf_palist *poola)
298 {
299 	struct pf_pooladdr	*empty_pool_pa;
300 
301 	while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) {
302 		pfi_dynaddr_remove(&empty_pool_pa->addr);
303 		pf_tbladdr_remove(&empty_pool_pa->addr);
304 		pfi_kif_unref(empty_pool_pa->kif, PFI_KIF_REF_RULE);
305 		TAILQ_REMOVE(poola, empty_pool_pa, entries);
306 		pool_put(&pf_pooladdr_pl, empty_pool_pa);
307 	}
308 }
309 
310 void
311 pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
312 {
313 	if (rulequeue != NULL) {
314 		if (rule->states_cur <= 0) {
315 			/*
316 			 * XXX - we need to remove the table *before* detaching
317 			 * the rule to make sure the table code does not delete
318 			 * the anchor under our feet.
319 			 */
320 			pf_tbladdr_remove(&rule->src.addr);
321 			pf_tbladdr_remove(&rule->dst.addr);
322 			if (rule->overload_tbl)
323 				pfr_detach_table(rule->overload_tbl);
324 		}
325 		TAILQ_REMOVE(rulequeue, rule, entries);
326 		rule->entries.tqe_prev = NULL;
327 		rule->nr = -1;
328 	}
329 
330 	if (rule->states_cur > 0 || rule->src_nodes > 0 ||
331 	    rule->entries.tqe_prev != NULL)
332 		return;
333 	pf_tag_unref(rule->tag);
334 	pf_tag_unref(rule->match_tag);
335 #ifdef ALTQ
336 	if (rule->pqid != rule->qid)
337 		pf_qid_unref(rule->pqid);
338 	pf_qid_unref(rule->qid);
339 #endif
340 	pf_rtlabel_remove(&rule->src.addr);
341 	pf_rtlabel_remove(&rule->dst.addr);
342 	pfi_dynaddr_remove(&rule->src.addr);
343 	pfi_dynaddr_remove(&rule->dst.addr);
344 	if (rulequeue == NULL) {
345 		pf_tbladdr_remove(&rule->src.addr);
346 		pf_tbladdr_remove(&rule->dst.addr);
347 		if (rule->overload_tbl)
348 			pfr_detach_table(rule->overload_tbl);
349 	}
350 	pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE);
351 	pf_anchor_remove(rule);
352 	pf_empty_pool(&rule->rpool.list);
353 	pool_put(&pf_rule_pl, rule);
354 }
355 
356 u_int16_t
357 tagname2tag(struct pf_tags *head, char *tagname)
358 {
359 	struct pf_tagname	*tag, *p = NULL;
360 	u_int16_t		 new_tagid = 1;
361 
362 	TAILQ_FOREACH(tag, head, entries)
363 		if (strcmp(tagname, tag->name) == 0) {
364 			tag->ref++;
365 			return (tag->tag);
366 		}
367 
368 	/*
369 	 * to avoid fragmentation, we do a linear search from the beginning
370 	 * and take the first free slot we find. if there is none or the list
371 	 * is empty, append a new entry at the end.
372 	 */
373 
374 	/* new entry */
375 	if (!TAILQ_EMPTY(head))
376 		for (p = TAILQ_FIRST(head); p != NULL &&
377 		    p->tag == new_tagid; p = TAILQ_NEXT(p, entries))
378 			new_tagid = p->tag + 1;
379 
380 	if (new_tagid > TAGID_MAX)
381 		return (0);
382 
383 	/* allocate and fill new struct pf_tagname */
384 	tag = malloc(sizeof(*tag), M_TEMP, M_NOWAIT|M_ZERO);
385 	if (tag == NULL)
386 		return (0);
387 	strlcpy(tag->name, tagname, sizeof(tag->name));
388 	tag->tag = new_tagid;
389 	tag->ref++;
390 
391 	if (p != NULL)	/* insert new entry before p */
392 		TAILQ_INSERT_BEFORE(p, tag, entries);
393 	else	/* either list empty or no free slot in between */
394 		TAILQ_INSERT_TAIL(head, tag, entries);
395 
396 	return (tag->tag);
397 }
398 
399 void
400 tag2tagname(struct pf_tags *head, u_int16_t tagid, char *p)
401 {
402 	struct pf_tagname	*tag;
403 
404 	TAILQ_FOREACH(tag, head, entries)
405 		if (tag->tag == tagid) {
406 			strlcpy(p, tag->name, PF_TAG_NAME_SIZE);
407 			return;
408 		}
409 }
410 
411 void
412 tag_unref(struct pf_tags *head, u_int16_t tag)
413 {
414 	struct pf_tagname	*p, *next;
415 
416 	if (tag == 0)
417 		return;
418 
419 	for (p = TAILQ_FIRST(head); p != NULL; p = next) {
420 		next = TAILQ_NEXT(p, entries);
421 		if (tag == p->tag) {
422 			if (--p->ref == 0) {
423 				TAILQ_REMOVE(head, p, entries);
424 				free(p, M_TEMP);
425 			}
426 			break;
427 		}
428 	}
429 }
430 
431 u_int16_t
432 pf_tagname2tag(char *tagname)
433 {
434 	return (tagname2tag(&pf_tags, tagname));
435 }
436 
437 void
438 pf_tag2tagname(u_int16_t tagid, char *p)
439 {
440 	tag2tagname(&pf_tags, tagid, p);
441 }
442 
443 void
444 pf_tag_ref(u_int16_t tag)
445 {
446 	struct pf_tagname *t;
447 
448 	TAILQ_FOREACH(t, &pf_tags, entries)
449 		if (t->tag == tag)
450 			break;
451 	if (t != NULL)
452 		t->ref++;
453 }
454 
455 void
456 pf_tag_unref(u_int16_t tag)
457 {
458 	tag_unref(&pf_tags, tag);
459 }
460 
461 int
462 pf_rtlabel_add(struct pf_addr_wrap *a)
463 {
464 	if (a->type == PF_ADDR_RTLABEL &&
465 	    (a->v.rtlabel = rtlabel_name2id(a->v.rtlabelname)) == 0)
466 		return (-1);
467 	return (0);
468 }
469 
470 void
471 pf_rtlabel_remove(struct pf_addr_wrap *a)
472 {
473 	if (a->type == PF_ADDR_RTLABEL)
474 		rtlabel_unref(a->v.rtlabel);
475 }
476 
477 void
478 pf_rtlabel_copyout(struct pf_addr_wrap *a)
479 {
480 	const char	*name;
481 
482 	if (a->type == PF_ADDR_RTLABEL && a->v.rtlabel) {
483 		if ((name = rtlabel_id2name(a->v.rtlabel)) == NULL)
484 			strlcpy(a->v.rtlabelname, "?",
485 			    sizeof(a->v.rtlabelname));
486 		else
487 			strlcpy(a->v.rtlabelname, name,
488 			    sizeof(a->v.rtlabelname));
489 	}
490 }
491 
492 #ifdef ALTQ
493 u_int32_t
494 pf_qname2qid(char *qname)
495 {
496 	return ((u_int32_t)tagname2tag(&pf_qids, qname));
497 }
498 
499 void
500 pf_qid2qname(u_int32_t qid, char *p)
501 {
502 	tag2tagname(&pf_qids, (u_int16_t)qid, p);
503 }
504 
505 void
506 pf_qid_unref(u_int32_t qid)
507 {
508 	tag_unref(&pf_qids, (u_int16_t)qid);
509 }
510 
511 int
512 pf_begin_altq(u_int32_t *ticket)
513 {
514 	struct pf_altq	*altq;
515 	int		 error = 0;
516 
517 	/* Purge the old altq list */
518 	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
519 		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
520 		if (altq->qname[0] == 0) {
521 			/* detach and destroy the discipline */
522 			error = altq_remove(altq);
523 		} else
524 			pf_qid_unref(altq->qid);
525 		pool_put(&pf_altq_pl, altq);
526 	}
527 	if (error)
528 		return (error);
529 	*ticket = ++ticket_altqs_inactive;
530 	altqs_inactive_open = 1;
531 	return (0);
532 }
533 
534 int
535 pf_rollback_altq(u_int32_t ticket)
536 {
537 	struct pf_altq	*altq;
538 	int		 error = 0;
539 
540 	if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
541 		return (0);
542 	/* Purge the old altq list */
543 	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
544 		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
545 		if (altq->qname[0] == 0) {
546 			/* detach and destroy the discipline */
547 			error = altq_remove(altq);
548 		} else
549 			pf_qid_unref(altq->qid);
550 		pool_put(&pf_altq_pl, altq);
551 	}
552 	altqs_inactive_open = 0;
553 	return (error);
554 }
555 
556 int
557 pf_commit_altq(u_int32_t ticket)
558 {
559 	struct pf_altqqueue	*old_altqs;
560 	struct pf_altq		*altq;
561 	int			 s, err, error = 0;
562 
563 	if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
564 		return (EBUSY);
565 
566 	/* swap altqs, keep the old. */
567 	s = splsoftnet();
568 	old_altqs = pf_altqs_active;
569 	pf_altqs_active = pf_altqs_inactive;
570 	pf_altqs_inactive = old_altqs;
571 	ticket_altqs_active = ticket_altqs_inactive;
572 
573 	/* Attach new disciplines */
574 	TAILQ_FOREACH(altq, pf_altqs_active, entries) {
575 		if (altq->qname[0] == 0) {
576 			/* attach the discipline */
577 			error = altq_pfattach(altq);
578 			if (error == 0 && pf_altq_running)
579 				error = pf_enable_altq(altq);
580 			if (error != 0) {
581 				splx(s);
582 				return (error);
583 			}
584 		}
585 	}
586 
587 	/* Purge the old altq list */
588 	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
589 		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
590 		if (altq->qname[0] == 0) {
591 			/* detach and destroy the discipline */
592 			if (pf_altq_running)
593 				error = pf_disable_altq(altq);
594 			err = altq_pfdetach(altq);
595 			if (err != 0 && error == 0)
596 				error = err;
597 			err = altq_remove(altq);
598 			if (err != 0 && error == 0)
599 				error = err;
600 		} else
601 			pf_qid_unref(altq->qid);
602 		pool_put(&pf_altq_pl, altq);
603 	}
604 	splx(s);
605 
606 	altqs_inactive_open = 0;
607 	return (error);
608 }
609 
610 int
611 pf_enable_altq(struct pf_altq *altq)
612 {
613 	struct ifnet		*ifp;
614 	struct tb_profile	 tb;
615 	int			 s, error = 0;
616 
617 	if ((ifp = ifunit(altq->ifname)) == NULL)
618 		return (EINVAL);
619 
620 	if (ifp->if_snd.altq_type != ALTQT_NONE)
621 		error = altq_enable(&ifp->if_snd);
622 
623 	/* set tokenbucket regulator */
624 	if (error == 0 && ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
625 		tb.rate = altq->ifbandwidth;
626 		tb.depth = altq->tbrsize;
627 		s = splnet();
628 		error = tbr_set(&ifp->if_snd, &tb);
629 		splx(s);
630 	}
631 
632 	return (error);
633 }
634 
635 int
636 pf_disable_altq(struct pf_altq *altq)
637 {
638 	struct ifnet		*ifp;
639 	struct tb_profile	 tb;
640 	int			 s, error;
641 
642 	if ((ifp = ifunit(altq->ifname)) == NULL)
643 		return (EINVAL);
644 
645 	/*
646 	 * when the discipline is no longer referenced, it was overridden
647 	 * by a new one.  if so, just return.
648 	 */
649 	if (altq->altq_disc != ifp->if_snd.altq_disc)
650 		return (0);
651 
652 	error = altq_disable(&ifp->if_snd);
653 
654 	if (error == 0) {
655 		/* clear tokenbucket regulator */
656 		tb.rate = 0;
657 		s = splnet();
658 		error = tbr_set(&ifp->if_snd, &tb);
659 		splx(s);
660 	}
661 
662 	return (error);
663 }
664 #endif /* ALTQ */
665 
666 int
667 pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
668 {
669 	struct pf_ruleset	*rs;
670 	struct pf_rule		*rule;
671 
672 	if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
673 		return (EINVAL);
674 	rs = pf_find_or_create_ruleset(anchor);
675 	if (rs == NULL)
676 		return (EINVAL);
677 	while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
678 		pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
679 		rs->rules[rs_num].inactive.rcount--;
680 	}
681 	*ticket = ++rs->rules[rs_num].inactive.ticket;
682 	rs->rules[rs_num].inactive.open = 1;
683 	return (0);
684 }
685 
686 int
687 pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor)
688 {
689 	struct pf_ruleset	*rs;
690 	struct pf_rule		*rule;
691 
692 	if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
693 		return (EINVAL);
694 	rs = pf_find_ruleset(anchor);
695 	if (rs == NULL || !rs->rules[rs_num].inactive.open ||
696 	    rs->rules[rs_num].inactive.ticket != ticket)
697 		return (0);
698 	while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
699 		pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
700 		rs->rules[rs_num].inactive.rcount--;
701 	}
702 	rs->rules[rs_num].inactive.open = 0;
703 	return (0);
704 }
705 
706 #define PF_MD5_UPD(st, elm)						\
707 		MD5Update(ctx, (u_int8_t *) &(st)->elm, sizeof((st)->elm))
708 
709 #define PF_MD5_UPD_STR(st, elm)						\
710 		MD5Update(ctx, (u_int8_t *) (st)->elm, strlen((st)->elm))
711 
712 #define PF_MD5_UPD_HTONL(st, elm, stor) do {				\
713 		(stor) = htonl((st)->elm);				\
714 		MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int32_t));\
715 } while (0)
716 
717 #define PF_MD5_UPD_HTONS(st, elm, stor) do {				\
718 		(stor) = htons((st)->elm);				\
719 		MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int16_t));\
720 } while (0)
721 
722 void
723 pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr)
724 {
725 	PF_MD5_UPD(pfr, addr.type);
726 	switch (pfr->addr.type) {
727 		case PF_ADDR_DYNIFTL:
728 			PF_MD5_UPD(pfr, addr.v.ifname);
729 			PF_MD5_UPD(pfr, addr.iflags);
730 			break;
731 		case PF_ADDR_TABLE:
732 			PF_MD5_UPD(pfr, addr.v.tblname);
733 			break;
734 		case PF_ADDR_ADDRMASK:
735 			/* XXX ignore af? */
736 			PF_MD5_UPD(pfr, addr.v.a.addr.addr32);
737 			PF_MD5_UPD(pfr, addr.v.a.mask.addr32);
738 			break;
739 		case PF_ADDR_RTLABEL:
740 			PF_MD5_UPD(pfr, addr.v.rtlabelname);
741 			break;
742 	}
743 
744 	PF_MD5_UPD(pfr, port[0]);
745 	PF_MD5_UPD(pfr, port[1]);
746 	PF_MD5_UPD(pfr, neg);
747 	PF_MD5_UPD(pfr, port_op);
748 }
749 
750 void
751 pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule)
752 {
753 	u_int16_t x;
754 	u_int32_t y;
755 
756 	pf_hash_rule_addr(ctx, &rule->src);
757 	pf_hash_rule_addr(ctx, &rule->dst);
758 	PF_MD5_UPD_STR(rule, label);
759 	PF_MD5_UPD_STR(rule, ifname);
760 	PF_MD5_UPD_STR(rule, match_tagname);
761 	PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */
762 	PF_MD5_UPD_HTONL(rule, os_fingerprint, y);
763 	PF_MD5_UPD_HTONL(rule, prob, y);
764 	PF_MD5_UPD_HTONL(rule, uid.uid[0], y);
765 	PF_MD5_UPD_HTONL(rule, uid.uid[1], y);
766 	PF_MD5_UPD(rule, uid.op);
767 	PF_MD5_UPD_HTONL(rule, gid.gid[0], y);
768 	PF_MD5_UPD_HTONL(rule, gid.gid[1], y);
769 	PF_MD5_UPD(rule, gid.op);
770 	PF_MD5_UPD_HTONL(rule, rule_flag, y);
771 	PF_MD5_UPD(rule, action);
772 	PF_MD5_UPD(rule, direction);
773 	PF_MD5_UPD(rule, af);
774 	PF_MD5_UPD(rule, quick);
775 	PF_MD5_UPD(rule, ifnot);
776 	PF_MD5_UPD(rule, match_tag_not);
777 	PF_MD5_UPD(rule, natpass);
778 	PF_MD5_UPD(rule, keep_state);
779 	PF_MD5_UPD(rule, proto);
780 	PF_MD5_UPD(rule, type);
781 	PF_MD5_UPD(rule, code);
782 	PF_MD5_UPD(rule, flags);
783 	PF_MD5_UPD(rule, flagset);
784 	PF_MD5_UPD(rule, allow_opts);
785 	PF_MD5_UPD(rule, rt);
786 	PF_MD5_UPD(rule, tos);
787 }
788 
789 int
790 pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
791 {
792 	struct pf_ruleset	*rs;
793 	struct pf_rule		*rule, **old_array;
794 	struct pf_rulequeue	*old_rules;
795 	int			 s, error;
796 	u_int32_t		 old_rcount;
797 
798 	if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
799 		return (EINVAL);
800 	rs = pf_find_ruleset(anchor);
801 	if (rs == NULL || !rs->rules[rs_num].inactive.open ||
802 	    ticket != rs->rules[rs_num].inactive.ticket)
803 		return (EBUSY);
804 
805 	/* Calculate checksum for the main ruleset */
806 	if (rs == &pf_main_ruleset) {
807 		error = pf_setup_pfsync_matching(rs);
808 		if (error != 0)
809 			return (error);
810 	}
811 
812 	/* Swap rules, keep the old. */
813 	s = splsoftnet();
814 	old_rules = rs->rules[rs_num].active.ptr;
815 	old_rcount = rs->rules[rs_num].active.rcount;
816 	old_array = rs->rules[rs_num].active.ptr_array;
817 
818 	rs->rules[rs_num].active.ptr =
819 	    rs->rules[rs_num].inactive.ptr;
820 	rs->rules[rs_num].active.ptr_array =
821 	    rs->rules[rs_num].inactive.ptr_array;
822 	rs->rules[rs_num].active.rcount =
823 	    rs->rules[rs_num].inactive.rcount;
824 	rs->rules[rs_num].inactive.ptr = old_rules;
825 	rs->rules[rs_num].inactive.ptr_array = old_array;
826 	rs->rules[rs_num].inactive.rcount = old_rcount;
827 
828 	rs->rules[rs_num].active.ticket =
829 	    rs->rules[rs_num].inactive.ticket;
830 	pf_calc_skip_steps(rs->rules[rs_num].active.ptr);
831 
832 
833 	/* Purge the old rule list. */
834 	while ((rule = TAILQ_FIRST(old_rules)) != NULL)
835 		pf_rm_rule(old_rules, rule);
836 	if (rs->rules[rs_num].inactive.ptr_array)
837 		free(rs->rules[rs_num].inactive.ptr_array, M_TEMP);
838 	rs->rules[rs_num].inactive.ptr_array = NULL;
839 	rs->rules[rs_num].inactive.rcount = 0;
840 	rs->rules[rs_num].inactive.open = 0;
841 	pf_remove_if_empty_ruleset(rs);
842 	splx(s);
843 	return (0);
844 }
845 
846 int
847 pf_setup_pfsync_matching(struct pf_ruleset *rs)
848 {
849 	MD5_CTX			 ctx;
850 	struct pf_rule		*rule;
851 	int			 rs_cnt;
852 	u_int8_t		 digest[PF_MD5_DIGEST_LENGTH];
853 
854 	MD5Init(&ctx);
855 	for (rs_cnt = 0; rs_cnt < PF_RULESET_MAX; rs_cnt++) {
856 		/* XXX PF_RULESET_SCRUB as well? */
857 		if (rs_cnt == PF_RULESET_SCRUB)
858 			continue;
859 
860 		if (rs->rules[rs_cnt].inactive.ptr_array)
861 			free(rs->rules[rs_cnt].inactive.ptr_array, M_TEMP);
862 		rs->rules[rs_cnt].inactive.ptr_array = NULL;
863 
864 		if (rs->rules[rs_cnt].inactive.rcount) {
865 			rs->rules[rs_cnt].inactive.ptr_array =
866 			    malloc(sizeof(caddr_t) *
867 			    rs->rules[rs_cnt].inactive.rcount,
868 			    M_TEMP, M_NOWAIT);
869 
870 			if (!rs->rules[rs_cnt].inactive.ptr_array)
871 				return (ENOMEM);
872 		}
873 
874 		TAILQ_FOREACH(rule, rs->rules[rs_cnt].inactive.ptr,
875 		    entries) {
876 			pf_hash_rule(&ctx, rule);
877 			(rs->rules[rs_cnt].inactive.ptr_array)[rule->nr] = rule;
878 		}
879 	}
880 
881 	MD5Final(digest, &ctx);
882 	memcpy(pf_status.pf_chksum, digest, sizeof(pf_status.pf_chksum));
883 	return (0);
884 }
885 
886 int
887 pf_addr_setup(struct pf_ruleset *ruleset, struct pf_addr_wrap *addr,
888     sa_family_t af)
889 {
890 	if (pfi_dynaddr_setup(addr, af) ||
891 	    pf_tbladdr_setup(ruleset, addr))
892 		return (EINVAL);
893 
894 	return (0);
895 }
896 
897 void
898 pf_addr_copyout(struct pf_addr_wrap *addr)
899 {
900 	pfi_dynaddr_copyout(addr);
901 	pf_tbladdr_copyout(addr);
902 	pf_rtlabel_copyout(addr);
903 }
904 
905 int
906 pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
907 {
908 	struct pf_pooladdr	*pa = NULL;
909 	struct pf_pool		*pool = NULL;
910 	int			 s;
911 	int			 error = 0;
912 
913 	/* XXX keep in sync with switch() below */
914 	if (securelevel > 1)
915 		switch (cmd) {
916 		case DIOCGETRULES:
917 		case DIOCGETRULE:
918 		case DIOCGETADDRS:
919 		case DIOCGETADDR:
920 		case DIOCGETSTATE:
921 		case DIOCSETSTATUSIF:
922 		case DIOCGETSTATUS:
923 		case DIOCCLRSTATUS:
924 		case DIOCNATLOOK:
925 		case DIOCSETDEBUG:
926 		case DIOCGETSTATES:
927 		case DIOCGETTIMEOUT:
928 		case DIOCCLRRULECTRS:
929 		case DIOCGETLIMIT:
930 		case DIOCGETALTQS:
931 		case DIOCGETALTQ:
932 		case DIOCGETQSTATS:
933 		case DIOCGETRULESETS:
934 		case DIOCGETRULESET:
935 		case DIOCRGETTABLES:
936 		case DIOCRGETTSTATS:
937 		case DIOCRCLRTSTATS:
938 		case DIOCRCLRADDRS:
939 		case DIOCRADDADDRS:
940 		case DIOCRDELADDRS:
941 		case DIOCRSETADDRS:
942 		case DIOCRGETADDRS:
943 		case DIOCRGETASTATS:
944 		case DIOCRCLRASTATS:
945 		case DIOCRTSTADDRS:
946 		case DIOCOSFPGET:
947 		case DIOCGETSRCNODES:
948 		case DIOCCLRSRCNODES:
949 		case DIOCIGETIFACES:
950 		case DIOCSETIFFLAG:
951 		case DIOCCLRIFFLAG:
952 			break;
953 		case DIOCRCLRTABLES:
954 		case DIOCRADDTABLES:
955 		case DIOCRDELTABLES:
956 		case DIOCRSETTFLAGS:
957 			if (((struct pfioc_table *)addr)->pfrio_flags &
958 			    PFR_FLAG_DUMMY)
959 				break; /* dummy operation ok */
960 			return (EPERM);
961 		default:
962 			return (EPERM);
963 		}
964 
965 	if (!(flags & FWRITE))
966 		switch (cmd) {
967 		case DIOCGETRULES:
968 		case DIOCGETADDRS:
969 		case DIOCGETADDR:
970 		case DIOCGETSTATE:
971 		case DIOCGETSTATUS:
972 		case DIOCGETSTATES:
973 		case DIOCGETTIMEOUT:
974 		case DIOCGETLIMIT:
975 		case DIOCGETALTQS:
976 		case DIOCGETALTQ:
977 		case DIOCGETQSTATS:
978 		case DIOCGETRULESETS:
979 		case DIOCGETRULESET:
980 		case DIOCNATLOOK:
981 		case DIOCRGETTABLES:
982 		case DIOCRGETTSTATS:
983 		case DIOCRGETADDRS:
984 		case DIOCRGETASTATS:
985 		case DIOCRTSTADDRS:
986 		case DIOCOSFPGET:
987 		case DIOCGETSRCNODES:
988 		case DIOCIGETIFACES:
989 			break;
990 		case DIOCRCLRTABLES:
991 		case DIOCRADDTABLES:
992 		case DIOCRDELTABLES:
993 		case DIOCRCLRTSTATS:
994 		case DIOCRCLRADDRS:
995 		case DIOCRADDADDRS:
996 		case DIOCRDELADDRS:
997 		case DIOCRSETADDRS:
998 		case DIOCRSETTFLAGS:
999 			if (((struct pfioc_table *)addr)->pfrio_flags &
1000 			    PFR_FLAG_DUMMY) {
1001 				flags |= FWRITE; /* need write lock for dummy */
1002 				break; /* dummy operation ok */
1003 			}
1004 			return (EACCES);
1005 		case DIOCGETRULE:
1006 			if (((struct pfioc_rule *)addr)->action ==
1007 			    PF_GET_CLR_CNTR)
1008 				return (EACCES);
1009 			break;
1010 		default:
1011 			return (EACCES);
1012 		}
1013 
1014 	if (flags & FWRITE)
1015 		rw_enter_write(&pf_consistency_lock);
1016 	else
1017 		rw_enter_read(&pf_consistency_lock);
1018 
1019 	s = splsoftnet();
1020 	switch (cmd) {
1021 
1022 	case DIOCSTART:
1023 		if (pf_status.running)
1024 			error = EEXIST;
1025 		else {
1026 			pf_status.running = 1;
1027 			pf_status.since = time_second;
1028 			if (pf_status.stateid == 0) {
1029 				pf_status.stateid = time_second;
1030 				pf_status.stateid = pf_status.stateid << 32;
1031 			}
1032 			DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
1033 		}
1034 		break;
1035 
1036 	case DIOCSTOP:
1037 		if (!pf_status.running)
1038 			error = ENOENT;
1039 		else {
1040 			pf_status.running = 0;
1041 			pf_status.since = time_second;
1042 			DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
1043 		}
1044 		break;
1045 
1046 	case DIOCADDRULE: {
1047 		struct pfioc_rule	*pr = (struct pfioc_rule *)addr;
1048 		struct pf_ruleset	*ruleset;
1049 		struct pf_rule		*rule, *tail;
1050 		struct pf_pooladdr	*pa;
1051 		int			 rs_num;
1052 
1053 		pr->anchor[sizeof(pr->anchor) - 1] = 0;
1054 		ruleset = pf_find_ruleset(pr->anchor);
1055 		if (ruleset == NULL) {
1056 			error = EINVAL;
1057 			break;
1058 		}
1059 		rs_num = pf_get_ruleset_number(pr->rule.action);
1060 		if (rs_num >= PF_RULESET_MAX) {
1061 			error = EINVAL;
1062 			break;
1063 		}
1064 		if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
1065 			error = EINVAL;
1066 			break;
1067 		}
1068 		if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) {
1069 			error = EBUSY;
1070 			break;
1071 		}
1072 		if (pr->pool_ticket != ticket_pabuf) {
1073 			error = EBUSY;
1074 			break;
1075 		}
1076 		rule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL);
1077 		if (rule == NULL) {
1078 			error = ENOMEM;
1079 			break;
1080 		}
1081 		bcopy(&pr->rule, rule, sizeof(struct pf_rule));
1082 		rule->cuid = p->p_cred->p_ruid;
1083 		rule->cpid = p->p_pid;
1084 		rule->anchor = NULL;
1085 		rule->kif = NULL;
1086 		TAILQ_INIT(&rule->rpool.list);
1087 		/* initialize refcounting */
1088 		rule->states_cur = 0;
1089 		rule->src_nodes = 0;
1090 		rule->entries.tqe_prev = NULL;
1091 #ifndef INET
1092 		if (rule->af == AF_INET) {
1093 			pool_put(&pf_rule_pl, rule);
1094 			error = EAFNOSUPPORT;
1095 			break;
1096 		}
1097 #endif /* INET */
1098 #ifndef INET6
1099 		if (rule->af == AF_INET6) {
1100 			pool_put(&pf_rule_pl, rule);
1101 			error = EAFNOSUPPORT;
1102 			break;
1103 		}
1104 #endif /* INET6 */
1105 		tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
1106 		    pf_rulequeue);
1107 		if (tail)
1108 			rule->nr = tail->nr + 1;
1109 		else
1110 			rule->nr = 0;
1111 		if (rule->ifname[0]) {
1112 			rule->kif = pfi_kif_get(rule->ifname);
1113 			if (rule->kif == NULL) {
1114 				pool_put(&pf_rule_pl, rule);
1115 				error = EINVAL;
1116 				break;
1117 			}
1118 			pfi_kif_ref(rule->kif, PFI_KIF_REF_RULE);
1119 		}
1120 
1121 		if (rule->rtableid > 0 && !rtable_exists(rule->rtableid))
1122 			error = EBUSY;
1123 
1124 #ifdef ALTQ
1125 		/* set queue IDs */
1126 		if (rule->qname[0] != 0) {
1127 			if ((rule->qid = pf_qname2qid(rule->qname)) == 0)
1128 				error = EBUSY;
1129 			else if (rule->pqname[0] != 0) {
1130 				if ((rule->pqid =
1131 				    pf_qname2qid(rule->pqname)) == 0)
1132 					error = EBUSY;
1133 			} else
1134 				rule->pqid = rule->qid;
1135 		}
1136 #endif
1137 		if (rule->tagname[0])
1138 			if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
1139 				error = EBUSY;
1140 		if (rule->match_tagname[0])
1141 			if ((rule->match_tag =
1142 			    pf_tagname2tag(rule->match_tagname)) == 0)
1143 				error = EBUSY;
1144 		if (rule->rt && !rule->direction)
1145 			error = EINVAL;
1146 #if NPFLOG > 0
1147 		if (!rule->log)
1148 			rule->logif = 0;
1149 		if (rule->logif >= PFLOGIFS_MAX)
1150 			error = EINVAL;
1151 #endif
1152 		if (pf_rtlabel_add(&rule->src.addr) ||
1153 		    pf_rtlabel_add(&rule->dst.addr))
1154 			error = EBUSY;
1155 		if (pf_addr_setup(ruleset, &rule->src.addr, rule->af))
1156 			error = EINVAL;
1157 		if (pf_addr_setup(ruleset, &rule->dst.addr, rule->af))
1158 			error = EINVAL;
1159 		if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
1160 			error = EINVAL;
1161 		TAILQ_FOREACH(pa, &pf_pabuf, entries)
1162 			if (pf_tbladdr_setup(ruleset, &pa->addr))
1163 				error = EINVAL;
1164 
1165 		if (rule->overload_tblname[0]) {
1166 			if ((rule->overload_tbl = pfr_attach_table(ruleset,
1167 			    rule->overload_tblname)) == NULL)
1168 				error = EINVAL;
1169 			else
1170 				rule->overload_tbl->pfrkt_flags |=
1171 				    PFR_TFLAG_ACTIVE;
1172 		}
1173 
1174 		pf_mv_pool(&pf_pabuf, &rule->rpool.list);
1175 		if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
1176 		    (rule->action == PF_BINAT)) && rule->anchor == NULL) ||
1177 		    (rule->rt > PF_FASTROUTE)) &&
1178 		    (TAILQ_FIRST(&rule->rpool.list) == NULL))
1179 			error = EINVAL;
1180 
1181 		if (error) {
1182 			pf_rm_rule(NULL, rule);
1183 			break;
1184 		}
1185 		rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
1186 		rule->evaluations = rule->packets[0] = rule->packets[1] =
1187 		    rule->bytes[0] = rule->bytes[1] = 0;
1188 		TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr,
1189 		    rule, entries);
1190 		ruleset->rules[rs_num].inactive.rcount++;
1191 		break;
1192 	}
1193 
1194 	case DIOCGETRULES: {
1195 		struct pfioc_rule	*pr = (struct pfioc_rule *)addr;
1196 		struct pf_ruleset	*ruleset;
1197 		struct pf_rule		*tail;
1198 		int			 rs_num;
1199 
1200 		pr->anchor[sizeof(pr->anchor) - 1] = 0;
1201 		ruleset = pf_find_ruleset(pr->anchor);
1202 		if (ruleset == NULL) {
1203 			error = EINVAL;
1204 			break;
1205 		}
1206 		rs_num = pf_get_ruleset_number(pr->rule.action);
1207 		if (rs_num >= PF_RULESET_MAX) {
1208 			error = EINVAL;
1209 			break;
1210 		}
1211 		tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
1212 		    pf_rulequeue);
1213 		if (tail)
1214 			pr->nr = tail->nr + 1;
1215 		else
1216 			pr->nr = 0;
1217 		pr->ticket = ruleset->rules[rs_num].active.ticket;
1218 		break;
1219 	}
1220 
1221 	case DIOCGETRULE: {
1222 		struct pfioc_rule	*pr = (struct pfioc_rule *)addr;
1223 		struct pf_ruleset	*ruleset;
1224 		struct pf_rule		*rule;
1225 		int			 rs_num, i;
1226 
1227 		pr->anchor[sizeof(pr->anchor) - 1] = 0;
1228 		ruleset = pf_find_ruleset(pr->anchor);
1229 		if (ruleset == NULL) {
1230 			error = EINVAL;
1231 			break;
1232 		}
1233 		rs_num = pf_get_ruleset_number(pr->rule.action);
1234 		if (rs_num >= PF_RULESET_MAX) {
1235 			error = EINVAL;
1236 			break;
1237 		}
1238 		if (pr->ticket != ruleset->rules[rs_num].active.ticket) {
1239 			error = EBUSY;
1240 			break;
1241 		}
1242 		rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
1243 		while ((rule != NULL) && (rule->nr != pr->nr))
1244 			rule = TAILQ_NEXT(rule, entries);
1245 		if (rule == NULL) {
1246 			error = EBUSY;
1247 			break;
1248 		}
1249 		bcopy(rule, &pr->rule, sizeof(struct pf_rule));
1250 		if (pf_anchor_copyout(ruleset, rule, pr)) {
1251 			error = EBUSY;
1252 			break;
1253 		}
1254 		pf_addr_copyout(&pr->rule.src.addr);
1255 		pf_addr_copyout(&pr->rule.dst.addr);
1256 		for (i = 0; i < PF_SKIP_COUNT; ++i)
1257 			if (rule->skip[i].ptr == NULL)
1258 				pr->rule.skip[i].nr = -1;
1259 			else
1260 				pr->rule.skip[i].nr =
1261 				    rule->skip[i].ptr->nr;
1262 
1263 		if (pr->action == PF_GET_CLR_CNTR) {
1264 			rule->evaluations = 0;
1265 			rule->packets[0] = rule->packets[1] = 0;
1266 			rule->bytes[0] = rule->bytes[1] = 0;
1267 			rule->states_tot = 0;
1268 		}
1269 		break;
1270 	}
1271 
1272 	case DIOCCHANGERULE: {
1273 		struct pfioc_rule	*pcr = (struct pfioc_rule *)addr;
1274 		struct pf_ruleset	*ruleset;
1275 		struct pf_rule		*oldrule = NULL, *newrule = NULL;
1276 		u_int32_t		 nr = 0;
1277 		int			 rs_num;
1278 
1279 		if (!(pcr->action == PF_CHANGE_REMOVE ||
1280 		    pcr->action == PF_CHANGE_GET_TICKET) &&
1281 		    pcr->pool_ticket != ticket_pabuf) {
1282 			error = EBUSY;
1283 			break;
1284 		}
1285 
1286 		if (pcr->action < PF_CHANGE_ADD_HEAD ||
1287 		    pcr->action > PF_CHANGE_GET_TICKET) {
1288 			error = EINVAL;
1289 			break;
1290 		}
1291 		ruleset = pf_find_ruleset(pcr->anchor);
1292 		if (ruleset == NULL) {
1293 			error = EINVAL;
1294 			break;
1295 		}
1296 		rs_num = pf_get_ruleset_number(pcr->rule.action);
1297 		if (rs_num >= PF_RULESET_MAX) {
1298 			error = EINVAL;
1299 			break;
1300 		}
1301 
1302 		if (pcr->action == PF_CHANGE_GET_TICKET) {
1303 			pcr->ticket = ++ruleset->rules[rs_num].active.ticket;
1304 			break;
1305 		} else {
1306 			if (pcr->ticket !=
1307 			    ruleset->rules[rs_num].active.ticket) {
1308 				error = EINVAL;
1309 				break;
1310 			}
1311 			if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
1312 				error = EINVAL;
1313 				break;
1314 			}
1315 		}
1316 
1317 		if (pcr->action != PF_CHANGE_REMOVE) {
1318 			newrule = pool_get(&pf_rule_pl, PR_WAITOK|PR_LIMITFAIL);
1319 			if (newrule == NULL) {
1320 				error = ENOMEM;
1321 				break;
1322 			}
1323 			bcopy(&pcr->rule, newrule, sizeof(struct pf_rule));
1324 			newrule->cuid = p->p_cred->p_ruid;
1325 			newrule->cpid = p->p_pid;
1326 			TAILQ_INIT(&newrule->rpool.list);
1327 			/* initialize refcounting */
1328 			newrule->states_cur = 0;
1329 			newrule->entries.tqe_prev = NULL;
1330 #ifndef INET
1331 			if (newrule->af == AF_INET) {
1332 				pool_put(&pf_rule_pl, newrule);
1333 				error = EAFNOSUPPORT;
1334 				break;
1335 			}
1336 #endif /* INET */
1337 #ifndef INET6
1338 			if (newrule->af == AF_INET6) {
1339 				pool_put(&pf_rule_pl, newrule);
1340 				error = EAFNOSUPPORT;
1341 				break;
1342 			}
1343 #endif /* INET6 */
1344 			if (newrule->ifname[0]) {
1345 				newrule->kif = pfi_kif_get(newrule->ifname);
1346 				if (newrule->kif == NULL) {
1347 					pool_put(&pf_rule_pl, newrule);
1348 					error = EINVAL;
1349 					break;
1350 				}
1351 				pfi_kif_ref(newrule->kif, PFI_KIF_REF_RULE);
1352 			} else
1353 				newrule->kif = NULL;
1354 
1355 			if (newrule->rtableid > 0 &&
1356 			    !rtable_exists(newrule->rtableid))
1357 				error = EBUSY;
1358 
1359 #ifdef ALTQ
1360 			/* set queue IDs */
1361 			if (newrule->qname[0] != 0) {
1362 				if ((newrule->qid =
1363 				    pf_qname2qid(newrule->qname)) == 0)
1364 					error = EBUSY;
1365 				else if (newrule->pqname[0] != 0) {
1366 					if ((newrule->pqid =
1367 					    pf_qname2qid(newrule->pqname)) == 0)
1368 						error = EBUSY;
1369 				} else
1370 					newrule->pqid = newrule->qid;
1371 			}
1372 #endif /* ALTQ */
1373 			if (newrule->tagname[0])
1374 				if ((newrule->tag =
1375 				    pf_tagname2tag(newrule->tagname)) == 0)
1376 					error = EBUSY;
1377 			if (newrule->match_tagname[0])
1378 				if ((newrule->match_tag = pf_tagname2tag(
1379 				    newrule->match_tagname)) == 0)
1380 					error = EBUSY;
1381 			if (newrule->rt && !newrule->direction)
1382 				error = EINVAL;
1383 #if NPFLOG > 0
1384 			if (!newrule->log)
1385 				newrule->logif = 0;
1386 			if (newrule->logif >= PFLOGIFS_MAX)
1387 				error = EINVAL;
1388 #endif
1389 			if (pf_rtlabel_add(&newrule->src.addr) ||
1390 			    pf_rtlabel_add(&newrule->dst.addr))
1391 				error = EBUSY;
1392 			if (pf_addr_setup(ruleset, &newrule->src.addr, newrule->af))
1393 				error = EINVAL;
1394 			if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af))
1395 				error = EINVAL;
1396 			if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
1397 				error = EINVAL;
1398 			TAILQ_FOREACH(pa, &pf_pabuf, entries)
1399 				if (pf_tbladdr_setup(ruleset, &pa->addr))
1400 					error = EINVAL;
1401 
1402 			if (newrule->overload_tblname[0]) {
1403 				if ((newrule->overload_tbl = pfr_attach_table(
1404 				    ruleset, newrule->overload_tblname)) ==
1405 				    NULL)
1406 					error = EINVAL;
1407 				else
1408 					newrule->overload_tbl->pfrkt_flags |=
1409 					    PFR_TFLAG_ACTIVE;
1410 			}
1411 
1412 			pf_mv_pool(&pf_pabuf, &newrule->rpool.list);
1413 			if (((((newrule->action == PF_NAT) ||
1414 			    (newrule->action == PF_RDR) ||
1415 			    (newrule->action == PF_BINAT) ||
1416 			    (newrule->rt > PF_FASTROUTE)) &&
1417 			    !newrule->anchor)) &&
1418 			    (TAILQ_FIRST(&newrule->rpool.list) == NULL))
1419 				error = EINVAL;
1420 
1421 			if (error) {
1422 				pf_rm_rule(NULL, newrule);
1423 				break;
1424 			}
1425 			newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list);
1426 			newrule->evaluations = 0;
1427 			newrule->packets[0] = newrule->packets[1] = 0;
1428 			newrule->bytes[0] = newrule->bytes[1] = 0;
1429 		}
1430 		pf_empty_pool(&pf_pabuf);
1431 
1432 		if (pcr->action == PF_CHANGE_ADD_HEAD)
1433 			oldrule = TAILQ_FIRST(
1434 			    ruleset->rules[rs_num].active.ptr);
1435 		else if (pcr->action == PF_CHANGE_ADD_TAIL)
1436 			oldrule = TAILQ_LAST(
1437 			    ruleset->rules[rs_num].active.ptr, pf_rulequeue);
1438 		else {
1439 			oldrule = TAILQ_FIRST(
1440 			    ruleset->rules[rs_num].active.ptr);
1441 			while ((oldrule != NULL) && (oldrule->nr != pcr->nr))
1442 				oldrule = TAILQ_NEXT(oldrule, entries);
1443 			if (oldrule == NULL) {
1444 				if (newrule != NULL)
1445 					pf_rm_rule(NULL, newrule);
1446 				error = EINVAL;
1447 				break;
1448 			}
1449 		}
1450 
1451 		if (pcr->action == PF_CHANGE_REMOVE) {
1452 			pf_rm_rule(ruleset->rules[rs_num].active.ptr, oldrule);
1453 			ruleset->rules[rs_num].active.rcount--;
1454 		} else {
1455 			if (oldrule == NULL)
1456 				TAILQ_INSERT_TAIL(
1457 				    ruleset->rules[rs_num].active.ptr,
1458 				    newrule, entries);
1459 			else if (pcr->action == PF_CHANGE_ADD_HEAD ||
1460 			    pcr->action == PF_CHANGE_ADD_BEFORE)
1461 				TAILQ_INSERT_BEFORE(oldrule, newrule, entries);
1462 			else
1463 				TAILQ_INSERT_AFTER(
1464 				    ruleset->rules[rs_num].active.ptr,
1465 				    oldrule, newrule, entries);
1466 			ruleset->rules[rs_num].active.rcount++;
1467 		}
1468 
1469 		nr = 0;
1470 		TAILQ_FOREACH(oldrule,
1471 		    ruleset->rules[rs_num].active.ptr, entries)
1472 			oldrule->nr = nr++;
1473 
1474 		ruleset->rules[rs_num].active.ticket++;
1475 
1476 		pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
1477 		pf_remove_if_empty_ruleset(ruleset);
1478 
1479 		break;
1480 	}
1481 
1482 	case DIOCCLRSTATES: {
1483 		struct pf_state		*s, *nexts;
1484 		struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
1485 		u_int			 killed = 0;
1486 
1487 		for (s = RB_MIN(pf_state_tree_id, &tree_id); s; s = nexts) {
1488 			nexts = RB_NEXT(pf_state_tree_id, &tree_id, s);
1489 
1490 			if (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
1491 			    s->kif->pfik_name)) {
1492 #if NPFSYNC
1493 				/* don't send out individual delete messages */
1494 				s->sync_flags = PFSTATE_NOSYNC;
1495 #endif
1496 				pf_unlink_state(s);
1497 				killed++;
1498 			}
1499 		}
1500 		psk->psk_killed = killed;
1501 #if NPFSYNC
1502 		pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
1503 #endif
1504 		break;
1505 	}
1506 
1507 	case DIOCKILLSTATES: {
1508 		struct pf_state		*s, *nexts;
1509 		struct pf_state_key	*sk;
1510 		struct pf_addr		*srcaddr, *dstaddr;
1511 		u_int16_t		 srcport, dstport;
1512 		struct pfioc_state_kill	*psk = (struct pfioc_state_kill *)addr;
1513 		u_int			 killed = 0;
1514 
1515 		if (psk->psk_pfcmp.id) {
1516 			if (psk->psk_pfcmp.creatorid == 0)
1517 				psk->psk_pfcmp.creatorid = pf_status.hostid;
1518 			if ((s = pf_find_state_byid(&psk->psk_pfcmp))) {
1519 #if NPFSYNC > 0
1520 				/* send immediate delete of state */
1521 				pfsync_delete_state(s);
1522 				s->sync_flags |= PFSTATE_NOSYNC;
1523 #endif
1524 				pf_unlink_state(s);
1525 				psk->psk_killed = 1;
1526 			}
1527 			break;
1528 		}
1529 
1530 		for (s = RB_MIN(pf_state_tree_id, &tree_id); s;
1531 		    s = nexts) {
1532 			nexts = RB_NEXT(pf_state_tree_id, &tree_id, s);
1533 			sk = s->key[PF_SK_WIRE];
1534 
1535 			if (s->direction == PF_OUT) {
1536 				srcaddr = &sk->addr[1];
1537 				dstaddr = &sk->addr[0];
1538 				srcport = sk->port[0];
1539 				dstport = sk->port[0];
1540 			} else {
1541 				srcaddr = &sk->addr[0];
1542 				dstaddr = &sk->addr[1];
1543 				srcport = sk->port[0];
1544 				dstport = sk->port[0];
1545 			}
1546 			if ((!psk->psk_af || sk->af == psk->psk_af)
1547 			    && (!psk->psk_proto || psk->psk_proto ==
1548 			    sk->proto) &&
1549 			    PF_MATCHA(psk->psk_src.neg,
1550 			    &psk->psk_src.addr.v.a.addr,
1551 			    &psk->psk_src.addr.v.a.mask,
1552 			    srcaddr, sk->af) &&
1553 			    PF_MATCHA(psk->psk_dst.neg,
1554 			    &psk->psk_dst.addr.v.a.addr,
1555 			    &psk->psk_dst.addr.v.a.mask,
1556 			    dstaddr, sk->af) &&
1557 			    (psk->psk_src.port_op == 0 ||
1558 			    pf_match_port(psk->psk_src.port_op,
1559 			    psk->psk_src.port[0], psk->psk_src.port[1],
1560 			    srcport)) &&
1561 			    (psk->psk_dst.port_op == 0 ||
1562 			    pf_match_port(psk->psk_dst.port_op,
1563 			    psk->psk_dst.port[0], psk->psk_dst.port[1],
1564 			    dstport)) &&
1565 			    (!psk->psk_label[0] || (s->rule.ptr->label[0] &&
1566 			    !strcmp(psk->psk_label, s->rule.ptr->label))) &&
1567 			    (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
1568 			    s->kif->pfik_name))) {
1569 #if NPFSYNC > 0
1570 				/* send immediate delete of state */
1571 				pfsync_delete_state(s);
1572 				s->sync_flags |= PFSTATE_NOSYNC;
1573 #endif
1574 				pf_unlink_state(s);
1575 				killed++;
1576 			}
1577 		}
1578 		psk->psk_killed = killed;
1579 		break;
1580 	}
1581 
1582 	case DIOCADDSTATE: {
1583 		struct pfioc_state	*ps = (struct pfioc_state *)addr;
1584 		struct pfsync_state	*sp = &ps->state;
1585 
1586 		if (sp->timeout >= PFTM_MAX &&
1587 		    sp->timeout != PFTM_UNTIL_PACKET) {
1588 			error = EINVAL;
1589 			break;
1590 		}
1591 		error = pfsync_state_import(sp, PFSYNC_SI_IOCTL);
1592 		break;
1593 	}
1594 
1595 	case DIOCGETSTATE: {
1596 		struct pfioc_state	*ps = (struct pfioc_state *)addr;
1597 		struct pf_state		*s;
1598 		struct pf_state_cmp	 id_key;
1599 
1600 		bcopy(ps->state.id, &id_key.id, sizeof(id_key.id));
1601 		id_key.creatorid = ps->state.creatorid;
1602 
1603 		s = pf_find_state_byid(&id_key);
1604 		if (s == NULL) {
1605 			error = ENOENT;
1606 			break;
1607 		}
1608 
1609 		pfsync_state_export(&ps->state, s);
1610 		break;
1611 	}
1612 
1613 	case DIOCGETSTATES: {
1614 		struct pfioc_states	*ps = (struct pfioc_states *)addr;
1615 		struct pf_state		*state;
1616 		struct pfsync_state	*p, *pstore;
1617 		u_int32_t		 nr = 0;
1618 
1619 		if (ps->ps_len == 0) {
1620 			nr = pf_status.states;
1621 			ps->ps_len = sizeof(struct pfsync_state) * nr;
1622 			break;
1623 		}
1624 
1625 		pstore = malloc(sizeof(*pstore), M_TEMP, M_WAITOK);
1626 
1627 		p = ps->ps_states;
1628 
1629 		state = TAILQ_FIRST(&state_list);
1630 		while (state) {
1631 			if (state->timeout != PFTM_UNLINKED) {
1632 				if ((nr+1) * sizeof(*p) > (unsigned)ps->ps_len)
1633 					break;
1634 				pfsync_state_export(pstore, state);
1635 				error = copyout(pstore, p, sizeof(*p));
1636 				if (error) {
1637 					free(pstore, M_TEMP);
1638 					goto fail;
1639 				}
1640 				p++;
1641 				nr++;
1642 			}
1643 			state = TAILQ_NEXT(state, entry_list);
1644 		}
1645 
1646 		ps->ps_len = sizeof(struct pfsync_state) * nr;
1647 
1648 		free(pstore, M_TEMP);
1649 		break;
1650 	}
1651 
1652 	case DIOCGETSTATUS: {
1653 		struct pf_status *s = (struct pf_status *)addr;
1654 		bcopy(&pf_status, s, sizeof(struct pf_status));
1655 		pfi_update_status(s->ifname, s);
1656 		break;
1657 	}
1658 
1659 	case DIOCSETSTATUSIF: {
1660 		struct pfioc_if	*pi = (struct pfioc_if *)addr;
1661 
1662 		if (pi->ifname[0] == 0) {
1663 			bzero(pf_status.ifname, IFNAMSIZ);
1664 			break;
1665 		}
1666 		strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ);
1667 		break;
1668 	}
1669 
1670 	case DIOCCLRSTATUS: {
1671 		bzero(pf_status.counters, sizeof(pf_status.counters));
1672 		bzero(pf_status.fcounters, sizeof(pf_status.fcounters));
1673 		bzero(pf_status.scounters, sizeof(pf_status.scounters));
1674 		pf_status.since = time_second;
1675 		if (*pf_status.ifname)
1676 			pfi_update_status(pf_status.ifname, NULL);
1677 		break;
1678 	}
1679 
1680 	case DIOCNATLOOK: {
1681 		struct pfioc_natlook	*pnl = (struct pfioc_natlook *)addr;
1682 		struct pf_state_key	*sk;
1683 		struct pf_state		*state;
1684 		struct pf_state_key_cmp	 key;
1685 		int			 m = 0, direction = pnl->direction;
1686 		int			 sidx, didx;
1687 
1688 		/* NATLOOK src and dst are reversed, so reverse sidx/didx */
1689 		sidx = (direction == PF_IN) ? 1 : 0;
1690 		didx = (direction == PF_IN) ? 0 : 1;
1691 
1692 		if (!pnl->proto ||
1693 		    PF_AZERO(&pnl->saddr, pnl->af) ||
1694 		    PF_AZERO(&pnl->daddr, pnl->af) ||
1695 		    ((pnl->proto == IPPROTO_TCP ||
1696 		    pnl->proto == IPPROTO_UDP) &&
1697 		    (!pnl->dport || !pnl->sport)))
1698 			error = EINVAL;
1699 		else {
1700 			key.af = pnl->af;
1701 			key.proto = pnl->proto;
1702 			PF_ACPY(&key.addr[sidx], &pnl->saddr, pnl->af);
1703 			key.port[sidx] = pnl->sport;
1704 			PF_ACPY(&key.addr[didx], &pnl->daddr, pnl->af);
1705 			key.port[didx] = pnl->dport;
1706 
1707 			state = pf_find_state_all(&key, direction, &m);
1708 
1709 			if (m > 1)
1710 				error = E2BIG;	/* more than one state */
1711 			else if (state != NULL) {
1712 				sk = state->key[sidx];
1713 				PF_ACPY(&pnl->rsaddr, &sk->addr[sidx], sk->af);
1714 				pnl->rsport = sk->port[sidx];
1715 				PF_ACPY(&pnl->rdaddr, &sk->addr[didx], sk->af);
1716 				pnl->rdport = sk->port[didx];
1717 			} else
1718 				error = ENOENT;
1719 		}
1720 		break;
1721 	}
1722 
1723 	case DIOCSETTIMEOUT: {
1724 		struct pfioc_tm	*pt = (struct pfioc_tm *)addr;
1725 		int		 old;
1726 
1727 		if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
1728 		    pt->seconds < 0) {
1729 			error = EINVAL;
1730 			goto fail;
1731 		}
1732 		old = pf_default_rule.timeout[pt->timeout];
1733 		if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0)
1734 			pt->seconds = 1;
1735 		pf_default_rule.timeout[pt->timeout] = pt->seconds;
1736 		if (pt->timeout == PFTM_INTERVAL && pt->seconds < old)
1737 			wakeup(pf_purge_thread);
1738 		pt->seconds = old;
1739 		break;
1740 	}
1741 
1742 	case DIOCGETTIMEOUT: {
1743 		struct pfioc_tm	*pt = (struct pfioc_tm *)addr;
1744 
1745 		if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
1746 			error = EINVAL;
1747 			goto fail;
1748 		}
1749 		pt->seconds = pf_default_rule.timeout[pt->timeout];
1750 		break;
1751 	}
1752 
1753 	case DIOCGETLIMIT: {
1754 		struct pfioc_limit	*pl = (struct pfioc_limit *)addr;
1755 
1756 		if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
1757 			error = EINVAL;
1758 			goto fail;
1759 		}
1760 		pl->limit = pf_pool_limits[pl->index].limit;
1761 		break;
1762 	}
1763 
1764 	case DIOCSETLIMIT: {
1765 		struct pfioc_limit	*pl = (struct pfioc_limit *)addr;
1766 		int			 old_limit;
1767 
1768 		if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
1769 		    pf_pool_limits[pl->index].pp == NULL) {
1770 			error = EINVAL;
1771 			goto fail;
1772 		}
1773 		if (pool_sethardlimit(pf_pool_limits[pl->index].pp,
1774 		    pl->limit, NULL, 0) != 0) {
1775 			error = EBUSY;
1776 			goto fail;
1777 		}
1778 		old_limit = pf_pool_limits[pl->index].limit;
1779 		pf_pool_limits[pl->index].limit = pl->limit;
1780 		pl->limit = old_limit;
1781 		break;
1782 	}
1783 
1784 	case DIOCSETDEBUG: {
1785 		u_int32_t	*level = (u_int32_t *)addr;
1786 
1787 		pf_status.debug = *level;
1788 		break;
1789 	}
1790 
1791 	case DIOCCLRRULECTRS: {
1792 		/* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */
1793 		struct pf_ruleset	*ruleset = &pf_main_ruleset;
1794 		struct pf_rule		*rule;
1795 
1796 		TAILQ_FOREACH(rule,
1797 		    ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) {
1798 			rule->evaluations = 0;
1799 			rule->packets[0] = rule->packets[1] = 0;
1800 			rule->bytes[0] = rule->bytes[1] = 0;
1801 		}
1802 		break;
1803 	}
1804 
1805 #ifdef ALTQ
1806 	case DIOCSTARTALTQ: {
1807 		struct pf_altq		*altq;
1808 
1809 		/* enable all altq interfaces on active list */
1810 		TAILQ_FOREACH(altq, pf_altqs_active, entries) {
1811 			if (altq->qname[0] == 0) {
1812 				error = pf_enable_altq(altq);
1813 				if (error != 0)
1814 					break;
1815 			}
1816 		}
1817 		if (error == 0)
1818 			pf_altq_running = 1;
1819 		DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
1820 		break;
1821 	}
1822 
1823 	case DIOCSTOPALTQ: {
1824 		struct pf_altq		*altq;
1825 
1826 		/* disable all altq interfaces on active list */
1827 		TAILQ_FOREACH(altq, pf_altqs_active, entries) {
1828 			if (altq->qname[0] == 0) {
1829 				error = pf_disable_altq(altq);
1830 				if (error != 0)
1831 					break;
1832 			}
1833 		}
1834 		if (error == 0)
1835 			pf_altq_running = 0;
1836 		DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
1837 		break;
1838 	}
1839 
1840 	case DIOCADDALTQ: {
1841 		struct pfioc_altq	*pa = (struct pfioc_altq *)addr;
1842 		struct pf_altq		*altq, *a;
1843 
1844 		if (pa->ticket != ticket_altqs_inactive) {
1845 			error = EBUSY;
1846 			break;
1847 		}
1848 		altq = pool_get(&pf_altq_pl, PR_WAITOK|PR_LIMITFAIL);
1849 		if (altq == NULL) {
1850 			error = ENOMEM;
1851 			break;
1852 		}
1853 		bcopy(&pa->altq, altq, sizeof(struct pf_altq));
1854 
1855 		/*
1856 		 * if this is for a queue, find the discipline and
1857 		 * copy the necessary fields
1858 		 */
1859 		if (altq->qname[0] != 0) {
1860 			if ((altq->qid = pf_qname2qid(altq->qname)) == 0) {
1861 				error = EBUSY;
1862 				pool_put(&pf_altq_pl, altq);
1863 				break;
1864 			}
1865 			altq->altq_disc = NULL;
1866 			TAILQ_FOREACH(a, pf_altqs_inactive, entries) {
1867 				if (strncmp(a->ifname, altq->ifname,
1868 				    IFNAMSIZ) == 0 && a->qname[0] == 0) {
1869 					altq->altq_disc = a->altq_disc;
1870 					break;
1871 				}
1872 			}
1873 		}
1874 
1875 		error = altq_add(altq);
1876 		if (error) {
1877 			pool_put(&pf_altq_pl, altq);
1878 			break;
1879 		}
1880 
1881 		TAILQ_INSERT_TAIL(pf_altqs_inactive, altq, entries);
1882 		bcopy(altq, &pa->altq, sizeof(struct pf_altq));
1883 		break;
1884 	}
1885 
1886 	case DIOCGETALTQS: {
1887 		struct pfioc_altq	*pa = (struct pfioc_altq *)addr;
1888 		struct pf_altq		*altq;
1889 
1890 		pa->nr = 0;
1891 		TAILQ_FOREACH(altq, pf_altqs_active, entries)
1892 			pa->nr++;
1893 		pa->ticket = ticket_altqs_active;
1894 		break;
1895 	}
1896 
1897 	case DIOCGETALTQ: {
1898 		struct pfioc_altq	*pa = (struct pfioc_altq *)addr;
1899 		struct pf_altq		*altq;
1900 		u_int32_t		 nr;
1901 
1902 		if (pa->ticket != ticket_altqs_active) {
1903 			error = EBUSY;
1904 			break;
1905 		}
1906 		nr = 0;
1907 		altq = TAILQ_FIRST(pf_altqs_active);
1908 		while ((altq != NULL) && (nr < pa->nr)) {
1909 			altq = TAILQ_NEXT(altq, entries);
1910 			nr++;
1911 		}
1912 		if (altq == NULL) {
1913 			error = EBUSY;
1914 			break;
1915 		}
1916 		bcopy(altq, &pa->altq, sizeof(struct pf_altq));
1917 		break;
1918 	}
1919 
1920 	case DIOCCHANGEALTQ:
1921 		/* CHANGEALTQ not supported yet! */
1922 		error = ENODEV;
1923 		break;
1924 
1925 	case DIOCGETQSTATS: {
1926 		struct pfioc_qstats	*pq = (struct pfioc_qstats *)addr;
1927 		struct pf_altq		*altq;
1928 		u_int32_t		 nr;
1929 		int			 nbytes;
1930 
1931 		if (pq->ticket != ticket_altqs_active) {
1932 			error = EBUSY;
1933 			break;
1934 		}
1935 		nbytes = pq->nbytes;
1936 		nr = 0;
1937 		altq = TAILQ_FIRST(pf_altqs_active);
1938 		while ((altq != NULL) && (nr < pq->nr)) {
1939 			altq = TAILQ_NEXT(altq, entries);
1940 			nr++;
1941 		}
1942 		if (altq == NULL) {
1943 			error = EBUSY;
1944 			break;
1945 		}
1946 		error = altq_getqstats(altq, pq->buf, &nbytes);
1947 		if (error == 0) {
1948 			pq->scheduler = altq->scheduler;
1949 			pq->nbytes = nbytes;
1950 		}
1951 		break;
1952 	}
1953 #endif /* ALTQ */
1954 
1955 	case DIOCBEGINADDRS: {
1956 		struct pfioc_pooladdr	*pp = (struct pfioc_pooladdr *)addr;
1957 
1958 		pf_empty_pool(&pf_pabuf);
1959 		pp->ticket = ++ticket_pabuf;
1960 		break;
1961 	}
1962 
1963 	case DIOCADDADDR: {
1964 		struct pfioc_pooladdr	*pp = (struct pfioc_pooladdr *)addr;
1965 
1966 		if (pp->ticket != ticket_pabuf) {
1967 			error = EBUSY;
1968 			break;
1969 		}
1970 #ifndef INET
1971 		if (pp->af == AF_INET) {
1972 			error = EAFNOSUPPORT;
1973 			break;
1974 		}
1975 #endif /* INET */
1976 #ifndef INET6
1977 		if (pp->af == AF_INET6) {
1978 			error = EAFNOSUPPORT;
1979 			break;
1980 		}
1981 #endif /* INET6 */
1982 		if (pp->addr.addr.type != PF_ADDR_ADDRMASK &&
1983 		    pp->addr.addr.type != PF_ADDR_DYNIFTL &&
1984 		    pp->addr.addr.type != PF_ADDR_TABLE) {
1985 			error = EINVAL;
1986 			break;
1987 		}
1988 		pa = pool_get(&pf_pooladdr_pl, PR_WAITOK|PR_LIMITFAIL);
1989 		if (pa == NULL) {
1990 			error = ENOMEM;
1991 			break;
1992 		}
1993 		bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr));
1994 		if (pa->ifname[0]) {
1995 			pa->kif = pfi_kif_get(pa->ifname);
1996 			if (pa->kif == NULL) {
1997 				pool_put(&pf_pooladdr_pl, pa);
1998 				error = EINVAL;
1999 				break;
2000 			}
2001 			pfi_kif_ref(pa->kif, PFI_KIF_REF_RULE);
2002 		}
2003 		if (pfi_dynaddr_setup(&pa->addr, pp->af)) {
2004 			pfi_dynaddr_remove(&pa->addr);
2005 			pfi_kif_unref(pa->kif, PFI_KIF_REF_RULE);
2006 			pool_put(&pf_pooladdr_pl, pa);
2007 			error = EINVAL;
2008 			break;
2009 		}
2010 		TAILQ_INSERT_TAIL(&pf_pabuf, pa, entries);
2011 		break;
2012 	}
2013 
2014 	case DIOCGETADDRS: {
2015 		struct pfioc_pooladdr	*pp = (struct pfioc_pooladdr *)addr;
2016 
2017 		pp->nr = 0;
2018 		pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
2019 		    pp->r_num, 0, 1, 0);
2020 		if (pool == NULL) {
2021 			error = EBUSY;
2022 			break;
2023 		}
2024 		TAILQ_FOREACH(pa, &pool->list, entries)
2025 			pp->nr++;
2026 		break;
2027 	}
2028 
2029 	case DIOCGETADDR: {
2030 		struct pfioc_pooladdr	*pp = (struct pfioc_pooladdr *)addr;
2031 		u_int32_t		 nr = 0;
2032 
2033 		pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
2034 		    pp->r_num, 0, 1, 1);
2035 		if (pool == NULL) {
2036 			error = EBUSY;
2037 			break;
2038 		}
2039 		pa = TAILQ_FIRST(&pool->list);
2040 		while ((pa != NULL) && (nr < pp->nr)) {
2041 			pa = TAILQ_NEXT(pa, entries);
2042 			nr++;
2043 		}
2044 		if (pa == NULL) {
2045 			error = EBUSY;
2046 			break;
2047 		}
2048 		bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr));
2049 		pf_addr_copyout(&pp->addr.addr);
2050 		break;
2051 	}
2052 
2053 	case DIOCCHANGEADDR: {
2054 		struct pfioc_pooladdr	*pca = (struct pfioc_pooladdr *)addr;
2055 		struct pf_pooladdr	*oldpa = NULL, *newpa = NULL;
2056 		struct pf_ruleset	*ruleset;
2057 
2058 		if (pca->action < PF_CHANGE_ADD_HEAD ||
2059 		    pca->action > PF_CHANGE_REMOVE) {
2060 			error = EINVAL;
2061 			break;
2062 		}
2063 		if (pca->addr.addr.type != PF_ADDR_ADDRMASK &&
2064 		    pca->addr.addr.type != PF_ADDR_DYNIFTL &&
2065 		    pca->addr.addr.type != PF_ADDR_TABLE) {
2066 			error = EINVAL;
2067 			break;
2068 		}
2069 
2070 		ruleset = pf_find_ruleset(pca->anchor);
2071 		if (ruleset == NULL) {
2072 			error = EBUSY;
2073 			break;
2074 		}
2075 		pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action,
2076 		    pca->r_num, pca->r_last, 1, 1);
2077 		if (pool == NULL) {
2078 			error = EBUSY;
2079 			break;
2080 		}
2081 		if (pca->action != PF_CHANGE_REMOVE) {
2082 			newpa = pool_get(&pf_pooladdr_pl,
2083 			    PR_WAITOK|PR_LIMITFAIL);
2084 			if (newpa == NULL) {
2085 				error = ENOMEM;
2086 				break;
2087 			}
2088 			bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr));
2089 #ifndef INET
2090 			if (pca->af == AF_INET) {
2091 				pool_put(&pf_pooladdr_pl, newpa);
2092 				error = EAFNOSUPPORT;
2093 				break;
2094 			}
2095 #endif /* INET */
2096 #ifndef INET6
2097 			if (pca->af == AF_INET6) {
2098 				pool_put(&pf_pooladdr_pl, newpa);
2099 				error = EAFNOSUPPORT;
2100 				break;
2101 			}
2102 #endif /* INET6 */
2103 			if (newpa->ifname[0]) {
2104 				newpa->kif = pfi_kif_get(newpa->ifname);
2105 				if (newpa->kif == NULL) {
2106 					pool_put(&pf_pooladdr_pl, newpa);
2107 					error = EINVAL;
2108 					break;
2109 				}
2110 				pfi_kif_ref(newpa->kif, PFI_KIF_REF_RULE);
2111 			} else
2112 				newpa->kif = NULL;
2113 			if (pfi_dynaddr_setup(&newpa->addr, pca->af) ||
2114 			    pf_tbladdr_setup(ruleset, &newpa->addr)) {
2115 				pfi_dynaddr_remove(&newpa->addr);
2116 				pfi_kif_unref(newpa->kif, PFI_KIF_REF_RULE);
2117 				pool_put(&pf_pooladdr_pl, newpa);
2118 				error = EINVAL;
2119 				break;
2120 			}
2121 		}
2122 
2123 		if (pca->action == PF_CHANGE_ADD_HEAD)
2124 			oldpa = TAILQ_FIRST(&pool->list);
2125 		else if (pca->action == PF_CHANGE_ADD_TAIL)
2126 			oldpa = TAILQ_LAST(&pool->list, pf_palist);
2127 		else {
2128 			int	i = 0;
2129 
2130 			oldpa = TAILQ_FIRST(&pool->list);
2131 			while ((oldpa != NULL) && (i < pca->nr)) {
2132 				oldpa = TAILQ_NEXT(oldpa, entries);
2133 				i++;
2134 			}
2135 			if (oldpa == NULL) {
2136 				error = EINVAL;
2137 				break;
2138 			}
2139 		}
2140 
2141 		if (pca->action == PF_CHANGE_REMOVE) {
2142 			TAILQ_REMOVE(&pool->list, oldpa, entries);
2143 			pfi_dynaddr_remove(&oldpa->addr);
2144 			pf_tbladdr_remove(&oldpa->addr);
2145 			pfi_kif_unref(oldpa->kif, PFI_KIF_REF_RULE);
2146 			pool_put(&pf_pooladdr_pl, oldpa);
2147 		} else {
2148 			if (oldpa == NULL)
2149 				TAILQ_INSERT_TAIL(&pool->list, newpa, entries);
2150 			else if (pca->action == PF_CHANGE_ADD_HEAD ||
2151 			    pca->action == PF_CHANGE_ADD_BEFORE)
2152 				TAILQ_INSERT_BEFORE(oldpa, newpa, entries);
2153 			else
2154 				TAILQ_INSERT_AFTER(&pool->list, oldpa,
2155 				    newpa, entries);
2156 		}
2157 
2158 		pool->cur = TAILQ_FIRST(&pool->list);
2159 		PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr,
2160 		    pca->af);
2161 		break;
2162 	}
2163 
2164 	case DIOCGETRULESETS: {
2165 		struct pfioc_ruleset	*pr = (struct pfioc_ruleset *)addr;
2166 		struct pf_ruleset	*ruleset;
2167 		struct pf_anchor	*anchor;
2168 
2169 		pr->path[sizeof(pr->path) - 1] = 0;
2170 		if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
2171 			error = EINVAL;
2172 			break;
2173 		}
2174 		pr->nr = 0;
2175 		if (ruleset->anchor == NULL) {
2176 			/* XXX kludge for pf_main_ruleset */
2177 			RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
2178 				if (anchor->parent == NULL)
2179 					pr->nr++;
2180 		} else {
2181 			RB_FOREACH(anchor, pf_anchor_node,
2182 			    &ruleset->anchor->children)
2183 				pr->nr++;
2184 		}
2185 		break;
2186 	}
2187 
2188 	case DIOCGETRULESET: {
2189 		struct pfioc_ruleset	*pr = (struct pfioc_ruleset *)addr;
2190 		struct pf_ruleset	*ruleset;
2191 		struct pf_anchor	*anchor;
2192 		u_int32_t		 nr = 0;
2193 
2194 		pr->path[sizeof(pr->path) - 1] = 0;
2195 		if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
2196 			error = EINVAL;
2197 			break;
2198 		}
2199 		pr->name[0] = 0;
2200 		if (ruleset->anchor == NULL) {
2201 			/* XXX kludge for pf_main_ruleset */
2202 			RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
2203 				if (anchor->parent == NULL && nr++ == pr->nr) {
2204 					strlcpy(pr->name, anchor->name,
2205 					    sizeof(pr->name));
2206 					break;
2207 				}
2208 		} else {
2209 			RB_FOREACH(anchor, pf_anchor_node,
2210 			    &ruleset->anchor->children)
2211 				if (nr++ == pr->nr) {
2212 					strlcpy(pr->name, anchor->name,
2213 					    sizeof(pr->name));
2214 					break;
2215 				}
2216 		}
2217 		if (!pr->name[0])
2218 			error = EBUSY;
2219 		break;
2220 	}
2221 
2222 	case DIOCRCLRTABLES: {
2223 		struct pfioc_table *io = (struct pfioc_table *)addr;
2224 
2225 		if (io->pfrio_esize != 0) {
2226 			error = ENODEV;
2227 			break;
2228 		}
2229 		error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
2230 		    io->pfrio_flags | PFR_FLAG_USERIOCTL);
2231 		break;
2232 	}
2233 
2234 	case DIOCRADDTABLES: {
2235 		struct pfioc_table *io = (struct pfioc_table *)addr;
2236 
2237 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
2238 			error = ENODEV;
2239 			break;
2240 		}
2241 		error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size,
2242 		    &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2243 		break;
2244 	}
2245 
2246 	case DIOCRDELTABLES: {
2247 		struct pfioc_table *io = (struct pfioc_table *)addr;
2248 
2249 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
2250 			error = ENODEV;
2251 			break;
2252 		}
2253 		error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size,
2254 		    &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2255 		break;
2256 	}
2257 
2258 	case DIOCRGETTABLES: {
2259 		struct pfioc_table *io = (struct pfioc_table *)addr;
2260 
2261 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
2262 			error = ENODEV;
2263 			break;
2264 		}
2265 		error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer,
2266 		    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2267 		break;
2268 	}
2269 
2270 	case DIOCRGETTSTATS: {
2271 		struct pfioc_table *io = (struct pfioc_table *)addr;
2272 
2273 		if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
2274 			error = ENODEV;
2275 			break;
2276 		}
2277 		error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer,
2278 		    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2279 		break;
2280 	}
2281 
2282 	case DIOCRCLRTSTATS: {
2283 		struct pfioc_table *io = (struct pfioc_table *)addr;
2284 
2285 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
2286 			error = ENODEV;
2287 			break;
2288 		}
2289 		error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size,
2290 		    &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2291 		break;
2292 	}
2293 
2294 	case DIOCRSETTFLAGS: {
2295 		struct pfioc_table *io = (struct pfioc_table *)addr;
2296 
2297 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
2298 			error = ENODEV;
2299 			break;
2300 		}
2301 		error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size,
2302 		    io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
2303 		    &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2304 		break;
2305 	}
2306 
2307 	case DIOCRCLRADDRS: {
2308 		struct pfioc_table *io = (struct pfioc_table *)addr;
2309 
2310 		if (io->pfrio_esize != 0) {
2311 			error = ENODEV;
2312 			break;
2313 		}
2314 		error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
2315 		    io->pfrio_flags | PFR_FLAG_USERIOCTL);
2316 		break;
2317 	}
2318 
2319 	case DIOCRADDADDRS: {
2320 		struct pfioc_table *io = (struct pfioc_table *)addr;
2321 
2322 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2323 			error = ENODEV;
2324 			break;
2325 		}
2326 		error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer,
2327 		    io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
2328 		    PFR_FLAG_USERIOCTL);
2329 		break;
2330 	}
2331 
2332 	case DIOCRDELADDRS: {
2333 		struct pfioc_table *io = (struct pfioc_table *)addr;
2334 
2335 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2336 			error = ENODEV;
2337 			break;
2338 		}
2339 		error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer,
2340 		    io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
2341 		    PFR_FLAG_USERIOCTL);
2342 		break;
2343 	}
2344 
2345 	case DIOCRSETADDRS: {
2346 		struct pfioc_table *io = (struct pfioc_table *)addr;
2347 
2348 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2349 			error = ENODEV;
2350 			break;
2351 		}
2352 		error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer,
2353 		    io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
2354 		    &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
2355 		    PFR_FLAG_USERIOCTL, 0);
2356 		break;
2357 	}
2358 
2359 	case DIOCRGETADDRS: {
2360 		struct pfioc_table *io = (struct pfioc_table *)addr;
2361 
2362 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2363 			error = ENODEV;
2364 			break;
2365 		}
2366 		error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer,
2367 		    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2368 		break;
2369 	}
2370 
2371 	case DIOCRGETASTATS: {
2372 		struct pfioc_table *io = (struct pfioc_table *)addr;
2373 
2374 		if (io->pfrio_esize != sizeof(struct pfr_astats)) {
2375 			error = ENODEV;
2376 			break;
2377 		}
2378 		error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer,
2379 		    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2380 		break;
2381 	}
2382 
2383 	case DIOCRCLRASTATS: {
2384 		struct pfioc_table *io = (struct pfioc_table *)addr;
2385 
2386 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2387 			error = ENODEV;
2388 			break;
2389 		}
2390 		error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer,
2391 		    io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
2392 		    PFR_FLAG_USERIOCTL);
2393 		break;
2394 	}
2395 
2396 	case DIOCRTSTADDRS: {
2397 		struct pfioc_table *io = (struct pfioc_table *)addr;
2398 
2399 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2400 			error = ENODEV;
2401 			break;
2402 		}
2403 		error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer,
2404 		    io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
2405 		    PFR_FLAG_USERIOCTL);
2406 		break;
2407 	}
2408 
2409 	case DIOCRINADEFINE: {
2410 		struct pfioc_table *io = (struct pfioc_table *)addr;
2411 
2412 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
2413 			error = ENODEV;
2414 			break;
2415 		}
2416 		error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer,
2417 		    io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
2418 		    io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
2419 		break;
2420 	}
2421 
2422 	case DIOCOSFPADD: {
2423 		struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
2424 		error = pf_osfp_add(io);
2425 		break;
2426 	}
2427 
2428 	case DIOCOSFPGET: {
2429 		struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
2430 		error = pf_osfp_get(io);
2431 		break;
2432 	}
2433 
2434 	case DIOCXBEGIN: {
2435 		struct pfioc_trans	*io = (struct pfioc_trans *)addr;
2436 		struct pfioc_trans_e	*ioe;
2437 		struct pfr_table	*table;
2438 		int			 i;
2439 
2440 		if (io->esize != sizeof(*ioe)) {
2441 			error = ENODEV;
2442 			goto fail;
2443 		}
2444 		ioe = malloc(sizeof(*ioe), M_TEMP, M_WAITOK);
2445 		table = malloc(sizeof(*table), M_TEMP, M_WAITOK);
2446 		for (i = 0; i < io->size; i++) {
2447 			if (copyin(io->array+i, ioe, sizeof(*ioe))) {
2448 				free(table, M_TEMP);
2449 				free(ioe, M_TEMP);
2450 				error = EFAULT;
2451 				goto fail;
2452 			}
2453 			switch (ioe->rs_num) {
2454 #ifdef ALTQ
2455 			case PF_RULESET_ALTQ:
2456 				if (ioe->anchor[0]) {
2457 					free(table, M_TEMP);
2458 					free(ioe, M_TEMP);
2459 					error = EINVAL;
2460 					goto fail;
2461 				}
2462 				if ((error = pf_begin_altq(&ioe->ticket))) {
2463 					free(table, M_TEMP);
2464 					free(ioe, M_TEMP);
2465 					goto fail;
2466 				}
2467 				break;
2468 #endif /* ALTQ */
2469 			case PF_RULESET_TABLE:
2470 				bzero(table, sizeof(*table));
2471 				strlcpy(table->pfrt_anchor, ioe->anchor,
2472 				    sizeof(table->pfrt_anchor));
2473 				if ((error = pfr_ina_begin(table,
2474 				    &ioe->ticket, NULL, 0))) {
2475 					free(table, M_TEMP);
2476 					free(ioe, M_TEMP);
2477 					goto fail;
2478 				}
2479 				break;
2480 			default:
2481 				if ((error = pf_begin_rules(&ioe->ticket,
2482 				    ioe->rs_num, ioe->anchor))) {
2483 					free(table, M_TEMP);
2484 					free(ioe, M_TEMP);
2485 					goto fail;
2486 				}
2487 				break;
2488 			}
2489 			if (copyout(ioe, io->array+i, sizeof(io->array[i]))) {
2490 				free(table, M_TEMP);
2491 				free(ioe, M_TEMP);
2492 				error = EFAULT;
2493 				goto fail;
2494 			}
2495 		}
2496 		free(table, M_TEMP);
2497 		free(ioe, M_TEMP);
2498 		break;
2499 	}
2500 
2501 	case DIOCXROLLBACK: {
2502 		struct pfioc_trans	*io = (struct pfioc_trans *)addr;
2503 		struct pfioc_trans_e	*ioe;
2504 		struct pfr_table	*table;
2505 		int			 i;
2506 
2507 		if (io->esize != sizeof(*ioe)) {
2508 			error = ENODEV;
2509 			goto fail;
2510 		}
2511 		ioe = malloc(sizeof(*ioe), M_TEMP, M_WAITOK);
2512 		table = malloc(sizeof(*table), M_TEMP, M_WAITOK);
2513 		for (i = 0; i < io->size; i++) {
2514 			if (copyin(io->array+i, ioe, sizeof(*ioe))) {
2515 				free(table, M_TEMP);
2516 				free(ioe, M_TEMP);
2517 				error = EFAULT;
2518 				goto fail;
2519 			}
2520 			switch (ioe->rs_num) {
2521 #ifdef ALTQ
2522 			case PF_RULESET_ALTQ:
2523 				if (ioe->anchor[0]) {
2524 					free(table, M_TEMP);
2525 					free(ioe, M_TEMP);
2526 					error = EINVAL;
2527 					goto fail;
2528 				}
2529 				if ((error = pf_rollback_altq(ioe->ticket))) {
2530 					free(table, M_TEMP);
2531 					free(ioe, M_TEMP);
2532 					goto fail; /* really bad */
2533 				}
2534 				break;
2535 #endif /* ALTQ */
2536 			case PF_RULESET_TABLE:
2537 				bzero(table, sizeof(*table));
2538 				strlcpy(table->pfrt_anchor, ioe->anchor,
2539 				    sizeof(table->pfrt_anchor));
2540 				if ((error = pfr_ina_rollback(table,
2541 				    ioe->ticket, NULL, 0))) {
2542 					free(table, M_TEMP);
2543 					free(ioe, M_TEMP);
2544 					goto fail; /* really bad */
2545 				}
2546 				break;
2547 			default:
2548 				if ((error = pf_rollback_rules(ioe->ticket,
2549 				    ioe->rs_num, ioe->anchor))) {
2550 					free(table, M_TEMP);
2551 					free(ioe, M_TEMP);
2552 					goto fail; /* really bad */
2553 				}
2554 				break;
2555 			}
2556 		}
2557 		free(table, M_TEMP);
2558 		free(ioe, M_TEMP);
2559 		break;
2560 	}
2561 
2562 	case DIOCXCOMMIT: {
2563 		struct pfioc_trans	*io = (struct pfioc_trans *)addr;
2564 		struct pfioc_trans_e	*ioe;
2565 		struct pfr_table	*table;
2566 		struct pf_ruleset	*rs;
2567 		int			 i;
2568 
2569 		if (io->esize != sizeof(*ioe)) {
2570 			error = ENODEV;
2571 			goto fail;
2572 		}
2573 		ioe = malloc(sizeof(*ioe), M_TEMP, M_WAITOK);
2574 		table = malloc(sizeof(*table), M_TEMP, M_WAITOK);
2575 		/* first makes sure everything will succeed */
2576 		for (i = 0; i < io->size; i++) {
2577 			if (copyin(io->array+i, ioe, sizeof(*ioe))) {
2578 				free(table, M_TEMP);
2579 				free(ioe, M_TEMP);
2580 				error = EFAULT;
2581 				goto fail;
2582 			}
2583 			switch (ioe->rs_num) {
2584 #ifdef ALTQ
2585 			case PF_RULESET_ALTQ:
2586 				if (ioe->anchor[0]) {
2587 					free(table, M_TEMP);
2588 					free(ioe, M_TEMP);
2589 					error = EINVAL;
2590 					goto fail;
2591 				}
2592 				if (!altqs_inactive_open || ioe->ticket !=
2593 				    ticket_altqs_inactive) {
2594 					free(table, M_TEMP);
2595 					free(ioe, M_TEMP);
2596 					error = EBUSY;
2597 					goto fail;
2598 				}
2599 				break;
2600 #endif /* ALTQ */
2601 			case PF_RULESET_TABLE:
2602 				rs = pf_find_ruleset(ioe->anchor);
2603 				if (rs == NULL || !rs->topen || ioe->ticket !=
2604 				     rs->tticket) {
2605 					free(table, M_TEMP);
2606 					free(ioe, M_TEMP);
2607 					error = EBUSY;
2608 					goto fail;
2609 				}
2610 				break;
2611 			default:
2612 				if (ioe->rs_num < 0 || ioe->rs_num >=
2613 				    PF_RULESET_MAX) {
2614 					free(table, M_TEMP);
2615 					free(ioe, M_TEMP);
2616 					error = EINVAL;
2617 					goto fail;
2618 				}
2619 				rs = pf_find_ruleset(ioe->anchor);
2620 				if (rs == NULL ||
2621 				    !rs->rules[ioe->rs_num].inactive.open ||
2622 				    rs->rules[ioe->rs_num].inactive.ticket !=
2623 				    ioe->ticket) {
2624 					free(table, M_TEMP);
2625 					free(ioe, M_TEMP);
2626 					error = EBUSY;
2627 					goto fail;
2628 				}
2629 				break;
2630 			}
2631 		}
2632 		/* now do the commit - no errors should happen here */
2633 		for (i = 0; i < io->size; i++) {
2634 			if (copyin(io->array+i, ioe, sizeof(*ioe))) {
2635 				free(table, M_TEMP);
2636 				free(ioe, M_TEMP);
2637 				error = EFAULT;
2638 				goto fail;
2639 			}
2640 			switch (ioe->rs_num) {
2641 #ifdef ALTQ
2642 			case PF_RULESET_ALTQ:
2643 				if ((error = pf_commit_altq(ioe->ticket))) {
2644 					free(table, M_TEMP);
2645 					free(ioe, M_TEMP);
2646 					goto fail; /* really bad */
2647 				}
2648 				break;
2649 #endif /* ALTQ */
2650 			case PF_RULESET_TABLE:
2651 				bzero(table, sizeof(*table));
2652 				strlcpy(table->pfrt_anchor, ioe->anchor,
2653 				    sizeof(table->pfrt_anchor));
2654 				if ((error = pfr_ina_commit(table, ioe->ticket,
2655 				    NULL, NULL, 0))) {
2656 					free(table, M_TEMP);
2657 					free(ioe, M_TEMP);
2658 					goto fail; /* really bad */
2659 				}
2660 				break;
2661 			default:
2662 				if ((error = pf_commit_rules(ioe->ticket,
2663 				    ioe->rs_num, ioe->anchor))) {
2664 					free(table, M_TEMP);
2665 					free(ioe, M_TEMP);
2666 					goto fail; /* really bad */
2667 				}
2668 				break;
2669 			}
2670 		}
2671 		free(table, M_TEMP);
2672 		free(ioe, M_TEMP);
2673 		break;
2674 	}
2675 
2676 	case DIOCGETSRCNODES: {
2677 		struct pfioc_src_nodes	*psn = (struct pfioc_src_nodes *)addr;
2678 		struct pf_src_node	*n, *p, *pstore;
2679 		u_int32_t		 nr = 0;
2680 		int			 space = psn->psn_len;
2681 
2682 		if (space == 0) {
2683 			RB_FOREACH(n, pf_src_tree, &tree_src_tracking)
2684 				nr++;
2685 			psn->psn_len = sizeof(struct pf_src_node) * nr;
2686 			break;
2687 		}
2688 
2689 		pstore = malloc(sizeof(*pstore), M_TEMP, M_WAITOK);
2690 
2691 		p = psn->psn_src_nodes;
2692 		RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
2693 			int	secs = time_second, diff;
2694 
2695 			if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
2696 				break;
2697 
2698 			bcopy(n, pstore, sizeof(*pstore));
2699 			if (n->rule.ptr != NULL)
2700 				pstore->rule.nr = n->rule.ptr->nr;
2701 			pstore->creation = secs - pstore->creation;
2702 			if (pstore->expire > secs)
2703 				pstore->expire -= secs;
2704 			else
2705 				pstore->expire = 0;
2706 
2707 			/* adjust the connection rate estimate */
2708 			diff = secs - n->conn_rate.last;
2709 			if (diff >= n->conn_rate.seconds)
2710 				pstore->conn_rate.count = 0;
2711 			else
2712 				pstore->conn_rate.count -=
2713 				    n->conn_rate.count * diff /
2714 				    n->conn_rate.seconds;
2715 
2716 			error = copyout(pstore, p, sizeof(*p));
2717 			if (error) {
2718 				free(pstore, M_TEMP);
2719 				goto fail;
2720 			}
2721 			p++;
2722 			nr++;
2723 		}
2724 		psn->psn_len = sizeof(struct pf_src_node) * nr;
2725 
2726 		free(pstore, M_TEMP);
2727 		break;
2728 	}
2729 
2730 	case DIOCCLRSRCNODES: {
2731 		struct pf_src_node	*n;
2732 		struct pf_state		*state;
2733 
2734 		RB_FOREACH(state, pf_state_tree_id, &tree_id) {
2735 			state->src_node = NULL;
2736 			state->nat_src_node = NULL;
2737 		}
2738 		RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
2739 			n->expire = 1;
2740 			n->states = 0;
2741 		}
2742 		pf_purge_expired_src_nodes(1);
2743 		pf_status.src_nodes = 0;
2744 		break;
2745 	}
2746 
2747 	case DIOCKILLSRCNODES: {
2748 		struct pf_src_node	*sn;
2749 		struct pf_state		*s;
2750 		struct pfioc_src_node_kill *psnk =
2751 		    (struct pfioc_src_node_kill *)addr;
2752 		u_int			killed = 0;
2753 
2754 		RB_FOREACH(sn, pf_src_tree, &tree_src_tracking) {
2755 			if (PF_MATCHA(psnk->psnk_src.neg,
2756 				&psnk->psnk_src.addr.v.a.addr,
2757 				&psnk->psnk_src.addr.v.a.mask,
2758 				&sn->addr, sn->af) &&
2759 			    PF_MATCHA(psnk->psnk_dst.neg,
2760 				&psnk->psnk_dst.addr.v.a.addr,
2761 				&psnk->psnk_dst.addr.v.a.mask,
2762 				&sn->raddr, sn->af)) {
2763 				/* Handle state to src_node linkage */
2764 				if (sn->states != 0) {
2765 					RB_FOREACH(s, pf_state_tree_id,
2766 					    &tree_id) {
2767 						if (s->src_node == sn)
2768 							s->src_node = NULL;
2769 						if (s->nat_src_node == sn)
2770 							s->nat_src_node = NULL;
2771 					}
2772 					sn->states = 0;
2773 				}
2774 				sn->expire = 1;
2775 				killed++;
2776 			}
2777 		}
2778 
2779 		if (killed > 0)
2780 			pf_purge_expired_src_nodes(1);
2781 
2782 		psnk->psnk_killed = killed;
2783 		break;
2784 	}
2785 
2786 	case DIOCSETHOSTID: {
2787 		u_int32_t	*hostid = (u_int32_t *)addr;
2788 
2789 		if (*hostid == 0)
2790 			pf_status.hostid = arc4random();
2791 		else
2792 			pf_status.hostid = *hostid;
2793 		break;
2794 	}
2795 
2796 	case DIOCOSFPFLUSH:
2797 		pf_osfp_flush();
2798 		break;
2799 
2800 	case DIOCIGETIFACES: {
2801 		struct pfioc_iface *io = (struct pfioc_iface *)addr;
2802 
2803 		if (io->pfiio_esize != sizeof(struct pfi_kif)) {
2804 			error = ENODEV;
2805 			break;
2806 		}
2807 		error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer,
2808 		    &io->pfiio_size);
2809 		break;
2810 	}
2811 
2812 	case DIOCSETIFFLAG: {
2813 		struct pfioc_iface *io = (struct pfioc_iface *)addr;
2814 
2815 		error = pfi_set_flags(io->pfiio_name, io->pfiio_flags);
2816 		break;
2817 	}
2818 
2819 	case DIOCCLRIFFLAG: {
2820 		struct pfioc_iface *io = (struct pfioc_iface *)addr;
2821 
2822 		error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags);
2823 		break;
2824 	}
2825 
2826 	default:
2827 		error = ENODEV;
2828 		break;
2829 	}
2830 fail:
2831 	splx(s);
2832 	if (flags & FWRITE)
2833 		rw_exit_write(&pf_consistency_lock);
2834 	else
2835 		rw_exit_read(&pf_consistency_lock);
2836 	return (error);
2837 }
2838