Home | History | Annotate | Line # | Download | only in net
pf_ioctl.c revision 1.21.12.1
      1  1.21.12.1     peter /*	$NetBSD: pf_ioctl.c,v 1.21.12.1 2006/03/18 14:07:52 peter Exp $	*/
      2       1.17     peter /*	$OpenBSD: pf_ioctl.c,v 1.139 2005/03/03 07:13:39 dhartmei Exp $ */
      3        1.1    itojun 
      4        1.1    itojun /*
      5        1.1    itojun  * Copyright (c) 2001 Daniel Hartmeier
      6        1.1    itojun  * Copyright (c) 2002,2003 Henning Brauer
      7        1.1    itojun  * All rights reserved.
      8        1.1    itojun  *
      9        1.1    itojun  * Redistribution and use in source and binary forms, with or without
     10        1.1    itojun  * modification, are permitted provided that the following conditions
     11        1.1    itojun  * are met:
     12        1.1    itojun  *
     13        1.1    itojun  *    - Redistributions of source code must retain the above copyright
     14        1.1    itojun  *      notice, this list of conditions and the following disclaimer.
     15        1.1    itojun  *    - Redistributions in binary form must reproduce the above
     16        1.1    itojun  *      copyright notice, this list of conditions and the following
     17        1.1    itojun  *      disclaimer in the documentation and/or other materials provided
     18        1.1    itojun  *      with the distribution.
     19        1.1    itojun  *
     20        1.1    itojun  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21        1.1    itojun  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     22        1.1    itojun  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     23        1.1    itojun  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     24        1.1    itojun  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     25        1.1    itojun  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     26        1.1    itojun  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     27        1.1    itojun  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     28        1.1    itojun  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29        1.1    itojun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     30        1.1    itojun  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31        1.1    itojun  * POSSIBILITY OF SUCH DAMAGE.
     32        1.1    itojun  *
     33        1.1    itojun  * Effort sponsored in part by the Defense Advanced Research Projects
     34        1.1    itojun  * Agency (DARPA) and Air Force Research Laboratory, Air Force
     35        1.1    itojun  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
     36        1.1    itojun  *
     37        1.1    itojun  */
     38        1.1    itojun 
     39        1.2    itojun #ifdef _KERNEL_OPT
     40        1.2    itojun #include "opt_inet.h"
     41        1.2    itojun #include "opt_altq.h"
     42        1.2    itojun #include "opt_pfil_hooks.h"
     43        1.2    itojun #endif
     44        1.2    itojun 
     45        1.2    itojun #ifdef __OpenBSD__
     46        1.1    itojun #include "pfsync.h"
     47        1.2    itojun #else
     48        1.2    itojun #define	NPFSYNC	0
     49        1.2    itojun #endif
     50        1.1    itojun 
     51        1.1    itojun #include <sys/param.h>
     52        1.1    itojun #include <sys/systm.h>
     53        1.1    itojun #include <sys/mbuf.h>
     54        1.1    itojun #include <sys/filio.h>
     55        1.1    itojun #include <sys/fcntl.h>
     56        1.1    itojun #include <sys/socket.h>
     57        1.1    itojun #include <sys/socketvar.h>
     58        1.1    itojun #include <sys/kernel.h>
     59        1.1    itojun #include <sys/time.h>
     60        1.2    itojun #ifdef __OpenBSD__
     61        1.1    itojun #include <sys/timeout.h>
     62        1.2    itojun #else
     63        1.2    itojun #include <sys/callout.h>
     64        1.2    itojun #endif
     65        1.1    itojun #include <sys/pool.h>
     66        1.1    itojun #include <sys/malloc.h>
     67        1.2    itojun #ifdef __NetBSD__
     68        1.2    itojun #include <sys/conf.h>
     69        1.2    itojun #endif
     70        1.1    itojun 
     71        1.1    itojun #include <net/if.h>
     72        1.1    itojun #include <net/if_types.h>
     73        1.1    itojun #include <net/route.h>
     74        1.1    itojun 
     75        1.1    itojun #include <netinet/in.h>
     76        1.1    itojun #include <netinet/in_var.h>
     77        1.1    itojun #include <netinet/in_systm.h>
     78        1.1    itojun #include <netinet/ip.h>
     79        1.1    itojun #include <netinet/ip_var.h>
     80        1.1    itojun #include <netinet/ip_icmp.h>
     81        1.1    itojun 
     82        1.2    itojun #ifdef __OpenBSD__
     83        1.1    itojun #include <dev/rndvar.h>
     84        1.2    itojun #endif
     85        1.1    itojun #include <net/pfvar.h>
     86        1.1    itojun 
     87        1.1    itojun #if NPFSYNC > 0
     88        1.1    itojun #include <net/if_pfsync.h>
     89        1.1    itojun #endif /* NPFSYNC > 0 */
     90        1.1    itojun 
     91        1.1    itojun #ifdef INET6
     92        1.1    itojun #include <netinet/ip6.h>
     93        1.1    itojun #include <netinet/in_pcb.h>
     94        1.1    itojun #endif /* INET6 */
     95        1.1    itojun 
     96        1.1    itojun #ifdef ALTQ
     97        1.1    itojun #include <altq/altq.h>
     98        1.1    itojun #endif
     99        1.1    itojun 
    100        1.1    itojun void			 pfattach(int);
    101        1.6    itojun #ifdef _LKM
    102        1.6    itojun void			 pfdetach(void);
    103        1.6    itojun #endif
    104       1.21  christos int			 pfopen(dev_t, int, int, struct lwp *);
    105       1.21  christos int			 pfclose(dev_t, int, int, struct lwp *);
    106       1.12      yamt struct pf_pool		*pf_get_pool(char *, u_int32_t, u_int8_t, u_int32_t,
    107       1.12      yamt 			    u_int8_t, u_int8_t, u_int8_t);
    108        1.1    itojun int			 pf_get_ruleset_number(u_int8_t);
    109        1.1    itojun void			 pf_init_ruleset(struct pf_ruleset *);
    110       1.12      yamt int			 pf_anchor_setup(struct pf_rule *,
    111       1.12      yamt 			    const struct pf_ruleset *, const char *);
    112       1.12      yamt int			 pf_anchor_copyout(const struct pf_ruleset *,
    113       1.12      yamt 			    const struct pf_rule *, struct pfioc_rule *);
    114       1.12      yamt void			 pf_anchor_remove(struct pf_rule *);
    115       1.12      yamt 
    116        1.1    itojun void			 pf_mv_pool(struct pf_palist *, struct pf_palist *);
    117        1.1    itojun void			 pf_empty_pool(struct pf_palist *);
    118       1.21  christos int			 pfioctl(dev_t, u_long, caddr_t, int, struct lwp *);
    119        1.1    itojun #ifdef ALTQ
    120        1.1    itojun int			 pf_begin_altq(u_int32_t *);
    121        1.1    itojun int			 pf_rollback_altq(u_int32_t);
    122        1.1    itojun int			 pf_commit_altq(u_int32_t);
    123       1.12      yamt int			 pf_enable_altq(struct pf_altq *);
    124       1.12      yamt int			 pf_disable_altq(struct pf_altq *);
    125        1.1    itojun #endif /* ALTQ */
    126       1.12      yamt int			 pf_begin_rules(u_int32_t *, int, const char *);
    127       1.12      yamt int			 pf_rollback_rules(u_int32_t, int, char *);
    128       1.12      yamt int			 pf_commit_rules(u_int32_t, int, char *);
    129        1.1    itojun 
    130        1.2    itojun #ifdef __NetBSD__
    131        1.2    itojun const struct cdevsw pf_cdevsw = {
    132        1.2    itojun 	pfopen, pfclose, noread, nowrite, pfioctl,
    133        1.2    itojun 	nostop, notty, nopoll, nommap, nokqfilter,
    134        1.2    itojun };
    135        1.2    itojun 
    136        1.2    itojun static int pf_pfil_attach(void);
    137        1.2    itojun static int pf_pfil_detach(void);
    138        1.2    itojun 
    139        1.6    itojun static int pf_pfil_attached = 0;
    140        1.2    itojun #endif
    141        1.2    itojun 
    142        1.2    itojun #ifdef __OpenBSD__
    143        1.1    itojun extern struct timeout	 pf_expire_to;
    144        1.2    itojun #else
    145        1.2    itojun extern struct callout	 pf_expire_to;
    146        1.2    itojun #endif
    147        1.1    itojun 
    148        1.1    itojun struct pf_rule		 pf_default_rule;
    149       1.12      yamt #ifdef ALTQ
    150       1.12      yamt static int		 pf_altq_running;
    151       1.12      yamt #endif
    152        1.1    itojun 
    153        1.1    itojun #define	TAGID_MAX	 50000
    154        1.1    itojun TAILQ_HEAD(pf_tags, pf_tagname)	pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags),
    155        1.1    itojun 				pf_qids = TAILQ_HEAD_INITIALIZER(pf_qids);
    156        1.1    itojun 
    157        1.1    itojun #if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
    158        1.1    itojun #error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
    159        1.1    itojun #endif
    160        1.1    itojun static u_int16_t	 tagname2tag(struct pf_tags *, char *);
    161        1.1    itojun static void		 tag2tagname(struct pf_tags *, u_int16_t, char *);
    162        1.1    itojun static void		 tag_unref(struct pf_tags *, u_int16_t);
    163       1.17     peter int			 pf_rtlabel_add(struct pf_addr_wrap *);
    164       1.17     peter void			 pf_rtlabel_remove(struct pf_addr_wrap *);
    165       1.17     peter void			 pf_rtlabel_copyout(struct pf_addr_wrap *);
    166        1.1    itojun 
    167        1.1    itojun #define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
    168        1.1    itojun 
    169        1.2    itojun #ifdef __NetBSD__
    170        1.2    itojun extern struct pfil_head if_pfil;
    171        1.2    itojun #endif
    172        1.2    itojun 
    173        1.1    itojun void
    174        1.1    itojun pfattach(int num)
    175        1.1    itojun {
    176        1.1    itojun 	u_int32_t *timeout = pf_default_rule.timeout;
    177        1.1    itojun 
    178        1.1    itojun 	pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
    179        1.1    itojun 	    &pool_allocator_nointr);
    180        1.1    itojun 	pool_init(&pf_src_tree_pl, sizeof(struct pf_src_node), 0, 0, 0,
    181        1.1    itojun 	    "pfsrctrpl", NULL);
    182        1.1    itojun 	pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
    183        1.1    itojun 	    NULL);
    184        1.1    itojun 	pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl",
    185       1.12      yamt 	    &pool_allocator_nointr);
    186        1.1    itojun 	pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0,
    187       1.12      yamt 	    "pfpooladdrpl", &pool_allocator_nointr);
    188        1.1    itojun 	pfr_initialize();
    189        1.1    itojun 	pfi_initialize();
    190        1.1    itojun 	pf_osfp_initialize();
    191        1.1    itojun 
    192        1.1    itojun 	pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp,
    193        1.1    itojun 	    pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0);
    194        1.1    itojun 
    195        1.1    itojun 	RB_INIT(&tree_src_tracking);
    196       1.12      yamt 	RB_INIT(&pf_anchors);
    197        1.1    itojun 	pf_init_ruleset(&pf_main_ruleset);
    198        1.1    itojun 	TAILQ_INIT(&pf_altqs[0]);
    199        1.1    itojun 	TAILQ_INIT(&pf_altqs[1]);
    200        1.1    itojun 	TAILQ_INIT(&pf_pabuf);
    201        1.1    itojun 	pf_altqs_active = &pf_altqs[0];
    202        1.1    itojun 	pf_altqs_inactive = &pf_altqs[1];
    203        1.1    itojun 	TAILQ_INIT(&state_updates);
    204        1.1    itojun 
    205        1.1    itojun 	/* default rule should never be garbage collected */
    206        1.1    itojun 	pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
    207        1.1    itojun 	pf_default_rule.action = PF_PASS;
    208        1.1    itojun 	pf_default_rule.nr = -1;
    209        1.1    itojun 
    210        1.1    itojun 	/* initialize default timeouts */
    211       1.17     peter 	timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
    212       1.17     peter 	timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
    213       1.17     peter 	timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
    214       1.17     peter 	timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
    215       1.17     peter 	timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
    216       1.17     peter 	timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
    217       1.17     peter 	timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
    218       1.17     peter 	timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
    219       1.17     peter 	timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
    220       1.17     peter 	timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
    221       1.17     peter 	timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
    222       1.17     peter 	timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
    223       1.17     peter 	timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
    224       1.17     peter 	timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
    225       1.17     peter 	timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
    226       1.17     peter 	timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
    227       1.17     peter 	timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
    228       1.17     peter 	timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
    229        1.1    itojun 
    230        1.2    itojun #ifdef __OpenBSD__
    231        1.1    itojun 	timeout_set(&pf_expire_to, pf_purge_timeout, &pf_expire_to);
    232        1.1    itojun 	timeout_add(&pf_expire_to, timeout[PFTM_INTERVAL] * hz);
    233        1.2    itojun #else
    234        1.2    itojun 	callout_init(&pf_expire_to);
    235        1.2    itojun 	callout_reset(&pf_expire_to, timeout[PFTM_INTERVAL] * hz,
    236        1.2    itojun 	    pf_purge_timeout, &pf_expire_to);
    237        1.2    itojun #endif
    238        1.1    itojun 
    239        1.1    itojun 	pf_normalize_init();
    240        1.1    itojun 	bzero(&pf_status, sizeof(pf_status));
    241        1.1    itojun 	pf_status.debug = PF_DEBUG_URGENT;
    242        1.1    itojun 
    243        1.1    itojun 	/* XXX do our best to avoid a conflict */
    244        1.1    itojun 	pf_status.hostid = arc4random();
    245        1.1    itojun }
    246        1.1    itojun 
    247        1.6    itojun #ifdef _LKM
    248        1.6    itojun void
    249        1.6    itojun pfdetach(void)
    250        1.6    itojun {
    251       1.13     peter 	struct pf_anchor	*anchor;
    252       1.13     peter 	struct pf_state		*state;
    253       1.13     peter 	struct pf_src_node	*node;
    254       1.13     peter 	struct pfioc_table	 pt;
    255       1.13     peter 	u_int32_t		 ticket;
    256       1.13     peter 	int			 i;
    257       1.13     peter 	char			 r = '\0';
    258        1.6    itojun 
    259        1.6    itojun 	(void)pf_pfil_detach();
    260        1.6    itojun 
    261        1.6    itojun 	callout_stop(&pf_expire_to);
    262       1.13     peter 	pf_status.running = 0;
    263       1.13     peter 
    264       1.13     peter 	/* clear the rulesets */
    265       1.13     peter 	for (i = 0; i < PF_RULESET_MAX; i++)
    266       1.13     peter 		if (pf_begin_rules(&ticket, i, &r) == 0)
    267       1.13     peter 			pf_commit_rules(ticket, i, &r);
    268       1.13     peter #ifdef ALTQ
    269       1.13     peter 	if (pf_begin_altq(&ticket) == 0)
    270       1.13     peter 		pf_commit_altq(ticket);
    271       1.13     peter #endif
    272       1.13     peter 
    273       1.13     peter 	/* clear states */
    274       1.13     peter 	RB_FOREACH(state, pf_state_tree_id, &tree_id) {
    275       1.13     peter 		state->timeout = PFTM_PURGE;
    276       1.13     peter #if NPFSYNC
    277       1.13     peter 		state->sync_flags = PFSTATE_NOSYNC;
    278       1.13     peter #endif
    279       1.13     peter 	}
    280       1.13     peter 	pf_purge_expired_states();
    281       1.13     peter #if NPFSYNC
    282       1.13     peter 	pfsync_clear_states(pf_status.hostid, NULL);
    283       1.13     peter #endif
    284       1.13     peter 
    285       1.13     peter 	/* clear source nodes */
    286       1.13     peter 	RB_FOREACH(state, pf_state_tree_id, &tree_id) {
    287       1.13     peter 		state->src_node = NULL;
    288       1.13     peter 		state->nat_src_node = NULL;
    289       1.13     peter 	}
    290       1.13     peter 	RB_FOREACH(node, pf_src_tree, &tree_src_tracking) {
    291       1.13     peter 		node->expire = 1;
    292       1.13     peter 		node->states = 0;
    293       1.13     peter 	}
    294       1.13     peter 	pf_purge_expired_src_nodes();
    295       1.13     peter 
    296       1.13     peter 	/* clear tables */
    297       1.13     peter 	memset(&pt, '\0', sizeof(pt));
    298       1.13     peter 	pfr_clr_tables(&pt.pfrio_table, &pt.pfrio_ndel, pt.pfrio_flags);
    299        1.6    itojun 
    300       1.13     peter 	/* destroy anchors */
    301       1.13     peter 	while ((anchor = RB_MIN(pf_anchor_global, &pf_anchors)) != NULL) {
    302       1.13     peter 		for (i = 0; i < PF_RULESET_MAX; i++)
    303       1.13     peter 			if (pf_begin_rules(&ticket, i, anchor->name) == 0)
    304       1.13     peter 				pf_commit_rules(ticket, i, anchor->name);
    305       1.12      yamt 	}
    306       1.13     peter 
    307       1.13     peter 	/* destroy main ruleset */
    308       1.13     peter 	pf_remove_if_empty_ruleset(&pf_main_ruleset);
    309       1.13     peter 
    310       1.13     peter 	/* destroy the pools */
    311        1.6    itojun 	pool_destroy(&pf_pooladdr_pl);
    312        1.6    itojun 	pool_destroy(&pf_altq_pl);
    313        1.6    itojun 	pool_destroy(&pf_state_pl);
    314        1.6    itojun 	pool_destroy(&pf_rule_pl);
    315        1.6    itojun 	pool_destroy(&pf_src_tree_pl);
    316       1.13     peter 
    317       1.13     peter 	/* destroy subsystems */
    318       1.13     peter 	pf_normalize_destroy();
    319       1.13     peter 	pf_osfp_destroy();
    320       1.13     peter 	pfr_destroy();
    321       1.13     peter 	pfi_destroy();
    322        1.6    itojun }
    323        1.6    itojun #endif
    324        1.6    itojun 
    325        1.1    itojun int
    326       1.21  christos pfopen(dev_t dev, int flags, int fmt, struct lwp *l)
    327        1.1    itojun {
    328        1.1    itojun 	if (minor(dev) >= 1)
    329        1.1    itojun 		return (ENXIO);
    330        1.1    itojun 	return (0);
    331        1.1    itojun }
    332        1.1    itojun 
    333        1.1    itojun int
    334       1.21  christos pfclose(dev_t dev, int flags, int fmt, struct lwp *l)
    335        1.1    itojun {
    336        1.1    itojun 	if (minor(dev) >= 1)
    337        1.1    itojun 		return (ENXIO);
    338        1.1    itojun 	return (0);
    339        1.1    itojun }
    340        1.1    itojun 
    341        1.1    itojun struct pf_pool *
    342       1.12      yamt pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
    343       1.12      yamt     u_int32_t rule_number, u_int8_t r_last, u_int8_t active,
    344       1.12      yamt     u_int8_t check_ticket)
    345        1.1    itojun {
    346        1.1    itojun 	struct pf_ruleset	*ruleset;
    347        1.1    itojun 	struct pf_rule		*rule;
    348        1.1    itojun 	int			 rs_num;
    349        1.1    itojun 
    350       1.12      yamt 	ruleset = pf_find_ruleset(anchor);
    351        1.1    itojun 	if (ruleset == NULL)
    352        1.1    itojun 		return (NULL);
    353        1.1    itojun 	rs_num = pf_get_ruleset_number(rule_action);
    354        1.1    itojun 	if (rs_num >= PF_RULESET_MAX)
    355        1.1    itojun 		return (NULL);
    356        1.1    itojun 	if (active) {
    357        1.1    itojun 		if (check_ticket && ticket !=
    358        1.1    itojun 		    ruleset->rules[rs_num].active.ticket)
    359        1.1    itojun 			return (NULL);
    360        1.1    itojun 		if (r_last)
    361        1.1    itojun 			rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
    362        1.1    itojun 			    pf_rulequeue);
    363        1.1    itojun 		else
    364        1.1    itojun 			rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
    365        1.1    itojun 	} else {
    366        1.1    itojun 		if (check_ticket && ticket !=
    367        1.1    itojun 		    ruleset->rules[rs_num].inactive.ticket)
    368        1.1    itojun 			return (NULL);
    369        1.1    itojun 		if (r_last)
    370        1.1    itojun 			rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
    371        1.1    itojun 			    pf_rulequeue);
    372        1.1    itojun 		else
    373        1.1    itojun 			rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr);
    374        1.1    itojun 	}
    375        1.1    itojun 	if (!r_last) {
    376        1.1    itojun 		while ((rule != NULL) && (rule->nr != rule_number))
    377        1.1    itojun 			rule = TAILQ_NEXT(rule, entries);
    378        1.1    itojun 	}
    379        1.1    itojun 	if (rule == NULL)
    380        1.1    itojun 		return (NULL);
    381        1.1    itojun 
    382        1.1    itojun 	return (&rule->rpool);
    383        1.1    itojun }
    384        1.1    itojun 
    385        1.1    itojun int
    386        1.1    itojun pf_get_ruleset_number(u_int8_t action)
    387        1.1    itojun {
    388        1.1    itojun 	switch (action) {
    389        1.1    itojun 	case PF_SCRUB:
    390       1.17     peter 	case PF_NOSCRUB:
    391        1.1    itojun 		return (PF_RULESET_SCRUB);
    392        1.1    itojun 		break;
    393        1.1    itojun 	case PF_PASS:
    394        1.1    itojun 	case PF_DROP:
    395        1.1    itojun 		return (PF_RULESET_FILTER);
    396        1.1    itojun 		break;
    397        1.1    itojun 	case PF_NAT:
    398        1.1    itojun 	case PF_NONAT:
    399        1.1    itojun 		return (PF_RULESET_NAT);
    400        1.1    itojun 		break;
    401        1.1    itojun 	case PF_BINAT:
    402        1.1    itojun 	case PF_NOBINAT:
    403        1.1    itojun 		return (PF_RULESET_BINAT);
    404        1.1    itojun 		break;
    405        1.1    itojun 	case PF_RDR:
    406        1.1    itojun 	case PF_NORDR:
    407        1.1    itojun 		return (PF_RULESET_RDR);
    408        1.1    itojun 		break;
    409        1.1    itojun 	default:
    410        1.1    itojun 		return (PF_RULESET_MAX);
    411        1.1    itojun 		break;
    412        1.1    itojun 	}
    413        1.1    itojun }
    414        1.1    itojun 
    415        1.1    itojun void
    416        1.1    itojun pf_init_ruleset(struct pf_ruleset *ruleset)
    417        1.1    itojun {
    418        1.1    itojun 	int	i;
    419        1.1    itojun 
    420        1.1    itojun 	memset(ruleset, 0, sizeof(struct pf_ruleset));
    421        1.1    itojun 	for (i = 0; i < PF_RULESET_MAX; i++) {
    422        1.1    itojun 		TAILQ_INIT(&ruleset->rules[i].queues[0]);
    423        1.1    itojun 		TAILQ_INIT(&ruleset->rules[i].queues[1]);
    424        1.1    itojun 		ruleset->rules[i].active.ptr = &ruleset->rules[i].queues[0];
    425        1.1    itojun 		ruleset->rules[i].inactive.ptr = &ruleset->rules[i].queues[1];
    426        1.1    itojun 	}
    427        1.1    itojun }
    428        1.1    itojun 
    429        1.1    itojun struct pf_anchor *
    430       1.12      yamt pf_find_anchor(const char *path)
    431        1.1    itojun {
    432       1.12      yamt 	static struct pf_anchor	 key;
    433        1.1    itojun 
    434       1.12      yamt 	memset(&key, 0, sizeof(key));
    435       1.12      yamt 	strlcpy(key.path, path, sizeof(key.path));
    436       1.12      yamt 	return (RB_FIND(pf_anchor_global, &pf_anchors, &key));
    437        1.1    itojun }
    438        1.1    itojun 
    439        1.1    itojun struct pf_ruleset *
    440       1.12      yamt pf_find_ruleset(const char *path)
    441        1.1    itojun {
    442        1.1    itojun 	struct pf_anchor	*anchor;
    443        1.1    itojun 
    444       1.12      yamt 	while (*path == '/')
    445       1.12      yamt 		path++;
    446       1.12      yamt 	if (!*path)
    447        1.1    itojun 		return (&pf_main_ruleset);
    448       1.12      yamt 	anchor = pf_find_anchor(path);
    449        1.1    itojun 	if (anchor == NULL)
    450        1.1    itojun 		return (NULL);
    451        1.1    itojun 	else
    452       1.12      yamt 		return (&anchor->ruleset);
    453        1.1    itojun }
    454        1.1    itojun 
    455        1.1    itojun struct pf_ruleset *
    456       1.12      yamt pf_find_or_create_ruleset(const char *path)
    457        1.1    itojun {
    458       1.12      yamt 	static char		 p[MAXPATHLEN];
    459       1.16     peter 	char			*q = NULL /* XXX gcc */, *r;
    460       1.12      yamt 	struct pf_ruleset	*ruleset;
    461       1.12      yamt 	struct pf_anchor	*anchor = NULL /* XXX gcc */,
    462       1.12      yamt 				*dup, *parent = NULL;
    463        1.1    itojun 
    464       1.12      yamt 	while (*path == '/')
    465       1.12      yamt 		path++;
    466       1.12      yamt 	ruleset = pf_find_ruleset(path);
    467       1.12      yamt 	if (ruleset != NULL)
    468       1.12      yamt 		return (ruleset);
    469       1.12      yamt 	strlcpy(p, path, sizeof(p));
    470       1.12      yamt 	while (parent == NULL && (q = strrchr(p, '/')) != NULL) {
    471       1.12      yamt 		*q = 0;
    472       1.12      yamt 		if ((ruleset = pf_find_ruleset(p)) != NULL) {
    473       1.12      yamt 			parent = ruleset->anchor;
    474       1.12      yamt 			break;
    475       1.12      yamt 		}
    476       1.12      yamt 	}
    477       1.12      yamt 	if (q == NULL)
    478       1.12      yamt 		q = p;
    479       1.12      yamt 	else
    480       1.12      yamt 		q++;
    481       1.12      yamt 	strlcpy(p, path, sizeof(p));
    482       1.12      yamt 	if (!*q)
    483        1.1    itojun 		return (NULL);
    484       1.12      yamt 	while ((r = strchr(q, '/')) != NULL || *q) {
    485       1.12      yamt 		if (r != NULL)
    486       1.12      yamt 			*r = 0;
    487       1.12      yamt 		if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE ||
    488       1.12      yamt 		    (parent != NULL && strlen(parent->path) >=
    489       1.12      yamt 		    MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1))
    490       1.12      yamt 			return (NULL);
    491       1.12      yamt 		anchor = (struct pf_anchor *)malloc(sizeof(*anchor), M_TEMP,
    492       1.12      yamt 		    M_NOWAIT);
    493        1.1    itojun 		if (anchor == NULL)
    494        1.1    itojun 			return (NULL);
    495       1.12      yamt 		memset(anchor, 0, sizeof(*anchor));
    496       1.12      yamt 		RB_INIT(&anchor->children);
    497       1.12      yamt 		strlcpy(anchor->name, q, sizeof(anchor->name));
    498       1.12      yamt 		if (parent != NULL) {
    499       1.12      yamt 			strlcpy(anchor->path, parent->path,
    500       1.12      yamt 			    sizeof(anchor->path));
    501       1.12      yamt 			strlcat(anchor->path, "/", sizeof(anchor->path));
    502       1.12      yamt 		}
    503       1.12      yamt 		strlcat(anchor->path, anchor->name, sizeof(anchor->path));
    504       1.12      yamt 		if ((dup = RB_INSERT(pf_anchor_global, &pf_anchors, anchor)) !=
    505       1.12      yamt 		    NULL) {
    506       1.12      yamt 			printf("pf_find_or_create_ruleset: RB_INSERT1 "
    507       1.12      yamt 			    "'%s' '%s' collides with '%s' '%s'\n",
    508       1.12      yamt 			    anchor->path, anchor->name, dup->path, dup->name);
    509       1.12      yamt 			free(anchor, M_TEMP);
    510       1.12      yamt 			return (NULL);
    511       1.12      yamt 		}
    512       1.12      yamt 		if (parent != NULL) {
    513       1.12      yamt 			anchor->parent = parent;
    514       1.12      yamt 			if ((dup = RB_INSERT(pf_anchor_node, &parent->children,
    515       1.12      yamt 			    anchor)) != NULL) {
    516       1.12      yamt 				printf("pf_find_or_create_ruleset: "
    517       1.12      yamt 				    "RB_INSERT2 '%s' '%s' collides with "
    518       1.12      yamt 				    "'%s' '%s'\n", anchor->path, anchor->name,
    519       1.12      yamt 				    dup->path, dup->name);
    520       1.12      yamt 				RB_REMOVE(pf_anchor_global, &pf_anchors,
    521       1.12      yamt 				    anchor);
    522       1.12      yamt 				free(anchor, M_TEMP);
    523       1.12      yamt 				return (NULL);
    524       1.12      yamt 			}
    525       1.12      yamt 		}
    526       1.12      yamt 		pf_init_ruleset(&anchor->ruleset);
    527       1.12      yamt 		anchor->ruleset.anchor = anchor;
    528       1.12      yamt 		parent = anchor;
    529        1.1    itojun 		if (r != NULL)
    530       1.12      yamt 			q = r + 1;
    531        1.1    itojun 		else
    532       1.12      yamt 			*q = 0;
    533        1.1    itojun 	}
    534       1.12      yamt 	return (&anchor->ruleset);
    535        1.1    itojun }
    536        1.1    itojun 
    537        1.1    itojun void
    538        1.1    itojun pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
    539        1.1    itojun {
    540       1.12      yamt 	struct pf_anchor	*parent;
    541        1.1    itojun 	int			 i;
    542        1.1    itojun 
    543       1.12      yamt 	while (ruleset != NULL) {
    544       1.12      yamt 		if (ruleset == &pf_main_ruleset || ruleset->anchor == NULL ||
    545       1.12      yamt 		    !RB_EMPTY(&ruleset->anchor->children) ||
    546       1.12      yamt 		    ruleset->anchor->refcnt > 0 || ruleset->tables > 0 ||
    547       1.12      yamt 		    ruleset->topen)
    548       1.12      yamt 			return;
    549       1.12      yamt 		for (i = 0; i < PF_RULESET_MAX; ++i)
    550       1.12      yamt 			if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
    551       1.12      yamt 			    !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
    552       1.12      yamt 			    ruleset->rules[i].inactive.open)
    553       1.12      yamt 				return;
    554       1.12      yamt 		RB_REMOVE(pf_anchor_global, &pf_anchors, ruleset->anchor);
    555       1.12      yamt 		if ((parent = ruleset->anchor->parent) != NULL)
    556       1.12      yamt 			RB_REMOVE(pf_anchor_node, &parent->children,
    557       1.12      yamt 			    ruleset->anchor);
    558       1.12      yamt 		free(ruleset->anchor, M_TEMP);
    559       1.12      yamt 		if (parent == NULL)
    560        1.1    itojun 			return;
    561       1.12      yamt 		ruleset = &parent->ruleset;
    562       1.12      yamt 	}
    563       1.12      yamt }
    564        1.1    itojun 
    565       1.12      yamt int
    566       1.12      yamt pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s,
    567       1.12      yamt     const char *name)
    568       1.12      yamt {
    569       1.12      yamt 	static char		*p, path[MAXPATHLEN];
    570       1.12      yamt 	struct pf_ruleset	*ruleset;
    571       1.12      yamt 
    572       1.12      yamt 	r->anchor = NULL;
    573       1.12      yamt 	r->anchor_relative = 0;
    574       1.12      yamt 	r->anchor_wildcard = 0;
    575       1.12      yamt 	if (!name[0])
    576       1.12      yamt 		return (0);
    577       1.12      yamt 	if (name[0] == '/')
    578       1.12      yamt 		strlcpy(path, name + 1, sizeof(path));
    579       1.12      yamt 	else {
    580       1.12      yamt 		/* relative path */
    581       1.12      yamt 		r->anchor_relative = 1;
    582       1.12      yamt 		if (s->anchor == NULL || !s->anchor->path[0])
    583       1.12      yamt 			path[0] = 0;
    584       1.12      yamt 		else
    585       1.12      yamt 			strlcpy(path, s->anchor->path, sizeof(path));
    586       1.12      yamt 		while (name[0] == '.' && name[1] == '.' && name[2] == '/') {
    587       1.12      yamt 			if (!path[0]) {
    588       1.12      yamt 				printf("pf_anchor_setup: .. beyond root\n");
    589       1.12      yamt 				return (1);
    590       1.12      yamt 			}
    591       1.12      yamt 			if ((p = strrchr(path, '/')) != NULL)
    592       1.12      yamt 				*p = 0;
    593       1.12      yamt 			else
    594       1.12      yamt 				path[0] = 0;
    595       1.12      yamt 			r->anchor_relative++;
    596       1.12      yamt 			name += 3;
    597       1.12      yamt 		}
    598       1.12      yamt 		if (path[0])
    599       1.12      yamt 			strlcat(path, "/", sizeof(path));
    600       1.12      yamt 		strlcat(path, name, sizeof(path));
    601       1.12      yamt 	}
    602       1.12      yamt 	if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) {
    603       1.12      yamt 		r->anchor_wildcard = 1;
    604       1.12      yamt 		*p = 0;
    605       1.12      yamt 	}
    606       1.12      yamt 	ruleset = pf_find_or_create_ruleset(path);
    607       1.12      yamt 	if (ruleset == NULL || ruleset->anchor == NULL) {
    608       1.12      yamt 		printf("pf_anchor_setup: ruleset\n");
    609       1.12      yamt 		return (1);
    610        1.1    itojun 	}
    611       1.12      yamt 	r->anchor = ruleset->anchor;
    612       1.12      yamt 	r->anchor->refcnt++;
    613       1.12      yamt 	return (0);
    614       1.12      yamt }
    615       1.12      yamt 
    616       1.12      yamt int
    617       1.12      yamt pf_anchor_copyout(const struct pf_ruleset *rs, const struct pf_rule *r,
    618       1.12      yamt     struct pfioc_rule *pr)
    619       1.12      yamt {
    620       1.12      yamt 	pr->anchor_call[0] = 0;
    621       1.12      yamt 	if (r->anchor == NULL)
    622       1.12      yamt 		return (0);
    623       1.12      yamt 	if (!r->anchor_relative) {
    624       1.12      yamt 		strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call));
    625       1.12      yamt 		strlcat(pr->anchor_call, r->anchor->path,
    626       1.12      yamt 		    sizeof(pr->anchor_call));
    627       1.12      yamt 	} else {
    628       1.12      yamt 		char a[MAXPATHLEN], b[MAXPATHLEN], *p;
    629       1.12      yamt 		int i;
    630       1.12      yamt 
    631       1.12      yamt 		if (rs->anchor == NULL)
    632       1.12      yamt 			a[0] = 0;
    633       1.12      yamt 		else
    634       1.12      yamt 			strlcpy(a, rs->anchor->path, sizeof(a));
    635       1.12      yamt 		strlcpy(b, r->anchor->path, sizeof(b));
    636       1.12      yamt 		for (i = 1; i < r->anchor_relative; ++i) {
    637       1.12      yamt 			if ((p = strrchr(a, '/')) == NULL)
    638       1.12      yamt 				p = a;
    639       1.12      yamt 			*p = 0;
    640       1.12      yamt 			strlcat(pr->anchor_call, "../",
    641       1.12      yamt 			    sizeof(pr->anchor_call));
    642       1.12      yamt 		}
    643       1.12      yamt 		if (strncmp(a, b, strlen(a))) {
    644       1.12      yamt 			printf("pf_anchor_copyout: '%s' '%s'\n", a, b);
    645       1.12      yamt 			return (1);
    646       1.12      yamt 		}
    647       1.12      yamt 		if (strlen(b) > strlen(a))
    648       1.12      yamt 			strlcat(pr->anchor_call, b + (a[0] ? strlen(a) + 1 : 0),
    649       1.12      yamt 			    sizeof(pr->anchor_call));
    650       1.12      yamt 	}
    651       1.12      yamt 	if (r->anchor_wildcard)
    652       1.12      yamt 		strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*",
    653       1.12      yamt 		    sizeof(pr->anchor_call));
    654       1.12      yamt 	return (0);
    655       1.12      yamt }
    656       1.12      yamt 
    657       1.12      yamt void
    658       1.12      yamt pf_anchor_remove(struct pf_rule *r)
    659       1.12      yamt {
    660       1.12      yamt 	if (r->anchor == NULL)
    661       1.12      yamt 		return;
    662       1.12      yamt 	if (r->anchor->refcnt <= 0) {
    663       1.12      yamt 		printf("pf_anchor_remove: broken refcount");
    664       1.12      yamt 		r->anchor = NULL;
    665       1.12      yamt 		return;
    666       1.12      yamt 	}
    667       1.12      yamt 	if (!--r->anchor->refcnt)
    668       1.12      yamt 		pf_remove_if_empty_ruleset(&r->anchor->ruleset);
    669       1.12      yamt 	r->anchor = NULL;
    670        1.1    itojun }
    671        1.1    itojun 
    672        1.1    itojun void
    673        1.1    itojun pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb)
    674        1.1    itojun {
    675        1.1    itojun 	struct pf_pooladdr	*mv_pool_pa;
    676        1.1    itojun 
    677        1.1    itojun 	while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) {
    678        1.1    itojun 		TAILQ_REMOVE(poola, mv_pool_pa, entries);
    679        1.1    itojun 		TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries);
    680        1.1    itojun 	}
    681        1.1    itojun }
    682        1.1    itojun 
    683        1.1    itojun void
    684        1.1    itojun pf_empty_pool(struct pf_palist *poola)
    685        1.1    itojun {
    686        1.1    itojun 	struct pf_pooladdr	*empty_pool_pa;
    687        1.1    itojun 
    688        1.1    itojun 	while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) {
    689        1.1    itojun 		pfi_dynaddr_remove(&empty_pool_pa->addr);
    690        1.1    itojun 		pf_tbladdr_remove(&empty_pool_pa->addr);
    691        1.1    itojun 		pfi_detach_rule(empty_pool_pa->kif);
    692        1.1    itojun 		TAILQ_REMOVE(poola, empty_pool_pa, entries);
    693        1.1    itojun 		pool_put(&pf_pooladdr_pl, empty_pool_pa);
    694        1.1    itojun 	}
    695        1.1    itojun }
    696        1.1    itojun 
    697        1.1    itojun void
    698        1.1    itojun pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
    699        1.1    itojun {
    700        1.1    itojun 	if (rulequeue != NULL) {
    701        1.1    itojun 		if (rule->states <= 0) {
    702        1.1    itojun 			/*
    703        1.1    itojun 			 * XXX - we need to remove the table *before* detaching
    704        1.1    itojun 			 * the rule to make sure the table code does not delete
    705        1.1    itojun 			 * the anchor under our feet.
    706        1.1    itojun 			 */
    707        1.1    itojun 			pf_tbladdr_remove(&rule->src.addr);
    708        1.1    itojun 			pf_tbladdr_remove(&rule->dst.addr);
    709       1.17     peter 			if (rule->overload_tbl)
    710       1.17     peter 				pfr_detach_table(rule->overload_tbl);
    711        1.1    itojun 		}
    712        1.1    itojun 		TAILQ_REMOVE(rulequeue, rule, entries);
    713        1.1    itojun 		rule->entries.tqe_prev = NULL;
    714        1.1    itojun 		rule->nr = -1;
    715        1.1    itojun 	}
    716        1.1    itojun 
    717        1.1    itojun 	if (rule->states > 0 || rule->src_nodes > 0 ||
    718        1.1    itojun 	    rule->entries.tqe_prev != NULL)
    719        1.1    itojun 		return;
    720        1.1    itojun 	pf_tag_unref(rule->tag);
    721        1.1    itojun 	pf_tag_unref(rule->match_tag);
    722        1.1    itojun #ifdef ALTQ
    723        1.1    itojun 	if (rule->pqid != rule->qid)
    724        1.1    itojun 		pf_qid_unref(rule->pqid);
    725        1.1    itojun 	pf_qid_unref(rule->qid);
    726        1.1    itojun #endif
    727       1.17     peter 	pf_rtlabel_remove(&rule->src.addr);
    728       1.17     peter 	pf_rtlabel_remove(&rule->dst.addr);
    729        1.1    itojun 	pfi_dynaddr_remove(&rule->src.addr);
    730        1.1    itojun 	pfi_dynaddr_remove(&rule->dst.addr);
    731        1.1    itojun 	if (rulequeue == NULL) {
    732        1.1    itojun 		pf_tbladdr_remove(&rule->src.addr);
    733        1.1    itojun 		pf_tbladdr_remove(&rule->dst.addr);
    734       1.17     peter 		if (rule->overload_tbl)
    735       1.17     peter 			pfr_detach_table(rule->overload_tbl);
    736        1.1    itojun 	}
    737        1.1    itojun 	pfi_detach_rule(rule->kif);
    738       1.12      yamt 	pf_anchor_remove(rule);
    739        1.1    itojun 	pf_empty_pool(&rule->rpool.list);
    740        1.1    itojun 	pool_put(&pf_rule_pl, rule);
    741        1.1    itojun }
    742        1.1    itojun 
    743        1.1    itojun static	u_int16_t
    744        1.1    itojun tagname2tag(struct pf_tags *head, char *tagname)
    745        1.1    itojun {
    746        1.1    itojun 	struct pf_tagname	*tag, *p = NULL;
    747        1.1    itojun 	u_int16_t		 new_tagid = 1;
    748        1.1    itojun 
    749        1.1    itojun 	TAILQ_FOREACH(tag, head, entries)
    750        1.1    itojun 		if (strcmp(tagname, tag->name) == 0) {
    751        1.1    itojun 			tag->ref++;
    752        1.1    itojun 			return (tag->tag);
    753        1.1    itojun 		}
    754        1.1    itojun 
    755        1.1    itojun 	/*
    756        1.1    itojun 	 * to avoid fragmentation, we do a linear search from the beginning
    757        1.1    itojun 	 * and take the first free slot we find. if there is none or the list
    758        1.1    itojun 	 * is empty, append a new entry at the end.
    759        1.1    itojun 	 */
    760        1.1    itojun 
    761        1.1    itojun 	/* new entry */
    762        1.1    itojun 	if (!TAILQ_EMPTY(head))
    763        1.1    itojun 		for (p = TAILQ_FIRST(head); p != NULL &&
    764        1.1    itojun 		    p->tag == new_tagid; p = TAILQ_NEXT(p, entries))
    765        1.1    itojun 			new_tagid = p->tag + 1;
    766        1.1    itojun 
    767        1.1    itojun 	if (new_tagid > TAGID_MAX)
    768        1.1    itojun 		return (0);
    769        1.1    itojun 
    770        1.1    itojun 	/* allocate and fill new struct pf_tagname */
    771        1.1    itojun 	tag = (struct pf_tagname *)malloc(sizeof(struct pf_tagname),
    772        1.1    itojun 	    M_TEMP, M_NOWAIT);
    773        1.1    itojun 	if (tag == NULL)
    774        1.1    itojun 		return (0);
    775        1.1    itojun 	bzero(tag, sizeof(struct pf_tagname));
    776        1.1    itojun 	strlcpy(tag->name, tagname, sizeof(tag->name));
    777        1.1    itojun 	tag->tag = new_tagid;
    778        1.1    itojun 	tag->ref++;
    779        1.1    itojun 
    780        1.1    itojun 	if (p != NULL)	/* insert new entry before p */
    781        1.1    itojun 		TAILQ_INSERT_BEFORE(p, tag, entries);
    782        1.1    itojun 	else	/* either list empty or no free slot in between */
    783        1.1    itojun 		TAILQ_INSERT_TAIL(head, tag, entries);
    784        1.1    itojun 
    785        1.1    itojun 	return (tag->tag);
    786        1.1    itojun }
    787        1.1    itojun 
    788        1.1    itojun static	void
    789        1.1    itojun tag2tagname(struct pf_tags *head, u_int16_t tagid, char *p)
    790        1.1    itojun {
    791        1.1    itojun 	struct pf_tagname	*tag;
    792        1.1    itojun 
    793        1.1    itojun 	TAILQ_FOREACH(tag, head, entries)
    794        1.1    itojun 		if (tag->tag == tagid) {
    795        1.1    itojun 			strlcpy(p, tag->name, PF_TAG_NAME_SIZE);
    796        1.1    itojun 			return;
    797        1.1    itojun 		}
    798        1.1    itojun }
    799        1.1    itojun 
    800        1.1    itojun static	void
    801        1.1    itojun tag_unref(struct pf_tags *head, u_int16_t tag)
    802        1.1    itojun {
    803        1.1    itojun 	struct pf_tagname	*p, *next;
    804        1.1    itojun 
    805        1.1    itojun 	if (tag == 0)
    806        1.1    itojun 		return;
    807        1.1    itojun 
    808        1.1    itojun 	for (p = TAILQ_FIRST(head); p != NULL; p = next) {
    809        1.1    itojun 		next = TAILQ_NEXT(p, entries);
    810        1.1    itojun 		if (tag == p->tag) {
    811        1.1    itojun 			if (--p->ref == 0) {
    812        1.1    itojun 				TAILQ_REMOVE(head, p, entries);
    813        1.1    itojun 				free(p, M_TEMP);
    814        1.1    itojun 			}
    815        1.1    itojun 			break;
    816        1.1    itojun 		}
    817        1.1    itojun 	}
    818        1.1    itojun }
    819        1.1    itojun 
    820        1.1    itojun u_int16_t
    821        1.1    itojun pf_tagname2tag(char *tagname)
    822        1.1    itojun {
    823        1.1    itojun 	return (tagname2tag(&pf_tags, tagname));
    824        1.1    itojun }
    825        1.1    itojun 
    826        1.1    itojun void
    827        1.1    itojun pf_tag2tagname(u_int16_t tagid, char *p)
    828        1.1    itojun {
    829        1.1    itojun 	return (tag2tagname(&pf_tags, tagid, p));
    830        1.1    itojun }
    831        1.1    itojun 
    832        1.1    itojun void
    833       1.17     peter pf_tag_ref(u_int16_t tag)
    834       1.17     peter {
    835       1.17     peter 	struct pf_tagname *t;
    836       1.17     peter 
    837       1.17     peter 	TAILQ_FOREACH(t, &pf_tags, entries)
    838       1.17     peter 		if (t->tag == tag)
    839       1.17     peter 			break;
    840       1.17     peter 	if (t != NULL)
    841       1.17     peter 		t->ref++;
    842       1.17     peter }
    843       1.17     peter 
    844       1.17     peter void
    845        1.1    itojun pf_tag_unref(u_int16_t tag)
    846        1.1    itojun {
    847        1.1    itojun 	return (tag_unref(&pf_tags, tag));
    848        1.1    itojun }
    849        1.1    itojun 
    850       1.17     peter int
    851       1.17     peter pf_rtlabel_add(struct pf_addr_wrap *a)
    852       1.17     peter {
    853       1.17     peter #ifdef __OpenBSD__
    854       1.17     peter 	if (a->type == PF_ADDR_RTLABEL &&
    855       1.17     peter 	    (a->v.rtlabel = rtlabel_name2id(a->v.rtlabelname)) == 0)
    856       1.17     peter 		return (-1);
    857       1.17     peter #endif
    858       1.17     peter 	return (0);
    859       1.17     peter }
    860       1.17     peter 
    861       1.17     peter void
    862       1.17     peter pf_rtlabel_remove(struct pf_addr_wrap *a)
    863       1.17     peter {
    864       1.17     peter #ifdef __OpenBSD__
    865       1.17     peter 	if (a->type == PF_ADDR_RTLABEL)
    866       1.17     peter 		rtlabel_unref(a->v.rtlabel);
    867       1.17     peter #endif
    868       1.17     peter }
    869       1.17     peter 
    870       1.17     peter void
    871       1.17     peter pf_rtlabel_copyout(struct pf_addr_wrap *a)
    872       1.17     peter {
    873       1.17     peter #ifdef __OpenBSD__
    874       1.17     peter 	const char	*name;
    875       1.17     peter 
    876       1.17     peter 	if (a->type == PF_ADDR_RTLABEL && a->v.rtlabel) {
    877       1.17     peter 		if ((name = rtlabel_id2name(a->v.rtlabel)) == NULL)
    878       1.17     peter 			strlcpy(a->v.rtlabelname, "?",
    879       1.17     peter 			    sizeof(a->v.rtlabelname));
    880       1.17     peter 		else
    881       1.17     peter 			strlcpy(a->v.rtlabelname, name,
    882       1.17     peter 			    sizeof(a->v.rtlabelname));
    883       1.17     peter 	}
    884       1.17     peter #endif
    885       1.17     peter }
    886       1.17     peter 
    887        1.1    itojun #ifdef ALTQ
    888        1.1    itojun u_int32_t
    889        1.1    itojun pf_qname2qid(char *qname)
    890        1.1    itojun {
    891        1.1    itojun 	return ((u_int32_t)tagname2tag(&pf_qids, qname));
    892        1.1    itojun }
    893        1.1    itojun 
    894        1.1    itojun void
    895        1.1    itojun pf_qid2qname(u_int32_t qid, char *p)
    896        1.1    itojun {
    897        1.1    itojun 	return (tag2tagname(&pf_qids, (u_int16_t)qid, p));
    898        1.1    itojun }
    899        1.1    itojun 
    900        1.1    itojun void
    901        1.1    itojun pf_qid_unref(u_int32_t qid)
    902        1.1    itojun {
    903        1.1    itojun 	return (tag_unref(&pf_qids, (u_int16_t)qid));
    904        1.1    itojun }
    905        1.1    itojun 
    906        1.1    itojun int
    907        1.1    itojun pf_begin_altq(u_int32_t *ticket)
    908        1.1    itojun {
    909        1.1    itojun 	struct pf_altq	*altq;
    910        1.1    itojun 	int		 error = 0;
    911        1.1    itojun 
    912        1.1    itojun 	/* Purge the old altq list */
    913        1.1    itojun 	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
    914        1.1    itojun 		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
    915        1.1    itojun 		if (altq->qname[0] == 0) {
    916        1.1    itojun 			/* detach and destroy the discipline */
    917        1.1    itojun 			error = altq_remove(altq);
    918        1.1    itojun 		} else
    919        1.1    itojun 			pf_qid_unref(altq->qid);
    920        1.1    itojun 		pool_put(&pf_altq_pl, altq);
    921        1.1    itojun 	}
    922        1.1    itojun 	if (error)
    923        1.1    itojun 		return (error);
    924        1.1    itojun 	*ticket = ++ticket_altqs_inactive;
    925        1.1    itojun 	altqs_inactive_open = 1;
    926        1.1    itojun 	return (0);
    927        1.1    itojun }
    928        1.1    itojun 
    929        1.1    itojun int
    930        1.1    itojun pf_rollback_altq(u_int32_t ticket)
    931        1.1    itojun {
    932        1.1    itojun 	struct pf_altq	*altq;
    933        1.1    itojun 	int		 error = 0;
    934        1.1    itojun 
    935        1.1    itojun 	if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
    936        1.1    itojun 		return (0);
    937        1.1    itojun 	/* Purge the old altq list */
    938        1.1    itojun 	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
    939        1.1    itojun 		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
    940        1.1    itojun 		if (altq->qname[0] == 0) {
    941        1.1    itojun 			/* detach and destroy the discipline */
    942        1.1    itojun 			error = altq_remove(altq);
    943        1.1    itojun 		} else
    944        1.1    itojun 			pf_qid_unref(altq->qid);
    945        1.1    itojun 		pool_put(&pf_altq_pl, altq);
    946        1.1    itojun 	}
    947        1.1    itojun 	altqs_inactive_open = 0;
    948        1.1    itojun 	return (error);
    949        1.1    itojun }
    950        1.1    itojun 
    951        1.1    itojun int
    952        1.1    itojun pf_commit_altq(u_int32_t ticket)
    953        1.1    itojun {
    954        1.1    itojun 	struct pf_altqqueue	*old_altqs;
    955        1.1    itojun 	struct pf_altq		*altq;
    956        1.1    itojun 	int			 s, err, error = 0;
    957        1.1    itojun 
    958        1.1    itojun 	if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
    959        1.1    itojun 		return (EBUSY);
    960        1.1    itojun 
    961        1.1    itojun 	/* swap altqs, keep the old. */
    962        1.1    itojun 	s = splsoftnet();
    963        1.1    itojun 	old_altqs = pf_altqs_active;
    964        1.1    itojun 	pf_altqs_active = pf_altqs_inactive;
    965        1.1    itojun 	pf_altqs_inactive = old_altqs;
    966        1.1    itojun 	ticket_altqs_active = ticket_altqs_inactive;
    967        1.1    itojun 
    968        1.1    itojun 	/* Attach new disciplines */
    969        1.1    itojun 	TAILQ_FOREACH(altq, pf_altqs_active, entries) {
    970        1.1    itojun 		if (altq->qname[0] == 0) {
    971        1.1    itojun 			/* attach the discipline */
    972        1.1    itojun 			error = altq_pfattach(altq);
    973       1.12      yamt 			if (error == 0 && pf_altq_running)
    974       1.12      yamt 				error = pf_enable_altq(altq);
    975       1.12      yamt 			if (error != 0) {
    976        1.1    itojun 				splx(s);
    977        1.1    itojun 				return (error);
    978        1.1    itojun 			}
    979        1.1    itojun 		}
    980        1.1    itojun 	}
    981        1.1    itojun 
    982        1.1    itojun 	/* Purge the old altq list */
    983        1.1    itojun 	while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
    984        1.1    itojun 		TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
    985        1.1    itojun 		if (altq->qname[0] == 0) {
    986        1.1    itojun 			/* detach and destroy the discipline */
    987       1.12      yamt 			if (pf_altq_running)
    988       1.12      yamt 				error = pf_disable_altq(altq);
    989        1.1    itojun 			err = altq_pfdetach(altq);
    990        1.1    itojun 			if (err != 0 && error == 0)
    991        1.1    itojun 				error = err;
    992        1.1    itojun 			err = altq_remove(altq);
    993        1.1    itojun 			if (err != 0 && error == 0)
    994        1.1    itojun 				error = err;
    995        1.1    itojun 		} else
    996        1.1    itojun 			pf_qid_unref(altq->qid);
    997        1.1    itojun 		pool_put(&pf_altq_pl, altq);
    998        1.1    itojun 	}
    999        1.1    itojun 	splx(s);
   1000        1.1    itojun 
   1001        1.1    itojun 	altqs_inactive_open = 0;
   1002        1.1    itojun 	return (error);
   1003        1.1    itojun }
   1004       1.12      yamt 
   1005       1.12      yamt int
   1006       1.12      yamt pf_enable_altq(struct pf_altq *altq)
   1007       1.12      yamt {
   1008       1.12      yamt 	struct ifnet		*ifp;
   1009       1.12      yamt 	struct tb_profile	 tb;
   1010       1.12      yamt 	int			 s, error = 0;
   1011       1.12      yamt 
   1012       1.12      yamt 	if ((ifp = ifunit(altq->ifname)) == NULL)
   1013       1.12      yamt 		return (EINVAL);
   1014       1.12      yamt 
   1015       1.12      yamt 	if (ifp->if_snd.altq_type != ALTQT_NONE)
   1016       1.12      yamt 		error = altq_enable(&ifp->if_snd);
   1017       1.12      yamt 
   1018       1.12      yamt 	/* set tokenbucket regulator */
   1019       1.12      yamt 	if (error == 0 && ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
   1020       1.12      yamt 		tb.rate = altq->ifbandwidth;
   1021       1.12      yamt 		tb.depth = altq->tbrsize;
   1022  1.21.12.1     peter #ifdef __NetBSD__
   1023  1.21.12.1     peter 		s = splnet();
   1024  1.21.12.1     peter #else
   1025       1.12      yamt 		s = splimp();
   1026  1.21.12.1     peter #endif
   1027       1.12      yamt 		error = tbr_set(&ifp->if_snd, &tb);
   1028       1.12      yamt 		splx(s);
   1029       1.12      yamt 	}
   1030       1.12      yamt 
   1031       1.12      yamt 	return (error);
   1032       1.12      yamt }
   1033       1.12      yamt 
   1034       1.12      yamt int
   1035       1.12      yamt pf_disable_altq(struct pf_altq *altq)
   1036       1.12      yamt {
   1037       1.12      yamt 	struct ifnet		*ifp;
   1038       1.12      yamt 	struct tb_profile	 tb;
   1039       1.12      yamt 	int			 s, error;
   1040       1.12      yamt 
   1041       1.12      yamt 	if ((ifp = ifunit(altq->ifname)) == NULL)
   1042       1.12      yamt 		return (EINVAL);
   1043       1.12      yamt 
   1044       1.12      yamt 	/*
   1045       1.12      yamt 	 * when the discipline is no longer referenced, it was overridden
   1046       1.12      yamt 	 * by a new one.  if so, just return.
   1047       1.12      yamt 	 */
   1048       1.12      yamt 	if (altq->altq_disc != ifp->if_snd.altq_disc)
   1049       1.12      yamt 		return (0);
   1050       1.12      yamt 
   1051       1.12      yamt 	error = altq_disable(&ifp->if_snd);
   1052       1.12      yamt 
   1053       1.12      yamt 	if (error == 0) {
   1054       1.12      yamt 		/* clear tokenbucket regulator */
   1055       1.12      yamt 		tb.rate = 0;
   1056  1.21.12.1     peter #ifdef __NetBSD__
   1057  1.21.12.1     peter 		s = splnet();
   1058  1.21.12.1     peter #else
   1059       1.12      yamt 		s = splimp();
   1060  1.21.12.1     peter #endif
   1061       1.12      yamt 		error = tbr_set(&ifp->if_snd, &tb);
   1062       1.12      yamt 		splx(s);
   1063       1.12      yamt 	}
   1064       1.12      yamt 
   1065       1.12      yamt 	return (error);
   1066       1.12      yamt }
   1067        1.1    itojun #endif /* ALTQ */
   1068        1.1    itojun 
   1069        1.1    itojun int
   1070       1.12      yamt pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
   1071        1.1    itojun {
   1072        1.1    itojun 	struct pf_ruleset	*rs;
   1073        1.1    itojun 	struct pf_rule		*rule;
   1074        1.1    itojun 
   1075        1.1    itojun 	if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
   1076        1.1    itojun 		return (EINVAL);
   1077       1.12      yamt 	rs = pf_find_or_create_ruleset(anchor);
   1078        1.1    itojun 	if (rs == NULL)
   1079        1.1    itojun 		return (EINVAL);
   1080        1.1    itojun 	while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL)
   1081        1.1    itojun 		pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
   1082        1.1    itojun 	*ticket = ++rs->rules[rs_num].inactive.ticket;
   1083        1.1    itojun 	rs->rules[rs_num].inactive.open = 1;
   1084        1.1    itojun 	return (0);
   1085        1.1    itojun }
   1086        1.1    itojun 
   1087        1.1    itojun int
   1088       1.12      yamt pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor)
   1089        1.1    itojun {
   1090        1.1    itojun 	struct pf_ruleset	*rs;
   1091        1.1    itojun 	struct pf_rule		*rule;
   1092        1.1    itojun 
   1093        1.1    itojun 	if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
   1094        1.1    itojun 		return (EINVAL);
   1095       1.12      yamt 	rs = pf_find_ruleset(anchor);
   1096        1.1    itojun 	if (rs == NULL || !rs->rules[rs_num].inactive.open ||
   1097        1.1    itojun 	    rs->rules[rs_num].inactive.ticket != ticket)
   1098        1.1    itojun 		return (0);
   1099        1.1    itojun 	while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL)
   1100        1.1    itojun 		pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
   1101        1.1    itojun 	rs->rules[rs_num].inactive.open = 0;
   1102        1.1    itojun 	return (0);
   1103        1.1    itojun }
   1104        1.1    itojun 
   1105        1.1    itojun int
   1106       1.12      yamt pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
   1107        1.1    itojun {
   1108        1.1    itojun 	struct pf_ruleset	*rs;
   1109        1.1    itojun 	struct pf_rule		*rule;
   1110        1.1    itojun 	struct pf_rulequeue	*old_rules;
   1111        1.1    itojun 	int			 s;
   1112        1.1    itojun 
   1113        1.1    itojun 	if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
   1114        1.1    itojun 		return (EINVAL);
   1115       1.12      yamt 	rs = pf_find_ruleset(anchor);
   1116        1.1    itojun 	if (rs == NULL || !rs->rules[rs_num].inactive.open ||
   1117        1.1    itojun 	    ticket != rs->rules[rs_num].inactive.ticket)
   1118        1.1    itojun 		return (EBUSY);
   1119        1.1    itojun 
   1120        1.1    itojun 	/* Swap rules, keep the old. */
   1121        1.1    itojun 	s = splsoftnet();
   1122        1.1    itojun 	old_rules = rs->rules[rs_num].active.ptr;
   1123        1.1    itojun 	rs->rules[rs_num].active.ptr =
   1124        1.1    itojun 	    rs->rules[rs_num].inactive.ptr;
   1125        1.1    itojun 	rs->rules[rs_num].inactive.ptr = old_rules;
   1126        1.1    itojun 	rs->rules[rs_num].active.ticket =
   1127        1.1    itojun 	    rs->rules[rs_num].inactive.ticket;
   1128        1.1    itojun 	pf_calc_skip_steps(rs->rules[rs_num].active.ptr);
   1129        1.1    itojun 
   1130        1.1    itojun 	/* Purge the old rule list. */
   1131        1.1    itojun 	while ((rule = TAILQ_FIRST(old_rules)) != NULL)
   1132        1.1    itojun 		pf_rm_rule(old_rules, rule);
   1133        1.1    itojun 	rs->rules[rs_num].inactive.open = 0;
   1134        1.1    itojun 	pf_remove_if_empty_ruleset(rs);
   1135        1.1    itojun 	splx(s);
   1136        1.1    itojun 	return (0);
   1137        1.1    itojun }
   1138        1.1    itojun 
   1139        1.1    itojun int
   1140       1.21  christos pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct lwp *l)
   1141        1.1    itojun {
   1142        1.1    itojun 	struct pf_pooladdr	*pa = NULL;
   1143        1.1    itojun 	struct pf_pool		*pool = NULL;
   1144        1.1    itojun 	int			 s;
   1145        1.1    itojun 	int			 error = 0;
   1146        1.1    itojun 
   1147        1.1    itojun 	/* XXX keep in sync with switch() below */
   1148        1.1    itojun 	if (securelevel > 1)
   1149        1.1    itojun 		switch (cmd) {
   1150        1.1    itojun 		case DIOCGETRULES:
   1151        1.1    itojun 		case DIOCGETRULE:
   1152        1.1    itojun 		case DIOCGETADDRS:
   1153        1.1    itojun 		case DIOCGETADDR:
   1154        1.1    itojun 		case DIOCGETSTATE:
   1155        1.1    itojun 		case DIOCSETSTATUSIF:
   1156        1.1    itojun 		case DIOCGETSTATUS:
   1157        1.1    itojun 		case DIOCCLRSTATUS:
   1158        1.1    itojun 		case DIOCNATLOOK:
   1159        1.1    itojun 		case DIOCSETDEBUG:
   1160        1.1    itojun 		case DIOCGETSTATES:
   1161        1.1    itojun 		case DIOCGETTIMEOUT:
   1162        1.1    itojun 		case DIOCCLRRULECTRS:
   1163        1.1    itojun 		case DIOCGETLIMIT:
   1164        1.1    itojun 		case DIOCGETALTQS:
   1165        1.1    itojun 		case DIOCGETALTQ:
   1166        1.1    itojun 		case DIOCGETQSTATS:
   1167        1.1    itojun 		case DIOCGETRULESETS:
   1168        1.1    itojun 		case DIOCGETRULESET:
   1169        1.1    itojun 		case DIOCRGETTABLES:
   1170        1.1    itojun 		case DIOCRGETTSTATS:
   1171        1.1    itojun 		case DIOCRCLRTSTATS:
   1172        1.1    itojun 		case DIOCRCLRADDRS:
   1173        1.1    itojun 		case DIOCRADDADDRS:
   1174        1.1    itojun 		case DIOCRDELADDRS:
   1175        1.1    itojun 		case DIOCRSETADDRS:
   1176        1.1    itojun 		case DIOCRGETADDRS:
   1177        1.1    itojun 		case DIOCRGETASTATS:
   1178        1.1    itojun 		case DIOCRCLRASTATS:
   1179        1.1    itojun 		case DIOCRTSTADDRS:
   1180        1.1    itojun 		case DIOCOSFPGET:
   1181        1.1    itojun 		case DIOCGETSRCNODES:
   1182        1.1    itojun 		case DIOCCLRSRCNODES:
   1183        1.1    itojun 		case DIOCIGETIFACES:
   1184        1.1    itojun 		case DIOCICLRISTATS:
   1185       1.17     peter 		case DIOCSETIFFLAG:
   1186       1.17     peter 		case DIOCCLRIFFLAG:
   1187        1.1    itojun 			break;
   1188        1.1    itojun 		case DIOCRCLRTABLES:
   1189        1.1    itojun 		case DIOCRADDTABLES:
   1190        1.1    itojun 		case DIOCRDELTABLES:
   1191        1.1    itojun 		case DIOCRSETTFLAGS:
   1192        1.1    itojun 			if (((struct pfioc_table *)addr)->pfrio_flags &
   1193        1.1    itojun 			    PFR_FLAG_DUMMY)
   1194        1.1    itojun 				break; /* dummy operation ok */
   1195        1.1    itojun 			return (EPERM);
   1196        1.1    itojun 		default:
   1197        1.1    itojun 			return (EPERM);
   1198        1.1    itojun 		}
   1199        1.1    itojun 
   1200        1.1    itojun 	if (!(flags & FWRITE))
   1201        1.1    itojun 		switch (cmd) {
   1202        1.1    itojun 		case DIOCGETRULES:
   1203        1.1    itojun 		case DIOCGETRULE:
   1204        1.1    itojun 		case DIOCGETADDRS:
   1205        1.1    itojun 		case DIOCGETADDR:
   1206        1.1    itojun 		case DIOCGETSTATE:
   1207        1.1    itojun 		case DIOCGETSTATUS:
   1208        1.1    itojun 		case DIOCGETSTATES:
   1209        1.1    itojun 		case DIOCGETTIMEOUT:
   1210        1.1    itojun 		case DIOCGETLIMIT:
   1211        1.1    itojun 		case DIOCGETALTQS:
   1212        1.1    itojun 		case DIOCGETALTQ:
   1213        1.1    itojun 		case DIOCGETQSTATS:
   1214        1.1    itojun 		case DIOCGETRULESETS:
   1215        1.1    itojun 		case DIOCGETRULESET:
   1216        1.1    itojun 		case DIOCRGETTABLES:
   1217        1.1    itojun 		case DIOCRGETTSTATS:
   1218        1.1    itojun 		case DIOCRGETADDRS:
   1219        1.1    itojun 		case DIOCRGETASTATS:
   1220        1.1    itojun 		case DIOCRTSTADDRS:
   1221        1.1    itojun 		case DIOCOSFPGET:
   1222        1.1    itojun 		case DIOCGETSRCNODES:
   1223        1.1    itojun 		case DIOCIGETIFACES:
   1224        1.1    itojun 			break;
   1225        1.1    itojun 		case DIOCRCLRTABLES:
   1226        1.1    itojun 		case DIOCRADDTABLES:
   1227        1.1    itojun 		case DIOCRDELTABLES:
   1228        1.1    itojun 		case DIOCRCLRTSTATS:
   1229        1.1    itojun 		case DIOCRCLRADDRS:
   1230        1.1    itojun 		case DIOCRADDADDRS:
   1231        1.1    itojun 		case DIOCRDELADDRS:
   1232        1.1    itojun 		case DIOCRSETADDRS:
   1233        1.1    itojun 		case DIOCRSETTFLAGS:
   1234        1.1    itojun 			if (((struct pfioc_table *)addr)->pfrio_flags &
   1235        1.1    itojun 			    PFR_FLAG_DUMMY)
   1236        1.1    itojun 				break; /* dummy operation ok */
   1237        1.1    itojun 			return (EACCES);
   1238        1.1    itojun 		default:
   1239        1.1    itojun 			return (EACCES);
   1240        1.1    itojun 		}
   1241        1.1    itojun 
   1242       1.15     peter 	s = splsoftnet();
   1243        1.1    itojun 	switch (cmd) {
   1244        1.1    itojun 
   1245        1.1    itojun 	case DIOCSTART:
   1246        1.1    itojun 		if (pf_status.running)
   1247        1.1    itojun 			error = EEXIST;
   1248        1.1    itojun 		else {
   1249        1.2    itojun #ifdef __NetBSD__
   1250        1.2    itojun 			error = pf_pfil_attach();
   1251        1.2    itojun 			if (error)
   1252        1.2    itojun 				break;
   1253        1.2    itojun #endif
   1254        1.1    itojun 			pf_status.running = 1;
   1255       1.12      yamt 			pf_status.since = time_second;
   1256        1.1    itojun 			if (pf_status.stateid == 0) {
   1257       1.12      yamt 				pf_status.stateid = time_second;
   1258        1.1    itojun 				pf_status.stateid = pf_status.stateid << 32;
   1259        1.1    itojun 			}
   1260        1.1    itojun 			DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
   1261        1.1    itojun 		}
   1262        1.1    itojun 		break;
   1263        1.1    itojun 
   1264        1.1    itojun 	case DIOCSTOP:
   1265        1.1    itojun 		if (!pf_status.running)
   1266        1.1    itojun 			error = ENOENT;
   1267        1.1    itojun 		else {
   1268        1.2    itojun #ifdef __NetBSD__
   1269        1.2    itojun 			error = pf_pfil_detach();
   1270        1.2    itojun 			if (error)
   1271        1.2    itojun 				break;
   1272        1.2    itojun #endif
   1273        1.1    itojun 			pf_status.running = 0;
   1274       1.12      yamt 			pf_status.since = time_second;
   1275        1.1    itojun 			DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
   1276        1.1    itojun 		}
   1277        1.1    itojun 		break;
   1278        1.1    itojun 
   1279        1.1    itojun 	case DIOCADDRULE: {
   1280        1.1    itojun 		struct pfioc_rule	*pr = (struct pfioc_rule *)addr;
   1281        1.1    itojun 		struct pf_ruleset	*ruleset;
   1282        1.1    itojun 		struct pf_rule		*rule, *tail;
   1283        1.1    itojun 		struct pf_pooladdr	*pa;
   1284        1.1    itojun 		int			 rs_num;
   1285        1.1    itojun 
   1286       1.12      yamt 		pr->anchor[sizeof(pr->anchor) - 1] = 0;
   1287       1.12      yamt 		ruleset = pf_find_ruleset(pr->anchor);
   1288        1.1    itojun 		if (ruleset == NULL) {
   1289        1.1    itojun 			error = EINVAL;
   1290        1.1    itojun 			break;
   1291        1.1    itojun 		}
   1292        1.1    itojun 		rs_num = pf_get_ruleset_number(pr->rule.action);
   1293        1.1    itojun 		if (rs_num >= PF_RULESET_MAX) {
   1294        1.1    itojun 			error = EINVAL;
   1295        1.1    itojun 			break;
   1296        1.1    itojun 		}
   1297        1.1    itojun 		if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
   1298        1.1    itojun 			error = EINVAL;
   1299        1.1    itojun 			break;
   1300        1.1    itojun 		}
   1301        1.1    itojun 		if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) {
   1302        1.1    itojun 			error = EBUSY;
   1303        1.1    itojun 			break;
   1304        1.1    itojun 		}
   1305        1.1    itojun 		if (pr->pool_ticket != ticket_pabuf) {
   1306        1.1    itojun 			error = EBUSY;
   1307        1.1    itojun 			break;
   1308        1.1    itojun 		}
   1309        1.1    itojun 		rule = pool_get(&pf_rule_pl, PR_NOWAIT);
   1310        1.1    itojun 		if (rule == NULL) {
   1311        1.1    itojun 			error = ENOMEM;
   1312        1.1    itojun 			break;
   1313        1.1    itojun 		}
   1314        1.1    itojun 		bcopy(&pr->rule, rule, sizeof(struct pf_rule));
   1315        1.1    itojun 		rule->anchor = NULL;
   1316        1.1    itojun 		rule->kif = NULL;
   1317        1.1    itojun 		TAILQ_INIT(&rule->rpool.list);
   1318        1.1    itojun 		/* initialize refcounting */
   1319        1.1    itojun 		rule->states = 0;
   1320        1.1    itojun 		rule->src_nodes = 0;
   1321        1.1    itojun 		rule->entries.tqe_prev = NULL;
   1322        1.1    itojun #ifndef INET
   1323        1.1    itojun 		if (rule->af == AF_INET) {
   1324        1.1    itojun 			pool_put(&pf_rule_pl, rule);
   1325        1.1    itojun 			error = EAFNOSUPPORT;
   1326        1.1    itojun 			break;
   1327        1.1    itojun 		}
   1328        1.1    itojun #endif /* INET */
   1329        1.1    itojun #ifndef INET6
   1330        1.1    itojun 		if (rule->af == AF_INET6) {
   1331        1.1    itojun 			pool_put(&pf_rule_pl, rule);
   1332        1.1    itojun 			error = EAFNOSUPPORT;
   1333        1.1    itojun 			break;
   1334        1.1    itojun 		}
   1335        1.1    itojun #endif /* INET6 */
   1336        1.1    itojun 		tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
   1337        1.1    itojun 		    pf_rulequeue);
   1338        1.1    itojun 		if (tail)
   1339        1.1    itojun 			rule->nr = tail->nr + 1;
   1340        1.1    itojun 		else
   1341        1.1    itojun 			rule->nr = 0;
   1342        1.1    itojun 		if (rule->ifname[0]) {
   1343        1.1    itojun 			rule->kif = pfi_attach_rule(rule->ifname);
   1344        1.1    itojun 			if (rule->kif == NULL) {
   1345        1.1    itojun 				pool_put(&pf_rule_pl, rule);
   1346        1.1    itojun 				error = EINVAL;
   1347        1.1    itojun 				break;
   1348        1.1    itojun 			}
   1349        1.1    itojun 		}
   1350        1.1    itojun 
   1351        1.1    itojun #ifdef ALTQ
   1352        1.1    itojun 		/* set queue IDs */
   1353        1.1    itojun 		if (rule->qname[0] != 0) {
   1354        1.1    itojun 			if ((rule->qid = pf_qname2qid(rule->qname)) == 0)
   1355        1.1    itojun 				error = EBUSY;
   1356        1.1    itojun 			else if (rule->pqname[0] != 0) {
   1357        1.1    itojun 				if ((rule->pqid =
   1358        1.1    itojun 				    pf_qname2qid(rule->pqname)) == 0)
   1359        1.1    itojun 					error = EBUSY;
   1360        1.1    itojun 			} else
   1361        1.1    itojun 				rule->pqid = rule->qid;
   1362        1.1    itojun 		}
   1363        1.1    itojun #endif
   1364        1.1    itojun 		if (rule->tagname[0])
   1365        1.1    itojun 			if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
   1366        1.1    itojun 				error = EBUSY;
   1367        1.1    itojun 		if (rule->match_tagname[0])
   1368        1.1    itojun 			if ((rule->match_tag =
   1369        1.1    itojun 			    pf_tagname2tag(rule->match_tagname)) == 0)
   1370        1.1    itojun 				error = EBUSY;
   1371        1.1    itojun 		if (rule->rt && !rule->direction)
   1372        1.1    itojun 			error = EINVAL;
   1373       1.17     peter 		if (pf_rtlabel_add(&rule->src.addr) ||
   1374       1.17     peter 		    pf_rtlabel_add(&rule->dst.addr))
   1375       1.17     peter 			error = EBUSY;
   1376        1.1    itojun 		if (pfi_dynaddr_setup(&rule->src.addr, rule->af))
   1377        1.1    itojun 			error = EINVAL;
   1378        1.1    itojun 		if (pfi_dynaddr_setup(&rule->dst.addr, rule->af))
   1379        1.1    itojun 			error = EINVAL;
   1380        1.1    itojun 		if (pf_tbladdr_setup(ruleset, &rule->src.addr))
   1381        1.1    itojun 			error = EINVAL;
   1382        1.1    itojun 		if (pf_tbladdr_setup(ruleset, &rule->dst.addr))
   1383        1.1    itojun 			error = EINVAL;
   1384       1.12      yamt 		if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
   1385       1.12      yamt 			error = EINVAL;
   1386        1.1    itojun 		TAILQ_FOREACH(pa, &pf_pabuf, entries)
   1387        1.1    itojun 			if (pf_tbladdr_setup(ruleset, &pa->addr))
   1388        1.1    itojun 				error = EINVAL;
   1389        1.1    itojun 
   1390       1.17     peter 		if (rule->overload_tblname[0]) {
   1391       1.17     peter 			if ((rule->overload_tbl = pfr_attach_table(ruleset,
   1392       1.17     peter 			    rule->overload_tblname)) == NULL)
   1393       1.17     peter 				error = EINVAL;
   1394       1.17     peter 			else
   1395       1.17     peter 				rule->overload_tbl->pfrkt_flags |=
   1396       1.17     peter 				    PFR_TFLAG_ACTIVE;
   1397       1.17     peter 		}
   1398       1.17     peter 
   1399        1.1    itojun 		pf_mv_pool(&pf_pabuf, &rule->rpool.list);
   1400        1.1    itojun 		if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
   1401       1.12      yamt 		    (rule->action == PF_BINAT)) && rule->anchor == NULL) ||
   1402        1.1    itojun 		    (rule->rt > PF_FASTROUTE)) &&
   1403        1.1    itojun 		    (TAILQ_FIRST(&rule->rpool.list) == NULL))
   1404        1.1    itojun 			error = EINVAL;
   1405        1.1    itojun 
   1406        1.1    itojun 		if (error) {
   1407        1.1    itojun 			pf_rm_rule(NULL, rule);
   1408        1.1    itojun 			break;
   1409        1.1    itojun 		}
   1410        1.1    itojun 		rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
   1411        1.1    itojun 		rule->evaluations = rule->packets = rule->bytes = 0;
   1412        1.1    itojun 		TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr,
   1413        1.1    itojun 		    rule, entries);
   1414        1.1    itojun 		break;
   1415        1.1    itojun 	}
   1416        1.1    itojun 
   1417        1.1    itojun 	case DIOCGETRULES: {
   1418        1.1    itojun 		struct pfioc_rule	*pr = (struct pfioc_rule *)addr;
   1419        1.1    itojun 		struct pf_ruleset	*ruleset;
   1420        1.1    itojun 		struct pf_rule		*tail;
   1421        1.1    itojun 		int			 rs_num;
   1422        1.1    itojun 
   1423       1.12      yamt 		pr->anchor[sizeof(pr->anchor) - 1] = 0;
   1424       1.12      yamt 		ruleset = pf_find_ruleset(pr->anchor);
   1425        1.1    itojun 		if (ruleset == NULL) {
   1426        1.1    itojun 			error = EINVAL;
   1427        1.1    itojun 			break;
   1428        1.1    itojun 		}
   1429        1.1    itojun 		rs_num = pf_get_ruleset_number(pr->rule.action);
   1430        1.1    itojun 		if (rs_num >= PF_RULESET_MAX) {
   1431        1.1    itojun 			error = EINVAL;
   1432        1.1    itojun 			break;
   1433        1.1    itojun 		}
   1434        1.1    itojun 		tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
   1435        1.1    itojun 		    pf_rulequeue);
   1436        1.1    itojun 		if (tail)
   1437        1.1    itojun 			pr->nr = tail->nr + 1;
   1438        1.1    itojun 		else
   1439        1.1    itojun 			pr->nr = 0;
   1440        1.1    itojun 		pr->ticket = ruleset->rules[rs_num].active.ticket;
   1441        1.1    itojun 		break;
   1442        1.1    itojun 	}
   1443        1.1    itojun 
   1444        1.1    itojun 	case DIOCGETRULE: {
   1445        1.1    itojun 		struct pfioc_rule	*pr = (struct pfioc_rule *)addr;
   1446        1.1    itojun 		struct pf_ruleset	*ruleset;
   1447        1.1    itojun 		struct pf_rule		*rule;
   1448        1.1    itojun 		int			 rs_num, i;
   1449        1.1    itojun 
   1450       1.12      yamt 		pr->anchor[sizeof(pr->anchor) - 1] = 0;
   1451       1.12      yamt 		ruleset = pf_find_ruleset(pr->anchor);
   1452        1.1    itojun 		if (ruleset == NULL) {
   1453        1.1    itojun 			error = EINVAL;
   1454        1.1    itojun 			break;
   1455        1.1    itojun 		}
   1456        1.1    itojun 		rs_num = pf_get_ruleset_number(pr->rule.action);
   1457        1.1    itojun 		if (rs_num >= PF_RULESET_MAX) {
   1458        1.1    itojun 			error = EINVAL;
   1459        1.1    itojun 			break;
   1460        1.1    itojun 		}
   1461        1.1    itojun 		if (pr->ticket != ruleset->rules[rs_num].active.ticket) {
   1462        1.1    itojun 			error = EBUSY;
   1463        1.1    itojun 			break;
   1464        1.1    itojun 		}
   1465        1.1    itojun 		rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
   1466        1.1    itojun 		while ((rule != NULL) && (rule->nr != pr->nr))
   1467        1.1    itojun 			rule = TAILQ_NEXT(rule, entries);
   1468        1.1    itojun 		if (rule == NULL) {
   1469        1.1    itojun 			error = EBUSY;
   1470        1.1    itojun 			break;
   1471        1.1    itojun 		}
   1472        1.1    itojun 		bcopy(rule, &pr->rule, sizeof(struct pf_rule));
   1473       1.12      yamt 		if (pf_anchor_copyout(ruleset, rule, pr)) {
   1474       1.12      yamt 			error = EBUSY;
   1475       1.12      yamt 			break;
   1476       1.12      yamt 		}
   1477        1.1    itojun 		pfi_dynaddr_copyout(&pr->rule.src.addr);
   1478        1.1    itojun 		pfi_dynaddr_copyout(&pr->rule.dst.addr);
   1479        1.1    itojun 		pf_tbladdr_copyout(&pr->rule.src.addr);
   1480        1.1    itojun 		pf_tbladdr_copyout(&pr->rule.dst.addr);
   1481       1.17     peter 		pf_rtlabel_copyout(&pr->rule.src.addr);
   1482       1.17     peter 		pf_rtlabel_copyout(&pr->rule.dst.addr);
   1483        1.1    itojun 		for (i = 0; i < PF_SKIP_COUNT; ++i)
   1484        1.1    itojun 			if (rule->skip[i].ptr == NULL)
   1485        1.1    itojun 				pr->rule.skip[i].nr = -1;
   1486        1.1    itojun 			else
   1487        1.1    itojun 				pr->rule.skip[i].nr =
   1488        1.1    itojun 				    rule->skip[i].ptr->nr;
   1489        1.1    itojun 		break;
   1490        1.1    itojun 	}
   1491        1.1    itojun 
   1492        1.1    itojun 	case DIOCCHANGERULE: {
   1493        1.1    itojun 		struct pfioc_rule	*pcr = (struct pfioc_rule *)addr;
   1494        1.1    itojun 		struct pf_ruleset	*ruleset;
   1495        1.1    itojun 		struct pf_rule		*oldrule = NULL, *newrule = NULL;
   1496        1.1    itojun 		u_int32_t		 nr = 0;
   1497        1.1    itojun 		int			 rs_num;
   1498        1.1    itojun 
   1499        1.1    itojun 		if (!(pcr->action == PF_CHANGE_REMOVE ||
   1500        1.1    itojun 		    pcr->action == PF_CHANGE_GET_TICKET) &&
   1501        1.1    itojun 		    pcr->pool_ticket != ticket_pabuf) {
   1502        1.1    itojun 			error = EBUSY;
   1503        1.1    itojun 			break;
   1504        1.1    itojun 		}
   1505        1.1    itojun 
   1506        1.1    itojun 		if (pcr->action < PF_CHANGE_ADD_HEAD ||
   1507        1.1    itojun 		    pcr->action > PF_CHANGE_GET_TICKET) {
   1508        1.1    itojun 			error = EINVAL;
   1509        1.1    itojun 			break;
   1510        1.1    itojun 		}
   1511       1.12      yamt 		ruleset = pf_find_ruleset(pcr->anchor);
   1512        1.1    itojun 		if (ruleset == NULL) {
   1513        1.1    itojun 			error = EINVAL;
   1514        1.1    itojun 			break;
   1515        1.1    itojun 		}
   1516        1.1    itojun 		rs_num = pf_get_ruleset_number(pcr->rule.action);
   1517        1.1    itojun 		if (rs_num >= PF_RULESET_MAX) {
   1518        1.1    itojun 			error = EINVAL;
   1519        1.1    itojun 			break;
   1520        1.1    itojun 		}
   1521        1.1    itojun 
   1522        1.1    itojun 		if (pcr->action == PF_CHANGE_GET_TICKET) {
   1523        1.1    itojun 			pcr->ticket = ++ruleset->rules[rs_num].active.ticket;
   1524        1.1    itojun 			break;
   1525        1.1    itojun 		} else {
   1526        1.1    itojun 			if (pcr->ticket !=
   1527        1.1    itojun 			    ruleset->rules[rs_num].active.ticket) {
   1528        1.1    itojun 				error = EINVAL;
   1529        1.1    itojun 				break;
   1530        1.1    itojun 			}
   1531        1.1    itojun 			if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
   1532        1.1    itojun 				error = EINVAL;
   1533        1.1    itojun 				break;
   1534        1.1    itojun 			}
   1535        1.1    itojun 		}
   1536        1.1    itojun 
   1537        1.1    itojun 		if (pcr->action != PF_CHANGE_REMOVE) {
   1538        1.1    itojun 			newrule = pool_get(&pf_rule_pl, PR_NOWAIT);
   1539        1.1    itojun 			if (newrule == NULL) {
   1540        1.1    itojun 				error = ENOMEM;
   1541        1.1    itojun 				break;
   1542        1.1    itojun 			}
   1543        1.1    itojun 			bcopy(&pcr->rule, newrule, sizeof(struct pf_rule));
   1544        1.1    itojun 			TAILQ_INIT(&newrule->rpool.list);
   1545        1.1    itojun 			/* initialize refcounting */
   1546        1.1    itojun 			newrule->states = 0;
   1547        1.1    itojun 			newrule->entries.tqe_prev = NULL;
   1548        1.1    itojun #ifndef INET
   1549        1.1    itojun 			if (newrule->af == AF_INET) {
   1550        1.1    itojun 				pool_put(&pf_rule_pl, newrule);
   1551        1.1    itojun 				error = EAFNOSUPPORT;
   1552        1.1    itojun 				break;
   1553        1.1    itojun 			}
   1554        1.1    itojun #endif /* INET */
   1555        1.1    itojun #ifndef INET6
   1556        1.1    itojun 			if (newrule->af == AF_INET6) {
   1557        1.1    itojun 				pool_put(&pf_rule_pl, newrule);
   1558        1.1    itojun 				error = EAFNOSUPPORT;
   1559        1.1    itojun 				break;
   1560        1.1    itojun 			}
   1561        1.1    itojun #endif /* INET6 */
   1562        1.1    itojun 			if (newrule->ifname[0]) {
   1563        1.1    itojun 				newrule->kif = pfi_attach_rule(newrule->ifname);
   1564        1.1    itojun 				if (newrule->kif == NULL) {
   1565        1.1    itojun 					pool_put(&pf_rule_pl, newrule);
   1566        1.1    itojun 					error = EINVAL;
   1567        1.1    itojun 					break;
   1568        1.1    itojun 				}
   1569        1.1    itojun 			} else
   1570        1.1    itojun 				newrule->kif = NULL;
   1571        1.1    itojun 
   1572        1.1    itojun #ifdef ALTQ
   1573        1.1    itojun 			/* set queue IDs */
   1574        1.1    itojun 			if (newrule->qname[0] != 0) {
   1575        1.1    itojun 				if ((newrule->qid =
   1576        1.1    itojun 				    pf_qname2qid(newrule->qname)) == 0)
   1577        1.1    itojun 					error = EBUSY;
   1578        1.1    itojun 				else if (newrule->pqname[0] != 0) {
   1579        1.1    itojun 					if ((newrule->pqid =
   1580        1.1    itojun 					    pf_qname2qid(newrule->pqname)) == 0)
   1581        1.1    itojun 						error = EBUSY;
   1582        1.1    itojun 				} else
   1583        1.1    itojun 					newrule->pqid = newrule->qid;
   1584        1.1    itojun 			}
   1585       1.12      yamt #endif /* ALTQ */
   1586        1.1    itojun 			if (newrule->tagname[0])
   1587        1.1    itojun 				if ((newrule->tag =
   1588        1.1    itojun 				    pf_tagname2tag(newrule->tagname)) == 0)
   1589        1.1    itojun 					error = EBUSY;
   1590        1.1    itojun 			if (newrule->match_tagname[0])
   1591        1.1    itojun 				if ((newrule->match_tag = pf_tagname2tag(
   1592        1.1    itojun 				    newrule->match_tagname)) == 0)
   1593        1.1    itojun 					error = EBUSY;
   1594        1.1    itojun 			if (newrule->rt && !newrule->direction)
   1595        1.1    itojun 				error = EINVAL;
   1596       1.17     peter 			if (pf_rtlabel_add(&newrule->src.addr) ||
   1597       1.17     peter 			    pf_rtlabel_add(&newrule->dst.addr))
   1598       1.17     peter 				error = EBUSY;
   1599        1.1    itojun 			if (pfi_dynaddr_setup(&newrule->src.addr, newrule->af))
   1600        1.1    itojun 				error = EINVAL;
   1601        1.1    itojun 			if (pfi_dynaddr_setup(&newrule->dst.addr, newrule->af))
   1602        1.1    itojun 				error = EINVAL;
   1603        1.1    itojun 			if (pf_tbladdr_setup(ruleset, &newrule->src.addr))
   1604        1.1    itojun 				error = EINVAL;
   1605        1.1    itojun 			if (pf_tbladdr_setup(ruleset, &newrule->dst.addr))
   1606        1.1    itojun 				error = EINVAL;
   1607       1.12      yamt 			if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
   1608       1.12      yamt 				error = EINVAL;
   1609        1.1    itojun 
   1610       1.17     peter 			if (newrule->overload_tblname[0]) {
   1611       1.17     peter 				if ((newrule->overload_tbl = pfr_attach_table(
   1612       1.17     peter 				    ruleset, newrule->overload_tblname)) ==
   1613       1.17     peter 				    NULL)
   1614       1.17     peter 					error = EINVAL;
   1615       1.17     peter 				else
   1616       1.17     peter 					newrule->overload_tbl->pfrkt_flags |=
   1617       1.17     peter 					    PFR_TFLAG_ACTIVE;
   1618       1.17     peter 			}
   1619       1.17     peter 
   1620        1.1    itojun 			pf_mv_pool(&pf_pabuf, &newrule->rpool.list);
   1621        1.1    itojun 			if (((((newrule->action == PF_NAT) ||
   1622        1.1    itojun 			    (newrule->action == PF_RDR) ||
   1623        1.1    itojun 			    (newrule->action == PF_BINAT) ||
   1624        1.1    itojun 			    (newrule->rt > PF_FASTROUTE)) &&
   1625       1.12      yamt 			    !pcr->anchor[0])) &&
   1626        1.1    itojun 			    (TAILQ_FIRST(&newrule->rpool.list) == NULL))
   1627        1.1    itojun 				error = EINVAL;
   1628        1.1    itojun 
   1629        1.1    itojun 			if (error) {
   1630        1.1    itojun 				pf_rm_rule(NULL, newrule);
   1631        1.1    itojun 				break;
   1632        1.1    itojun 			}
   1633        1.1    itojun 			newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list);
   1634        1.1    itojun 			newrule->evaluations = newrule->packets = 0;
   1635        1.1    itojun 			newrule->bytes = 0;
   1636        1.1    itojun 		}
   1637        1.1    itojun 		pf_empty_pool(&pf_pabuf);
   1638        1.1    itojun 
   1639        1.1    itojun 		if (pcr->action == PF_CHANGE_ADD_HEAD)
   1640        1.1    itojun 			oldrule = TAILQ_FIRST(
   1641        1.1    itojun 			    ruleset->rules[rs_num].active.ptr);
   1642        1.1    itojun 		else if (pcr->action == PF_CHANGE_ADD_TAIL)
   1643        1.1    itojun 			oldrule = TAILQ_LAST(
   1644        1.1    itojun 			    ruleset->rules[rs_num].active.ptr, pf_rulequeue);
   1645        1.1    itojun 		else {
   1646        1.1    itojun 			oldrule = TAILQ_FIRST(
   1647        1.1    itojun 			    ruleset->rules[rs_num].active.ptr);
   1648        1.1    itojun 			while ((oldrule != NULL) && (oldrule->nr != pcr->nr))
   1649        1.1    itojun 				oldrule = TAILQ_NEXT(oldrule, entries);
   1650        1.1    itojun 			if (oldrule == NULL) {
   1651       1.12      yamt 				if (newrule != NULL)
   1652       1.12      yamt 					pf_rm_rule(NULL, newrule);
   1653        1.1    itojun 				error = EINVAL;
   1654        1.1    itojun 				break;
   1655        1.1    itojun 			}
   1656        1.1    itojun 		}
   1657        1.1    itojun 
   1658        1.1    itojun 		if (pcr->action == PF_CHANGE_REMOVE)
   1659        1.1    itojun 			pf_rm_rule(ruleset->rules[rs_num].active.ptr, oldrule);
   1660        1.1    itojun 		else {
   1661        1.1    itojun 			if (oldrule == NULL)
   1662        1.1    itojun 				TAILQ_INSERT_TAIL(
   1663        1.1    itojun 				    ruleset->rules[rs_num].active.ptr,
   1664        1.1    itojun 				    newrule, entries);
   1665        1.1    itojun 			else if (pcr->action == PF_CHANGE_ADD_HEAD ||
   1666        1.1    itojun 			    pcr->action == PF_CHANGE_ADD_BEFORE)
   1667        1.1    itojun 				TAILQ_INSERT_BEFORE(oldrule, newrule, entries);
   1668        1.1    itojun 			else
   1669        1.1    itojun 				TAILQ_INSERT_AFTER(
   1670        1.1    itojun 				    ruleset->rules[rs_num].active.ptr,
   1671        1.1    itojun 				    oldrule, newrule, entries);
   1672        1.1    itojun 		}
   1673        1.1    itojun 
   1674        1.1    itojun 		nr = 0;
   1675        1.1    itojun 		TAILQ_FOREACH(oldrule,
   1676        1.1    itojun 		    ruleset->rules[rs_num].active.ptr, entries)
   1677        1.1    itojun 			oldrule->nr = nr++;
   1678        1.1    itojun 
   1679       1.12      yamt 		ruleset->rules[rs_num].active.ticket++;
   1680       1.12      yamt 
   1681        1.1    itojun 		pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
   1682        1.1    itojun 		pf_remove_if_empty_ruleset(ruleset);
   1683        1.1    itojun 
   1684        1.1    itojun 		break;
   1685        1.1    itojun 	}
   1686        1.1    itojun 
   1687        1.1    itojun 	case DIOCCLRSTATES: {
   1688        1.1    itojun 		struct pf_state		*state;
   1689        1.1    itojun 		struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
   1690        1.1    itojun 		int			 killed = 0;
   1691        1.1    itojun 
   1692        1.1    itojun 		RB_FOREACH(state, pf_state_tree_id, &tree_id) {
   1693        1.1    itojun 			if (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
   1694        1.1    itojun 			    state->u.s.kif->pfik_name)) {
   1695        1.1    itojun 				state->timeout = PFTM_PURGE;
   1696        1.1    itojun #if NPFSYNC
   1697        1.1    itojun 				/* don't send out individual delete messages */
   1698        1.1    itojun 				state->sync_flags = PFSTATE_NOSYNC;
   1699        1.1    itojun #endif
   1700        1.1    itojun 				killed++;
   1701        1.1    itojun 			}
   1702        1.1    itojun 		}
   1703        1.1    itojun 		pf_purge_expired_states();
   1704        1.1    itojun 		pf_status.states = 0;
   1705        1.1    itojun 		psk->psk_af = killed;
   1706        1.1    itojun #if NPFSYNC
   1707        1.1    itojun 		pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
   1708        1.1    itojun #endif
   1709        1.1    itojun 		break;
   1710        1.1    itojun 	}
   1711        1.1    itojun 
   1712        1.1    itojun 	case DIOCKILLSTATES: {
   1713        1.1    itojun 		struct pf_state		*state;
   1714        1.1    itojun 		struct pfioc_state_kill	*psk = (struct pfioc_state_kill *)addr;
   1715        1.1    itojun 		int			 killed = 0;
   1716        1.1    itojun 
   1717        1.1    itojun 		RB_FOREACH(state, pf_state_tree_id, &tree_id) {
   1718        1.1    itojun 			if ((!psk->psk_af || state->af == psk->psk_af)
   1719        1.1    itojun 			    && (!psk->psk_proto || psk->psk_proto ==
   1720        1.1    itojun 			    state->proto) &&
   1721       1.12      yamt 			    PF_MATCHA(psk->psk_src.neg,
   1722        1.1    itojun 			    &psk->psk_src.addr.v.a.addr,
   1723        1.1    itojun 			    &psk->psk_src.addr.v.a.mask,
   1724        1.1    itojun 			    &state->lan.addr, state->af) &&
   1725       1.12      yamt 			    PF_MATCHA(psk->psk_dst.neg,
   1726        1.1    itojun 			    &psk->psk_dst.addr.v.a.addr,
   1727        1.1    itojun 			    &psk->psk_dst.addr.v.a.mask,
   1728        1.1    itojun 			    &state->ext.addr, state->af) &&
   1729        1.1    itojun 			    (psk->psk_src.port_op == 0 ||
   1730        1.1    itojun 			    pf_match_port(psk->psk_src.port_op,
   1731        1.1    itojun 			    psk->psk_src.port[0], psk->psk_src.port[1],
   1732        1.1    itojun 			    state->lan.port)) &&
   1733        1.1    itojun 			    (psk->psk_dst.port_op == 0 ||
   1734        1.1    itojun 			    pf_match_port(psk->psk_dst.port_op,
   1735        1.1    itojun 			    psk->psk_dst.port[0], psk->psk_dst.port[1],
   1736        1.1    itojun 			    state->ext.port)) &&
   1737        1.1    itojun 			    (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
   1738        1.1    itojun 			    state->u.s.kif->pfik_name))) {
   1739        1.1    itojun 				state->timeout = PFTM_PURGE;
   1740        1.1    itojun 				killed++;
   1741        1.1    itojun 			}
   1742        1.1    itojun 		}
   1743        1.1    itojun 		pf_purge_expired_states();
   1744        1.1    itojun 		psk->psk_af = killed;
   1745        1.1    itojun 		break;
   1746        1.1    itojun 	}
   1747        1.1    itojun 
   1748        1.1    itojun 	case DIOCADDSTATE: {
   1749        1.1    itojun 		struct pfioc_state	*ps = (struct pfioc_state *)addr;
   1750        1.1    itojun 		struct pf_state		*state;
   1751        1.1    itojun 		struct pfi_kif		*kif;
   1752        1.1    itojun 
   1753        1.1    itojun 		if (ps->state.timeout >= PFTM_MAX &&
   1754        1.1    itojun 		    ps->state.timeout != PFTM_UNTIL_PACKET) {
   1755        1.1    itojun 			error = EINVAL;
   1756        1.1    itojun 			break;
   1757        1.1    itojun 		}
   1758        1.1    itojun 		state = pool_get(&pf_state_pl, PR_NOWAIT);
   1759        1.1    itojun 		if (state == NULL) {
   1760        1.1    itojun 			error = ENOMEM;
   1761        1.1    itojun 			break;
   1762        1.1    itojun 		}
   1763        1.1    itojun 		kif = pfi_lookup_create(ps->state.u.ifname);
   1764        1.1    itojun 		if (kif == NULL) {
   1765        1.1    itojun 			pool_put(&pf_state_pl, state);
   1766        1.1    itojun 			error = ENOENT;
   1767        1.1    itojun 			break;
   1768        1.1    itojun 		}
   1769        1.1    itojun 		bcopy(&ps->state, state, sizeof(struct pf_state));
   1770        1.1    itojun 		bzero(&state->u, sizeof(state->u));
   1771        1.1    itojun 		state->rule.ptr = &pf_default_rule;
   1772        1.1    itojun 		state->nat_rule.ptr = NULL;
   1773        1.1    itojun 		state->anchor.ptr = NULL;
   1774        1.1    itojun 		state->rt_kif = NULL;
   1775       1.12      yamt 		state->creation = time_second;
   1776        1.1    itojun 		state->pfsync_time = 0;
   1777        1.1    itojun 		state->packets[0] = state->packets[1] = 0;
   1778        1.1    itojun 		state->bytes[0] = state->bytes[1] = 0;
   1779        1.1    itojun 
   1780        1.1    itojun 		if (pf_insert_state(kif, state)) {
   1781        1.1    itojun 			pfi_maybe_destroy(kif);
   1782        1.1    itojun 			pool_put(&pf_state_pl, state);
   1783        1.1    itojun 			error = ENOMEM;
   1784        1.1    itojun 		}
   1785        1.1    itojun 		break;
   1786        1.1    itojun 	}
   1787        1.1    itojun 
   1788        1.1    itojun 	case DIOCGETSTATE: {
   1789        1.1    itojun 		struct pfioc_state	*ps = (struct pfioc_state *)addr;
   1790        1.1    itojun 		struct pf_state		*state;
   1791        1.1    itojun 		u_int32_t		 nr;
   1792        1.1    itojun 
   1793        1.1    itojun 		nr = 0;
   1794        1.1    itojun 		RB_FOREACH(state, pf_state_tree_id, &tree_id) {
   1795        1.1    itojun 			if (nr >= ps->nr)
   1796        1.1    itojun 				break;
   1797        1.1    itojun 			nr++;
   1798        1.1    itojun 		}
   1799        1.1    itojun 		if (state == NULL) {
   1800        1.1    itojun 			error = EBUSY;
   1801        1.1    itojun 			break;
   1802        1.1    itojun 		}
   1803        1.1    itojun 		bcopy(state, &ps->state, sizeof(struct pf_state));
   1804        1.1    itojun 		ps->state.rule.nr = state->rule.ptr->nr;
   1805        1.1    itojun 		ps->state.nat_rule.nr = (state->nat_rule.ptr == NULL) ?
   1806        1.1    itojun 		    -1 : state->nat_rule.ptr->nr;
   1807        1.1    itojun 		ps->state.anchor.nr = (state->anchor.ptr == NULL) ?
   1808        1.1    itojun 		    -1 : state->anchor.ptr->nr;
   1809        1.1    itojun 		ps->state.expire = pf_state_expires(state);
   1810       1.12      yamt 		if (ps->state.expire > time_second)
   1811       1.12      yamt 			ps->state.expire -= time_second;
   1812        1.1    itojun 		else
   1813        1.1    itojun 			ps->state.expire = 0;
   1814        1.1    itojun 		break;
   1815        1.1    itojun 	}
   1816        1.1    itojun 
   1817        1.1    itojun 	case DIOCGETSTATES: {
   1818        1.1    itojun 		struct pfioc_states	*ps = (struct pfioc_states *)addr;
   1819        1.1    itojun 		struct pf_state		*state;
   1820        1.1    itojun 		struct pf_state		*p, pstore;
   1821        1.1    itojun 		struct pfi_kif		*kif;
   1822        1.1    itojun 		u_int32_t		 nr = 0;
   1823        1.1    itojun 		int			 space = ps->ps_len;
   1824        1.1    itojun 
   1825        1.1    itojun 		if (space == 0) {
   1826        1.1    itojun 			TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states)
   1827        1.1    itojun 				nr += kif->pfik_states;
   1828        1.1    itojun 			ps->ps_len = sizeof(struct pf_state) * nr;
   1829       1.15     peter 			break;
   1830        1.1    itojun 		}
   1831        1.1    itojun 
   1832        1.1    itojun 		p = ps->ps_states;
   1833        1.1    itojun 		TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states)
   1834        1.1    itojun 			RB_FOREACH(state, pf_state_tree_ext_gwy,
   1835        1.1    itojun 			    &kif->pfik_ext_gwy) {
   1836       1.12      yamt 				int	secs = time_second;
   1837        1.1    itojun 
   1838        1.1    itojun 				if ((nr+1) * sizeof(*p) > (unsigned)ps->ps_len)
   1839        1.1    itojun 					break;
   1840        1.1    itojun 
   1841        1.1    itojun 				bcopy(state, &pstore, sizeof(pstore));
   1842        1.1    itojun 				strlcpy(pstore.u.ifname, kif->pfik_name,
   1843        1.1    itojun 				    sizeof(pstore.u.ifname));
   1844        1.1    itojun 				pstore.rule.nr = state->rule.ptr->nr;
   1845        1.1    itojun 				pstore.nat_rule.nr = (state->nat_rule.ptr ==
   1846        1.1    itojun 				    NULL) ? -1 : state->nat_rule.ptr->nr;
   1847        1.1    itojun 				pstore.anchor.nr = (state->anchor.ptr ==
   1848        1.1    itojun 				    NULL) ? -1 : state->anchor.ptr->nr;
   1849        1.1    itojun 				pstore.creation = secs - pstore.creation;
   1850        1.1    itojun 				pstore.expire = pf_state_expires(state);
   1851        1.1    itojun 				if (pstore.expire > secs)
   1852        1.1    itojun 					pstore.expire -= secs;
   1853        1.1    itojun 				else
   1854        1.1    itojun 					pstore.expire = 0;
   1855        1.1    itojun 				error = copyout(&pstore, p, sizeof(*p));
   1856       1.15     peter 				if (error)
   1857        1.1    itojun 					goto fail;
   1858        1.1    itojun 				p++;
   1859        1.1    itojun 				nr++;
   1860        1.1    itojun 			}
   1861        1.1    itojun 		ps->ps_len = sizeof(struct pf_state) * nr;
   1862        1.1    itojun 		break;
   1863        1.1    itojun 	}
   1864        1.1    itojun 
   1865        1.1    itojun 	case DIOCGETSTATUS: {
   1866        1.1    itojun 		struct pf_status *s = (struct pf_status *)addr;
   1867        1.1    itojun 		bcopy(&pf_status, s, sizeof(struct pf_status));
   1868        1.1    itojun 		pfi_fill_oldstatus(s);
   1869        1.1    itojun 		break;
   1870        1.1    itojun 	}
   1871        1.1    itojun 
   1872        1.1    itojun 	case DIOCSETSTATUSIF: {
   1873        1.1    itojun 		struct pfioc_if	*pi = (struct pfioc_if *)addr;
   1874        1.1    itojun 
   1875        1.1    itojun 		if (pi->ifname[0] == 0) {
   1876        1.1    itojun 			bzero(pf_status.ifname, IFNAMSIZ);
   1877        1.1    itojun 			break;
   1878        1.1    itojun 		}
   1879        1.1    itojun 		if (ifunit(pi->ifname) == NULL) {
   1880        1.1    itojun 			error = EINVAL;
   1881        1.1    itojun 			break;
   1882        1.1    itojun 		}
   1883        1.1    itojun 		strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ);
   1884        1.1    itojun 		break;
   1885        1.1    itojun 	}
   1886        1.1    itojun 
   1887        1.1    itojun 	case DIOCCLRSTATUS: {
   1888        1.1    itojun 		bzero(pf_status.counters, sizeof(pf_status.counters));
   1889        1.1    itojun 		bzero(pf_status.fcounters, sizeof(pf_status.fcounters));
   1890        1.1    itojun 		bzero(pf_status.scounters, sizeof(pf_status.scounters));
   1891        1.1    itojun 		if (*pf_status.ifname)
   1892        1.1    itojun 			pfi_clr_istats(pf_status.ifname, NULL,
   1893        1.1    itojun 			    PFI_FLAG_INSTANCE);
   1894        1.1    itojun 		break;
   1895        1.1    itojun 	}
   1896        1.1    itojun 
   1897        1.1    itojun 	case DIOCNATLOOK: {
   1898        1.1    itojun 		struct pfioc_natlook	*pnl = (struct pfioc_natlook *)addr;
   1899        1.1    itojun 		struct pf_state		*state;
   1900        1.1    itojun 		struct pf_state		 key;
   1901        1.1    itojun 		int			 m = 0, direction = pnl->direction;
   1902        1.1    itojun 
   1903        1.1    itojun 		key.af = pnl->af;
   1904        1.1    itojun 		key.proto = pnl->proto;
   1905        1.1    itojun 
   1906        1.1    itojun 		if (!pnl->proto ||
   1907        1.1    itojun 		    PF_AZERO(&pnl->saddr, pnl->af) ||
   1908        1.1    itojun 		    PF_AZERO(&pnl->daddr, pnl->af) ||
   1909        1.1    itojun 		    !pnl->dport || !pnl->sport)
   1910        1.1    itojun 			error = EINVAL;
   1911        1.1    itojun 		else {
   1912        1.1    itojun 			/*
   1913        1.1    itojun 			 * userland gives us source and dest of connection,
   1914        1.1    itojun 			 * reverse the lookup so we ask for what happens with
   1915        1.1    itojun 			 * the return traffic, enabling us to find it in the
   1916        1.1    itojun 			 * state tree.
   1917        1.1    itojun 			 */
   1918        1.1    itojun 			if (direction == PF_IN) {
   1919        1.1    itojun 				PF_ACPY(&key.ext.addr, &pnl->daddr, pnl->af);
   1920        1.1    itojun 				key.ext.port = pnl->dport;
   1921        1.1    itojun 				PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af);
   1922        1.1    itojun 				key.gwy.port = pnl->sport;
   1923        1.1    itojun 				state = pf_find_state_all(&key, PF_EXT_GWY, &m);
   1924        1.1    itojun 			} else {
   1925        1.1    itojun 				PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af);
   1926        1.1    itojun 				key.lan.port = pnl->dport;
   1927        1.1    itojun 				PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af);
   1928        1.1    itojun 				key.ext.port = pnl->sport;
   1929        1.1    itojun 				state = pf_find_state_all(&key, PF_LAN_EXT, &m);
   1930        1.1    itojun 			}
   1931        1.1    itojun 			if (m > 1)
   1932        1.1    itojun 				error = E2BIG;	/* more than one state */
   1933        1.1    itojun 			else if (state != NULL) {
   1934        1.1    itojun 				if (direction == PF_IN) {
   1935        1.1    itojun 					PF_ACPY(&pnl->rsaddr, &state->lan.addr,
   1936        1.1    itojun 					    state->af);
   1937        1.1    itojun 					pnl->rsport = state->lan.port;
   1938        1.1    itojun 					PF_ACPY(&pnl->rdaddr, &pnl->daddr,
   1939        1.1    itojun 					    pnl->af);
   1940        1.1    itojun 					pnl->rdport = pnl->dport;
   1941        1.1    itojun 				} else {
   1942        1.1    itojun 					PF_ACPY(&pnl->rdaddr, &state->gwy.addr,
   1943        1.1    itojun 					    state->af);
   1944        1.1    itojun 					pnl->rdport = state->gwy.port;
   1945        1.1    itojun 					PF_ACPY(&pnl->rsaddr, &pnl->saddr,
   1946        1.1    itojun 					    pnl->af);
   1947        1.1    itojun 					pnl->rsport = pnl->sport;
   1948        1.1    itojun 				}
   1949        1.1    itojun 			} else
   1950        1.1    itojun 				error = ENOENT;
   1951        1.1    itojun 		}
   1952        1.1    itojun 		break;
   1953        1.1    itojun 	}
   1954        1.1    itojun 
   1955        1.1    itojun 	case DIOCSETTIMEOUT: {
   1956        1.1    itojun 		struct pfioc_tm	*pt = (struct pfioc_tm *)addr;
   1957        1.1    itojun 		int		 old;
   1958        1.1    itojun 
   1959        1.1    itojun 		if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
   1960        1.1    itojun 		    pt->seconds < 0) {
   1961        1.1    itojun 			error = EINVAL;
   1962        1.1    itojun 			goto fail;
   1963        1.1    itojun 		}
   1964        1.1    itojun 		old = pf_default_rule.timeout[pt->timeout];
   1965        1.1    itojun 		pf_default_rule.timeout[pt->timeout] = pt->seconds;
   1966        1.1    itojun 		pt->seconds = old;
   1967        1.1    itojun 		break;
   1968        1.1    itojun 	}
   1969        1.1    itojun 
   1970        1.1    itojun 	case DIOCGETTIMEOUT: {
   1971        1.1    itojun 		struct pfioc_tm	*pt = (struct pfioc_tm *)addr;
   1972        1.1    itojun 
   1973        1.1    itojun 		if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
   1974        1.1    itojun 			error = EINVAL;
   1975        1.1    itojun 			goto fail;
   1976        1.1    itojun 		}
   1977        1.1    itojun 		pt->seconds = pf_default_rule.timeout[pt->timeout];
   1978        1.1    itojun 		break;
   1979        1.1    itojun 	}
   1980        1.1    itojun 
   1981        1.1    itojun 	case DIOCGETLIMIT: {
   1982        1.1    itojun 		struct pfioc_limit	*pl = (struct pfioc_limit *)addr;
   1983        1.1    itojun 
   1984        1.1    itojun 		if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
   1985        1.1    itojun 			error = EINVAL;
   1986        1.1    itojun 			goto fail;
   1987        1.1    itojun 		}
   1988        1.1    itojun 		pl->limit = pf_pool_limits[pl->index].limit;
   1989        1.1    itojun 		break;
   1990        1.1    itojun 	}
   1991        1.1    itojun 
   1992        1.1    itojun 	case DIOCSETLIMIT: {
   1993        1.1    itojun 		struct pfioc_limit	*pl = (struct pfioc_limit *)addr;
   1994        1.1    itojun 		int			 old_limit;
   1995        1.1    itojun 
   1996        1.1    itojun 		if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
   1997        1.1    itojun 		    pf_pool_limits[pl->index].pp == NULL) {
   1998        1.1    itojun 			error = EINVAL;
   1999        1.1    itojun 			goto fail;
   2000        1.1    itojun 		}
   2001        1.2    itojun #ifdef __OpenBSD__
   2002        1.1    itojun 		if (pool_sethardlimit(pf_pool_limits[pl->index].pp,
   2003        1.1    itojun 		    pl->limit, NULL, 0) != 0) {
   2004        1.1    itojun 			error = EBUSY;
   2005        1.1    itojun 			goto fail;
   2006        1.1    itojun 		}
   2007        1.2    itojun #else
   2008        1.2    itojun 		pool_sethardlimit(pf_pool_limits[pl->index].pp,
   2009        1.2    itojun 		    pl->limit, NULL, 0);
   2010        1.2    itojun #endif
   2011        1.1    itojun 		old_limit = pf_pool_limits[pl->index].limit;
   2012        1.1    itojun 		pf_pool_limits[pl->index].limit = pl->limit;
   2013        1.1    itojun 		pl->limit = old_limit;
   2014        1.1    itojun 		break;
   2015        1.1    itojun 	}
   2016        1.1    itojun 
   2017        1.1    itojun 	case DIOCSETDEBUG: {
   2018        1.1    itojun 		u_int32_t	*level = (u_int32_t *)addr;
   2019        1.1    itojun 
   2020        1.1    itojun 		pf_status.debug = *level;
   2021        1.1    itojun 		break;
   2022        1.1    itojun 	}
   2023        1.1    itojun 
   2024        1.1    itojun 	case DIOCCLRRULECTRS: {
   2025        1.1    itojun 		struct pf_ruleset	*ruleset = &pf_main_ruleset;
   2026        1.1    itojun 		struct pf_rule		*rule;
   2027        1.1    itojun 
   2028        1.1    itojun 		TAILQ_FOREACH(rule,
   2029        1.1    itojun 		    ruleset->rules[PF_RULESET_FILTER].active.ptr, entries)
   2030        1.1    itojun 			rule->evaluations = rule->packets =
   2031        1.1    itojun 			    rule->bytes = 0;
   2032        1.1    itojun 		break;
   2033        1.1    itojun 	}
   2034        1.1    itojun 
   2035        1.1    itojun #ifdef ALTQ
   2036        1.1    itojun 	case DIOCSTARTALTQ: {
   2037        1.1    itojun 		struct pf_altq		*altq;
   2038        1.1    itojun 
   2039        1.1    itojun 		/* enable all altq interfaces on active list */
   2040        1.1    itojun 		TAILQ_FOREACH(altq, pf_altqs_active, entries) {
   2041        1.1    itojun 			if (altq->qname[0] == 0) {
   2042       1.12      yamt 				error = pf_enable_altq(altq);
   2043        1.1    itojun 				if (error != 0)
   2044        1.1    itojun 					break;
   2045        1.1    itojun 			}
   2046        1.1    itojun 		}
   2047        1.1    itojun 		if (error == 0)
   2048       1.12      yamt 			pf_altq_running = 1;
   2049        1.1    itojun 		DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
   2050        1.1    itojun 		break;
   2051        1.1    itojun 	}
   2052        1.1    itojun 
   2053        1.1    itojun 	case DIOCSTOPALTQ: {
   2054        1.1    itojun 		struct pf_altq		*altq;
   2055        1.1    itojun 
   2056        1.1    itojun 		/* disable all altq interfaces on active list */
   2057        1.1    itojun 		TAILQ_FOREACH(altq, pf_altqs_active, entries) {
   2058        1.1    itojun 			if (altq->qname[0] == 0) {
   2059       1.12      yamt 				error = pf_disable_altq(altq);
   2060       1.12      yamt 				if (error != 0)
   2061        1.1    itojun 					break;
   2062        1.1    itojun 			}
   2063        1.1    itojun 		}
   2064        1.1    itojun 		if (error == 0)
   2065       1.12      yamt 			pf_altq_running = 0;
   2066        1.1    itojun 		DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
   2067        1.1    itojun 		break;
   2068        1.1    itojun 	}
   2069        1.1    itojun 
   2070        1.1    itojun 	case DIOCADDALTQ: {
   2071        1.1    itojun 		struct pfioc_altq	*pa = (struct pfioc_altq *)addr;
   2072        1.1    itojun 		struct pf_altq		*altq, *a;
   2073        1.1    itojun 
   2074        1.1    itojun 		if (pa->ticket != ticket_altqs_inactive) {
   2075        1.1    itojun 			error = EBUSY;
   2076        1.1    itojun 			break;
   2077        1.1    itojun 		}
   2078        1.1    itojun 		altq = pool_get(&pf_altq_pl, PR_NOWAIT);
   2079        1.1    itojun 		if (altq == NULL) {
   2080        1.1    itojun 			error = ENOMEM;
   2081        1.1    itojun 			break;
   2082        1.1    itojun 		}
   2083        1.1    itojun 		bcopy(&pa->altq, altq, sizeof(struct pf_altq));
   2084        1.1    itojun 
   2085        1.1    itojun 		/*
   2086        1.1    itojun 		 * if this is for a queue, find the discipline and
   2087        1.1    itojun 		 * copy the necessary fields
   2088        1.1    itojun 		 */
   2089        1.1    itojun 		if (altq->qname[0] != 0) {
   2090        1.1    itojun 			if ((altq->qid = pf_qname2qid(altq->qname)) == 0) {
   2091        1.1    itojun 				error = EBUSY;
   2092        1.1    itojun 				pool_put(&pf_altq_pl, altq);
   2093        1.1    itojun 				break;
   2094        1.1    itojun 			}
   2095        1.1    itojun 			TAILQ_FOREACH(a, pf_altqs_inactive, entries) {
   2096        1.1    itojun 				if (strncmp(a->ifname, altq->ifname,
   2097        1.1    itojun 				    IFNAMSIZ) == 0 && a->qname[0] == 0) {
   2098        1.1    itojun 					altq->altq_disc = a->altq_disc;
   2099        1.1    itojun 					break;
   2100        1.1    itojun 				}
   2101        1.1    itojun 			}
   2102        1.1    itojun 		}
   2103        1.1    itojun 
   2104        1.1    itojun 		error = altq_add(altq);
   2105        1.1    itojun 		if (error) {
   2106        1.1    itojun 			pool_put(&pf_altq_pl, altq);
   2107        1.1    itojun 			break;
   2108        1.1    itojun 		}
   2109        1.1    itojun 
   2110        1.1    itojun 		TAILQ_INSERT_TAIL(pf_altqs_inactive, altq, entries);
   2111        1.1    itojun 		bcopy(altq, &pa->altq, sizeof(struct pf_altq));
   2112        1.1    itojun 		break;
   2113        1.1    itojun 	}
   2114        1.1    itojun 
   2115        1.1    itojun 	case DIOCGETALTQS: {
   2116        1.1    itojun 		struct pfioc_altq	*pa = (struct pfioc_altq *)addr;
   2117        1.1    itojun 		struct pf_altq		*altq;
   2118        1.1    itojun 
   2119        1.1    itojun 		pa->nr = 0;
   2120        1.1    itojun 		TAILQ_FOREACH(altq, pf_altqs_active, entries)
   2121        1.1    itojun 			pa->nr++;
   2122        1.1    itojun 		pa->ticket = ticket_altqs_active;
   2123        1.1    itojun 		break;
   2124        1.1    itojun 	}
   2125        1.1    itojun 
   2126        1.1    itojun 	case DIOCGETALTQ: {
   2127        1.1    itojun 		struct pfioc_altq	*pa = (struct pfioc_altq *)addr;
   2128        1.1    itojun 		struct pf_altq		*altq;
   2129        1.1    itojun 		u_int32_t		 nr;
   2130        1.1    itojun 
   2131        1.1    itojun 		if (pa->ticket != ticket_altqs_active) {
   2132        1.1    itojun 			error = EBUSY;
   2133        1.1    itojun 			break;
   2134        1.1    itojun 		}
   2135        1.1    itojun 		nr = 0;
   2136        1.1    itojun 		altq = TAILQ_FIRST(pf_altqs_active);
   2137        1.1    itojun 		while ((altq != NULL) && (nr < pa->nr)) {
   2138        1.1    itojun 			altq = TAILQ_NEXT(altq, entries);
   2139        1.1    itojun 			nr++;
   2140        1.1    itojun 		}
   2141        1.1    itojun 		if (altq == NULL) {
   2142        1.1    itojun 			error = EBUSY;
   2143        1.1    itojun 			break;
   2144        1.1    itojun 		}
   2145        1.1    itojun 		bcopy(altq, &pa->altq, sizeof(struct pf_altq));
   2146        1.1    itojun 		break;
   2147        1.1    itojun 	}
   2148        1.1    itojun 
   2149        1.1    itojun 	case DIOCCHANGEALTQ:
   2150        1.1    itojun 		/* CHANGEALTQ not supported yet! */
   2151        1.1    itojun 		error = ENODEV;
   2152        1.1    itojun 		break;
   2153        1.1    itojun 
   2154        1.1    itojun 	case DIOCGETQSTATS: {
   2155        1.1    itojun 		struct pfioc_qstats	*pq = (struct pfioc_qstats *)addr;
   2156        1.1    itojun 		struct pf_altq		*altq;
   2157        1.1    itojun 		u_int32_t		 nr;
   2158        1.1    itojun 		int			 nbytes;
   2159        1.1    itojun 
   2160        1.1    itojun 		if (pq->ticket != ticket_altqs_active) {
   2161        1.1    itojun 			error = EBUSY;
   2162        1.1    itojun 			break;
   2163        1.1    itojun 		}
   2164        1.1    itojun 		nbytes = pq->nbytes;
   2165        1.1    itojun 		nr = 0;
   2166        1.1    itojun 		altq = TAILQ_FIRST(pf_altqs_active);
   2167        1.1    itojun 		while ((altq != NULL) && (nr < pq->nr)) {
   2168        1.1    itojun 			altq = TAILQ_NEXT(altq, entries);
   2169        1.1    itojun 			nr++;
   2170        1.1    itojun 		}
   2171        1.1    itojun 		if (altq == NULL) {
   2172        1.1    itojun 			error = EBUSY;
   2173        1.1    itojun 			break;
   2174        1.1    itojun 		}
   2175        1.1    itojun 		error = altq_getqstats(altq, pq->buf, &nbytes);
   2176        1.1    itojun 		if (error == 0) {
   2177        1.1    itojun 			pq->scheduler = altq->scheduler;
   2178        1.1    itojun 			pq->nbytes = nbytes;
   2179        1.1    itojun 		}
   2180        1.1    itojun 		break;
   2181        1.1    itojun 	}
   2182        1.1    itojun #endif /* ALTQ */
   2183        1.1    itojun 
   2184        1.1    itojun 	case DIOCBEGINADDRS: {
   2185        1.1    itojun 		struct pfioc_pooladdr	*pp = (struct pfioc_pooladdr *)addr;
   2186        1.1    itojun 
   2187        1.1    itojun 		pf_empty_pool(&pf_pabuf);
   2188        1.1    itojun 		pp->ticket = ++ticket_pabuf;
   2189        1.1    itojun 		break;
   2190        1.1    itojun 	}
   2191        1.1    itojun 
   2192        1.1    itojun 	case DIOCADDADDR: {
   2193        1.1    itojun 		struct pfioc_pooladdr	*pp = (struct pfioc_pooladdr *)addr;
   2194        1.1    itojun 
   2195        1.1    itojun #ifndef INET
   2196        1.1    itojun 		if (pp->af == AF_INET) {
   2197        1.1    itojun 			error = EAFNOSUPPORT;
   2198        1.1    itojun 			break;
   2199        1.1    itojun 		}
   2200        1.1    itojun #endif /* INET */
   2201        1.1    itojun #ifndef INET6
   2202        1.1    itojun 		if (pp->af == AF_INET6) {
   2203        1.1    itojun 			error = EAFNOSUPPORT;
   2204        1.1    itojun 			break;
   2205        1.1    itojun 		}
   2206        1.1    itojun #endif /* INET6 */
   2207        1.1    itojun 		if (pp->addr.addr.type != PF_ADDR_ADDRMASK &&
   2208        1.1    itojun 		    pp->addr.addr.type != PF_ADDR_DYNIFTL &&
   2209        1.1    itojun 		    pp->addr.addr.type != PF_ADDR_TABLE) {
   2210        1.1    itojun 			error = EINVAL;
   2211        1.1    itojun 			break;
   2212        1.1    itojun 		}
   2213        1.1    itojun 		pa = pool_get(&pf_pooladdr_pl, PR_NOWAIT);
   2214        1.1    itojun 		if (pa == NULL) {
   2215        1.1    itojun 			error = ENOMEM;
   2216        1.1    itojun 			break;
   2217        1.1    itojun 		}
   2218        1.1    itojun 		bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr));
   2219        1.1    itojun 		if (pa->ifname[0]) {
   2220        1.1    itojun 			pa->kif = pfi_attach_rule(pa->ifname);
   2221        1.1    itojun 			if (pa->kif == NULL) {
   2222        1.1    itojun 				pool_put(&pf_pooladdr_pl, pa);
   2223        1.1    itojun 				error = EINVAL;
   2224        1.1    itojun 				break;
   2225        1.1    itojun 			}
   2226        1.1    itojun 		}
   2227        1.1    itojun 		if (pfi_dynaddr_setup(&pa->addr, pp->af)) {
   2228        1.1    itojun 			pfi_dynaddr_remove(&pa->addr);
   2229        1.1    itojun 			pfi_detach_rule(pa->kif);
   2230        1.1    itojun 			pool_put(&pf_pooladdr_pl, pa);
   2231        1.1    itojun 			error = EINVAL;
   2232        1.1    itojun 			break;
   2233        1.1    itojun 		}
   2234        1.1    itojun 		TAILQ_INSERT_TAIL(&pf_pabuf, pa, entries);
   2235        1.1    itojun 		break;
   2236        1.1    itojun 	}
   2237        1.1    itojun 
   2238        1.1    itojun 	case DIOCGETADDRS: {
   2239        1.1    itojun 		struct pfioc_pooladdr	*pp = (struct pfioc_pooladdr *)addr;
   2240        1.1    itojun 
   2241        1.1    itojun 		pp->nr = 0;
   2242       1.12      yamt 		pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
   2243       1.12      yamt 		    pp->r_num, 0, 1, 0);
   2244        1.1    itojun 		if (pool == NULL) {
   2245        1.1    itojun 			error = EBUSY;
   2246        1.1    itojun 			break;
   2247        1.1    itojun 		}
   2248        1.1    itojun 		TAILQ_FOREACH(pa, &pool->list, entries)
   2249        1.1    itojun 			pp->nr++;
   2250        1.1    itojun 		break;
   2251        1.1    itojun 	}
   2252        1.1    itojun 
   2253        1.1    itojun 	case DIOCGETADDR: {
   2254        1.1    itojun 		struct pfioc_pooladdr	*pp = (struct pfioc_pooladdr *)addr;
   2255        1.1    itojun 		u_int32_t		 nr = 0;
   2256        1.1    itojun 
   2257       1.12      yamt 		pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
   2258       1.12      yamt 		    pp->r_num, 0, 1, 1);
   2259        1.1    itojun 		if (pool == NULL) {
   2260        1.1    itojun 			error = EBUSY;
   2261        1.1    itojun 			break;
   2262        1.1    itojun 		}
   2263        1.1    itojun 		pa = TAILQ_FIRST(&pool->list);
   2264        1.1    itojun 		while ((pa != NULL) && (nr < pp->nr)) {
   2265        1.1    itojun 			pa = TAILQ_NEXT(pa, entries);
   2266        1.1    itojun 			nr++;
   2267        1.1    itojun 		}
   2268        1.1    itojun 		if (pa == NULL) {
   2269        1.1    itojun 			error = EBUSY;
   2270        1.1    itojun 			break;
   2271        1.1    itojun 		}
   2272        1.1    itojun 		bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr));
   2273        1.1    itojun 		pfi_dynaddr_copyout(&pp->addr.addr);
   2274        1.1    itojun 		pf_tbladdr_copyout(&pp->addr.addr);
   2275       1.17     peter 		pf_rtlabel_copyout(&pp->addr.addr);
   2276        1.1    itojun 		break;
   2277        1.1    itojun 	}
   2278        1.1    itojun 
   2279        1.1    itojun 	case DIOCCHANGEADDR: {
   2280        1.1    itojun 		struct pfioc_pooladdr	*pca = (struct pfioc_pooladdr *)addr;
   2281        1.1    itojun 		struct pf_pooladdr	*oldpa = NULL, *newpa = NULL;
   2282        1.1    itojun 		struct pf_ruleset	*ruleset;
   2283        1.1    itojun 
   2284        1.1    itojun 		if (pca->action < PF_CHANGE_ADD_HEAD ||
   2285        1.1    itojun 		    pca->action > PF_CHANGE_REMOVE) {
   2286        1.1    itojun 			error = EINVAL;
   2287        1.1    itojun 			break;
   2288        1.1    itojun 		}
   2289        1.1    itojun 		if (pca->addr.addr.type != PF_ADDR_ADDRMASK &&
   2290        1.1    itojun 		    pca->addr.addr.type != PF_ADDR_DYNIFTL &&
   2291        1.1    itojun 		    pca->addr.addr.type != PF_ADDR_TABLE) {
   2292        1.1    itojun 			error = EINVAL;
   2293        1.1    itojun 			break;
   2294        1.1    itojun 		}
   2295        1.1    itojun 
   2296       1.12      yamt 		ruleset = pf_find_ruleset(pca->anchor);
   2297        1.1    itojun 		if (ruleset == NULL) {
   2298        1.1    itojun 			error = EBUSY;
   2299        1.1    itojun 			break;
   2300        1.1    itojun 		}
   2301       1.12      yamt 		pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action,
   2302       1.12      yamt 		    pca->r_num, pca->r_last, 1, 1);
   2303        1.1    itojun 		if (pool == NULL) {
   2304        1.1    itojun 			error = EBUSY;
   2305        1.1    itojun 			break;
   2306        1.1    itojun 		}
   2307        1.1    itojun 		if (pca->action != PF_CHANGE_REMOVE) {
   2308        1.1    itojun 			newpa = pool_get(&pf_pooladdr_pl, PR_NOWAIT);
   2309        1.1    itojun 			if (newpa == NULL) {
   2310        1.1    itojun 				error = ENOMEM;
   2311        1.1    itojun 				break;
   2312        1.1    itojun 			}
   2313        1.1    itojun 			bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr));
   2314        1.1    itojun #ifndef INET
   2315        1.1    itojun 			if (pca->af == AF_INET) {
   2316        1.1    itojun 				pool_put(&pf_pooladdr_pl, newpa);
   2317        1.1    itojun 				error = EAFNOSUPPORT;
   2318        1.1    itojun 				break;
   2319        1.1    itojun 			}
   2320        1.1    itojun #endif /* INET */
   2321        1.1    itojun #ifndef INET6
   2322        1.1    itojun 			if (pca->af == AF_INET6) {
   2323        1.1    itojun 				pool_put(&pf_pooladdr_pl, newpa);
   2324        1.1    itojun 				error = EAFNOSUPPORT;
   2325        1.1    itojun 				break;
   2326        1.1    itojun 			}
   2327        1.1    itojun #endif /* INET6 */
   2328        1.1    itojun 			if (newpa->ifname[0]) {
   2329        1.1    itojun 				newpa->kif = pfi_attach_rule(newpa->ifname);
   2330        1.1    itojun 				if (newpa->kif == NULL) {
   2331        1.1    itojun 					pool_put(&pf_pooladdr_pl, newpa);
   2332        1.1    itojun 					error = EINVAL;
   2333        1.1    itojun 					break;
   2334        1.1    itojun 				}
   2335        1.1    itojun 			} else
   2336        1.1    itojun 				newpa->kif = NULL;
   2337        1.1    itojun 			if (pfi_dynaddr_setup(&newpa->addr, pca->af) ||
   2338        1.1    itojun 			    pf_tbladdr_setup(ruleset, &newpa->addr)) {
   2339        1.1    itojun 				pfi_dynaddr_remove(&newpa->addr);
   2340        1.1    itojun 				pfi_detach_rule(newpa->kif);
   2341        1.1    itojun 				pool_put(&pf_pooladdr_pl, newpa);
   2342        1.1    itojun 				error = EINVAL;
   2343        1.1    itojun 				break;
   2344        1.1    itojun 			}
   2345        1.1    itojun 		}
   2346        1.1    itojun 
   2347        1.1    itojun 		if (pca->action == PF_CHANGE_ADD_HEAD)
   2348        1.1    itojun 			oldpa = TAILQ_FIRST(&pool->list);
   2349        1.1    itojun 		else if (pca->action == PF_CHANGE_ADD_TAIL)
   2350        1.1    itojun 			oldpa = TAILQ_LAST(&pool->list, pf_palist);
   2351        1.1    itojun 		else {
   2352        1.1    itojun 			int	i = 0;
   2353        1.1    itojun 
   2354        1.1    itojun 			oldpa = TAILQ_FIRST(&pool->list);
   2355        1.1    itojun 			while ((oldpa != NULL) && (i < pca->nr)) {
   2356        1.1    itojun 				oldpa = TAILQ_NEXT(oldpa, entries);
   2357        1.1    itojun 				i++;
   2358        1.1    itojun 			}
   2359        1.1    itojun 			if (oldpa == NULL) {
   2360        1.1    itojun 				error = EINVAL;
   2361        1.1    itojun 				break;
   2362        1.1    itojun 			}
   2363        1.1    itojun 		}
   2364        1.1    itojun 
   2365        1.1    itojun 		if (pca->action == PF_CHANGE_REMOVE) {
   2366        1.1    itojun 			TAILQ_REMOVE(&pool->list, oldpa, entries);
   2367        1.1    itojun 			pfi_dynaddr_remove(&oldpa->addr);
   2368        1.1    itojun 			pf_tbladdr_remove(&oldpa->addr);
   2369        1.1    itojun 			pfi_detach_rule(oldpa->kif);
   2370        1.1    itojun 			pool_put(&pf_pooladdr_pl, oldpa);
   2371        1.1    itojun 		} else {
   2372        1.1    itojun 			if (oldpa == NULL)
   2373        1.1    itojun 				TAILQ_INSERT_TAIL(&pool->list, newpa, entries);
   2374        1.1    itojun 			else if (pca->action == PF_CHANGE_ADD_HEAD ||
   2375        1.1    itojun 			    pca->action == PF_CHANGE_ADD_BEFORE)
   2376        1.1    itojun 				TAILQ_INSERT_BEFORE(oldpa, newpa, entries);
   2377        1.1    itojun 			else
   2378        1.1    itojun 				TAILQ_INSERT_AFTER(&pool->list, oldpa,
   2379        1.1    itojun 				    newpa, entries);
   2380        1.1    itojun 		}
   2381        1.1    itojun 
   2382        1.1    itojun 		pool->cur = TAILQ_FIRST(&pool->list);
   2383        1.1    itojun 		PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr,
   2384        1.1    itojun 		    pca->af);
   2385        1.1    itojun 		break;
   2386        1.1    itojun 	}
   2387        1.1    itojun 
   2388        1.1    itojun 	case DIOCGETRULESETS: {
   2389        1.1    itojun 		struct pfioc_ruleset	*pr = (struct pfioc_ruleset *)addr;
   2390       1.12      yamt 		struct pf_ruleset	*ruleset;
   2391        1.1    itojun 		struct pf_anchor	*anchor;
   2392        1.1    itojun 
   2393       1.12      yamt 		pr->path[sizeof(pr->path) - 1] = 0;
   2394       1.12      yamt 		if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
   2395        1.1    itojun 			error = EINVAL;
   2396        1.1    itojun 			break;
   2397        1.1    itojun 		}
   2398        1.1    itojun 		pr->nr = 0;
   2399       1.12      yamt 		if (ruleset->anchor == NULL) {
   2400       1.12      yamt 			/* XXX kludge for pf_main_ruleset */
   2401       1.12      yamt 			RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
   2402       1.12      yamt 				if (anchor->parent == NULL)
   2403       1.12      yamt 					pr->nr++;
   2404       1.12      yamt 		} else {
   2405       1.12      yamt 			RB_FOREACH(anchor, pf_anchor_node,
   2406       1.12      yamt 			    &ruleset->anchor->children)
   2407       1.12      yamt 				pr->nr++;
   2408       1.12      yamt 		}
   2409        1.1    itojun 		break;
   2410        1.1    itojun 	}
   2411        1.1    itojun 
   2412        1.1    itojun 	case DIOCGETRULESET: {
   2413        1.1    itojun 		struct pfioc_ruleset	*pr = (struct pfioc_ruleset *)addr;
   2414       1.12      yamt 		struct pf_ruleset	*ruleset;
   2415        1.1    itojun 		struct pf_anchor	*anchor;
   2416        1.1    itojun 		u_int32_t		 nr = 0;
   2417        1.1    itojun 
   2418       1.12      yamt 		pr->path[sizeof(pr->path) - 1] = 0;
   2419       1.12      yamt 		if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
   2420        1.1    itojun 			error = EINVAL;
   2421        1.1    itojun 			break;
   2422        1.1    itojun 		}
   2423       1.12      yamt 		pr->name[0] = 0;
   2424       1.12      yamt 		if (ruleset->anchor == NULL) {
   2425       1.12      yamt 			/* XXX kludge for pf_main_ruleset */
   2426       1.12      yamt 			RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
   2427       1.12      yamt 				if (anchor->parent == NULL && nr++ == pr->nr) {
   2428       1.12      yamt 					strlcpy(pr->name, anchor->name,
   2429       1.12      yamt 					    sizeof(pr->name));
   2430       1.12      yamt 					break;
   2431       1.12      yamt 				}
   2432       1.12      yamt 		} else {
   2433       1.12      yamt 			RB_FOREACH(anchor, pf_anchor_node,
   2434       1.12      yamt 			    &ruleset->anchor->children)
   2435       1.12      yamt 				if (nr++ == pr->nr) {
   2436       1.12      yamt 					strlcpy(pr->name, anchor->name,
   2437       1.12      yamt 					    sizeof(pr->name));
   2438       1.12      yamt 					break;
   2439       1.12      yamt 				}
   2440        1.1    itojun 		}
   2441       1.12      yamt 		if (!pr->name[0])
   2442        1.1    itojun 			error = EBUSY;
   2443        1.1    itojun 		break;
   2444        1.1    itojun 	}
   2445        1.1    itojun 
   2446        1.1    itojun 	case DIOCRCLRTABLES: {
   2447        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2448        1.1    itojun 
   2449        1.1    itojun 		if (io->pfrio_esize != 0) {
   2450        1.1    itojun 			error = ENODEV;
   2451        1.1    itojun 			break;
   2452        1.1    itojun 		}
   2453        1.1    itojun 		error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
   2454        1.1    itojun 		    io->pfrio_flags | PFR_FLAG_USERIOCTL);
   2455        1.1    itojun 		break;
   2456        1.1    itojun 	}
   2457        1.1    itojun 
   2458        1.1    itojun 	case DIOCRADDTABLES: {
   2459        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2460        1.1    itojun 
   2461        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
   2462        1.1    itojun 			error = ENODEV;
   2463        1.1    itojun 			break;
   2464        1.1    itojun 		}
   2465        1.1    itojun 		error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size,
   2466        1.1    itojun 		    &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
   2467        1.1    itojun 		break;
   2468        1.1    itojun 	}
   2469        1.1    itojun 
   2470        1.1    itojun 	case DIOCRDELTABLES: {
   2471        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2472        1.1    itojun 
   2473        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
   2474        1.1    itojun 			error = ENODEV;
   2475        1.1    itojun 			break;
   2476        1.1    itojun 		}
   2477        1.1    itojun 		error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size,
   2478        1.1    itojun 		    &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
   2479        1.1    itojun 		break;
   2480        1.1    itojun 	}
   2481        1.1    itojun 
   2482        1.1    itojun 	case DIOCRGETTABLES: {
   2483        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2484        1.1    itojun 
   2485        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
   2486        1.1    itojun 			error = ENODEV;
   2487        1.1    itojun 			break;
   2488        1.1    itojun 		}
   2489        1.1    itojun 		error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer,
   2490        1.1    itojun 		    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
   2491        1.1    itojun 		break;
   2492        1.1    itojun 	}
   2493        1.1    itojun 
   2494        1.1    itojun 	case DIOCRGETTSTATS: {
   2495        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2496        1.1    itojun 
   2497        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
   2498        1.1    itojun 			error = ENODEV;
   2499        1.1    itojun 			break;
   2500        1.1    itojun 		}
   2501        1.1    itojun 		error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer,
   2502        1.1    itojun 		    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
   2503        1.1    itojun 		break;
   2504        1.1    itojun 	}
   2505        1.1    itojun 
   2506        1.1    itojun 	case DIOCRCLRTSTATS: {
   2507        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2508        1.1    itojun 
   2509        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
   2510        1.1    itojun 			error = ENODEV;
   2511        1.1    itojun 			break;
   2512        1.1    itojun 		}
   2513        1.1    itojun 		error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size,
   2514        1.1    itojun 		    &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
   2515        1.1    itojun 		break;
   2516        1.1    itojun 	}
   2517        1.1    itojun 
   2518        1.1    itojun 	case DIOCRSETTFLAGS: {
   2519        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2520        1.1    itojun 
   2521        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_table)) {
   2522        1.1    itojun 			error = ENODEV;
   2523        1.1    itojun 			break;
   2524        1.1    itojun 		}
   2525        1.1    itojun 		error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size,
   2526        1.1    itojun 		    io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
   2527        1.1    itojun 		    &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
   2528        1.1    itojun 		break;
   2529        1.1    itojun 	}
   2530        1.1    itojun 
   2531        1.1    itojun 	case DIOCRCLRADDRS: {
   2532        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2533        1.1    itojun 
   2534        1.1    itojun 		if (io->pfrio_esize != 0) {
   2535        1.1    itojun 			error = ENODEV;
   2536        1.1    itojun 			break;
   2537        1.1    itojun 		}
   2538        1.1    itojun 		error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
   2539        1.1    itojun 		    io->pfrio_flags | PFR_FLAG_USERIOCTL);
   2540        1.1    itojun 		break;
   2541        1.1    itojun 	}
   2542        1.1    itojun 
   2543        1.1    itojun 	case DIOCRADDADDRS: {
   2544        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2545        1.1    itojun 
   2546        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
   2547        1.1    itojun 			error = ENODEV;
   2548        1.1    itojun 			break;
   2549        1.1    itojun 		}
   2550        1.1    itojun 		error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer,
   2551        1.1    itojun 		    io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
   2552        1.1    itojun 		    PFR_FLAG_USERIOCTL);
   2553        1.1    itojun 		break;
   2554        1.1    itojun 	}
   2555        1.1    itojun 
   2556        1.1    itojun 	case DIOCRDELADDRS: {
   2557        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2558        1.1    itojun 
   2559        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
   2560        1.1    itojun 			error = ENODEV;
   2561        1.1    itojun 			break;
   2562        1.1    itojun 		}
   2563        1.1    itojun 		error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer,
   2564        1.1    itojun 		    io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
   2565        1.1    itojun 		    PFR_FLAG_USERIOCTL);
   2566        1.1    itojun 		break;
   2567        1.1    itojun 	}
   2568        1.1    itojun 
   2569        1.1    itojun 	case DIOCRSETADDRS: {
   2570        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2571        1.1    itojun 
   2572        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
   2573        1.1    itojun 			error = ENODEV;
   2574        1.1    itojun 			break;
   2575        1.1    itojun 		}
   2576        1.1    itojun 		error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer,
   2577        1.1    itojun 		    io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
   2578        1.1    itojun 		    &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
   2579        1.1    itojun 		    PFR_FLAG_USERIOCTL);
   2580        1.1    itojun 		break;
   2581        1.1    itojun 	}
   2582        1.1    itojun 
   2583        1.1    itojun 	case DIOCRGETADDRS: {
   2584        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2585        1.1    itojun 
   2586        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
   2587        1.1    itojun 			error = ENODEV;
   2588        1.1    itojun 			break;
   2589        1.1    itojun 		}
   2590        1.1    itojun 		error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer,
   2591        1.1    itojun 		    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
   2592        1.1    itojun 		break;
   2593        1.1    itojun 	}
   2594        1.1    itojun 
   2595        1.1    itojun 	case DIOCRGETASTATS: {
   2596        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2597        1.1    itojun 
   2598        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_astats)) {
   2599        1.1    itojun 			error = ENODEV;
   2600        1.1    itojun 			break;
   2601        1.1    itojun 		}
   2602        1.1    itojun 		error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer,
   2603        1.1    itojun 		    &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
   2604        1.1    itojun 		break;
   2605        1.1    itojun 	}
   2606        1.1    itojun 
   2607        1.1    itojun 	case DIOCRCLRASTATS: {
   2608        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2609        1.1    itojun 
   2610        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
   2611        1.1    itojun 			error = ENODEV;
   2612        1.1    itojun 			break;
   2613        1.1    itojun 		}
   2614        1.1    itojun 		error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer,
   2615        1.1    itojun 		    io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
   2616        1.1    itojun 		    PFR_FLAG_USERIOCTL);
   2617        1.1    itojun 		break;
   2618        1.1    itojun 	}
   2619        1.1    itojun 
   2620        1.1    itojun 	case DIOCRTSTADDRS: {
   2621        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2622        1.1    itojun 
   2623        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
   2624        1.1    itojun 			error = ENODEV;
   2625        1.1    itojun 			break;
   2626        1.1    itojun 		}
   2627        1.1    itojun 		error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer,
   2628        1.1    itojun 		    io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
   2629        1.1    itojun 		    PFR_FLAG_USERIOCTL);
   2630        1.1    itojun 		break;
   2631        1.1    itojun 	}
   2632        1.1    itojun 
   2633        1.1    itojun 	case DIOCRINADEFINE: {
   2634        1.1    itojun 		struct pfioc_table *io = (struct pfioc_table *)addr;
   2635        1.1    itojun 
   2636        1.1    itojun 		if (io->pfrio_esize != sizeof(struct pfr_addr)) {
   2637        1.1    itojun 			error = ENODEV;
   2638        1.1    itojun 			break;
   2639        1.1    itojun 		}
   2640        1.1    itojun 		error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer,
   2641        1.1    itojun 		    io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
   2642        1.1    itojun 		    io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
   2643        1.1    itojun 		break;
   2644        1.1    itojun 	}
   2645        1.1    itojun 
   2646        1.1    itojun 	case DIOCOSFPADD: {
   2647        1.1    itojun 		struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
   2648        1.1    itojun 		error = pf_osfp_add(io);
   2649        1.1    itojun 		break;
   2650        1.1    itojun 	}
   2651        1.1    itojun 
   2652        1.1    itojun 	case DIOCOSFPGET: {
   2653        1.1    itojun 		struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
   2654        1.1    itojun 		error = pf_osfp_get(io);
   2655        1.1    itojun 		break;
   2656        1.1    itojun 	}
   2657        1.1    itojun 
   2658        1.1    itojun 	case DIOCXBEGIN: {
   2659       1.12      yamt 		struct pfioc_trans		*io = (struct pfioc_trans *)
   2660       1.12      yamt 						    addr;
   2661       1.12      yamt 		static struct pfioc_trans_e	 ioe;
   2662       1.12      yamt 		static struct pfr_table		 table;
   2663       1.12      yamt 		int				 i;
   2664        1.1    itojun 
   2665        1.1    itojun 		if (io->esize != sizeof(ioe)) {
   2666        1.1    itojun 			error = ENODEV;
   2667        1.1    itojun 			goto fail;
   2668        1.1    itojun 		}
   2669        1.1    itojun 		for (i = 0; i < io->size; i++) {
   2670        1.1    itojun 			if (copyin(io->array+i, &ioe, sizeof(ioe))) {
   2671        1.1    itojun 				error = EFAULT;
   2672        1.1    itojun 				goto fail;
   2673        1.1    itojun 			}
   2674        1.1    itojun 			switch (ioe.rs_num) {
   2675        1.1    itojun #ifdef ALTQ
   2676        1.1    itojun 			case PF_RULESET_ALTQ:
   2677       1.12      yamt 				if (ioe.anchor[0]) {
   2678        1.1    itojun 					error = EINVAL;
   2679        1.1    itojun 					goto fail;
   2680        1.1    itojun 				}
   2681        1.1    itojun 				if ((error = pf_begin_altq(&ioe.ticket)))
   2682        1.1    itojun 					goto fail;
   2683        1.1    itojun 				break;
   2684        1.1    itojun #endif /* ALTQ */
   2685        1.1    itojun 			case PF_RULESET_TABLE:
   2686        1.1    itojun 				bzero(&table, sizeof(table));
   2687        1.1    itojun 				strlcpy(table.pfrt_anchor, ioe.anchor,
   2688        1.1    itojun 				    sizeof(table.pfrt_anchor));
   2689        1.1    itojun 				if ((error = pfr_ina_begin(&table,
   2690        1.1    itojun 				    &ioe.ticket, NULL, 0)))
   2691        1.1    itojun 					goto fail;
   2692        1.1    itojun 				break;
   2693        1.1    itojun 			default:
   2694        1.1    itojun 				if ((error = pf_begin_rules(&ioe.ticket,
   2695       1.12      yamt 				    ioe.rs_num, ioe.anchor)))
   2696        1.1    itojun 					goto fail;
   2697        1.1    itojun 				break;
   2698        1.1    itojun 			}
   2699        1.1    itojun 			if (copyout(&ioe, io->array+i, sizeof(io->array[i]))) {
   2700        1.1    itojun 				error = EFAULT;
   2701        1.1    itojun 				goto fail;
   2702        1.1    itojun 			}
   2703        1.1    itojun 		}
   2704        1.1    itojun 		break;
   2705        1.1    itojun 	}
   2706        1.1    itojun 
   2707        1.1    itojun 	case DIOCXROLLBACK: {
   2708       1.12      yamt 		struct pfioc_trans		*io = (struct pfioc_trans *)
   2709       1.12      yamt 						    addr;
   2710       1.12      yamt 		static struct pfioc_trans_e	 ioe;
   2711       1.12      yamt 		static struct pfr_table		 table;
   2712       1.12      yamt 		int				 i;
   2713        1.1    itojun 
   2714        1.1    itojun 		if (io->esize != sizeof(ioe)) {
   2715        1.1    itojun 			error = ENODEV;
   2716        1.1    itojun 			goto fail;
   2717        1.1    itojun 		}
   2718        1.1    itojun 		for (i = 0; i < io->size; i++) {
   2719        1.1    itojun 			if (copyin(io->array+i, &ioe, sizeof(ioe))) {
   2720        1.1    itojun 				error = EFAULT;
   2721        1.1    itojun 				goto fail;
   2722        1.1    itojun 			}
   2723        1.1    itojun 			switch (ioe.rs_num) {
   2724        1.1    itojun #ifdef ALTQ
   2725        1.1    itojun 			case PF_RULESET_ALTQ:
   2726       1.12      yamt 				if (ioe.anchor[0]) {
   2727        1.1    itojun 					error = EINVAL;
   2728        1.1    itojun 					goto fail;
   2729        1.1    itojun 				}
   2730        1.1    itojun 				if ((error = pf_rollback_altq(ioe.ticket)))
   2731        1.1    itojun 					goto fail; /* really bad */
   2732        1.1    itojun 				break;
   2733        1.1    itojun #endif /* ALTQ */
   2734        1.1    itojun 			case PF_RULESET_TABLE:
   2735        1.1    itojun 				bzero(&table, sizeof(table));
   2736        1.1    itojun 				strlcpy(table.pfrt_anchor, ioe.anchor,
   2737        1.1    itojun 				    sizeof(table.pfrt_anchor));
   2738        1.1    itojun 				if ((error = pfr_ina_rollback(&table,
   2739        1.1    itojun 				    ioe.ticket, NULL, 0)))
   2740        1.1    itojun 					goto fail; /* really bad */
   2741        1.1    itojun 				break;
   2742        1.1    itojun 			default:
   2743        1.1    itojun 				if ((error = pf_rollback_rules(ioe.ticket,
   2744       1.12      yamt 				    ioe.rs_num, ioe.anchor)))
   2745        1.1    itojun 					goto fail; /* really bad */
   2746        1.1    itojun 				break;
   2747        1.1    itojun 			}
   2748        1.1    itojun 		}
   2749        1.1    itojun 		break;
   2750        1.1    itojun 	}
   2751        1.1    itojun 
   2752        1.1    itojun 	case DIOCXCOMMIT: {
   2753       1.12      yamt 		struct pfioc_trans		*io = (struct pfioc_trans *)
   2754       1.12      yamt 						    addr;
   2755       1.12      yamt 		static struct pfioc_trans_e	 ioe;
   2756       1.12      yamt 		static struct pfr_table		 table;
   2757       1.12      yamt 		struct pf_ruleset		*rs;
   2758       1.12      yamt 		int				 i;
   2759        1.1    itojun 
   2760        1.1    itojun 		if (io->esize != sizeof(ioe)) {
   2761        1.1    itojun 			error = ENODEV;
   2762        1.1    itojun 			goto fail;
   2763        1.1    itojun 		}
   2764        1.1    itojun 		/* first makes sure everything will succeed */
   2765        1.1    itojun 		for (i = 0; i < io->size; i++) {
   2766        1.1    itojun 			if (copyin(io->array+i, &ioe, sizeof(ioe))) {
   2767        1.1    itojun 				error = EFAULT;
   2768        1.1    itojun 				goto fail;
   2769        1.1    itojun 			}
   2770        1.1    itojun 			switch (ioe.rs_num) {
   2771        1.1    itojun #ifdef ALTQ
   2772        1.1    itojun 			case PF_RULESET_ALTQ:
   2773       1.12      yamt 				if (ioe.anchor[0]) {
   2774        1.1    itojun 					error = EINVAL;
   2775        1.1    itojun 					goto fail;
   2776        1.1    itojun 				}
   2777        1.1    itojun 				if (!altqs_inactive_open || ioe.ticket !=
   2778        1.1    itojun 				    ticket_altqs_inactive) {
   2779        1.1    itojun 					error = EBUSY;
   2780        1.1    itojun 					goto fail;
   2781        1.1    itojun 				}
   2782        1.1    itojun 				break;
   2783        1.1    itojun #endif /* ALTQ */
   2784        1.1    itojun 			case PF_RULESET_TABLE:
   2785       1.12      yamt 				rs = pf_find_ruleset(ioe.anchor);
   2786        1.1    itojun 				if (rs == NULL || !rs->topen || ioe.ticket !=
   2787        1.1    itojun 				     rs->tticket) {
   2788        1.1    itojun 					error = EBUSY;
   2789        1.1    itojun 					goto fail;
   2790        1.1    itojun 				}
   2791        1.1    itojun 				break;
   2792        1.1    itojun 			default:
   2793        1.1    itojun 				if (ioe.rs_num < 0 || ioe.rs_num >=
   2794        1.1    itojun 				    PF_RULESET_MAX) {
   2795        1.1    itojun 					error = EINVAL;
   2796        1.1    itojun 					goto fail;
   2797        1.1    itojun 				}
   2798       1.12      yamt 				rs = pf_find_ruleset(ioe.anchor);
   2799        1.1    itojun 				if (rs == NULL ||
   2800        1.1    itojun 				    !rs->rules[ioe.rs_num].inactive.open ||
   2801        1.1    itojun 				    rs->rules[ioe.rs_num].inactive.ticket !=
   2802        1.1    itojun 				    ioe.ticket) {
   2803        1.1    itojun 					error = EBUSY;
   2804        1.1    itojun 					goto fail;
   2805        1.1    itojun 				}
   2806        1.1    itojun 				break;
   2807        1.1    itojun 			}
   2808        1.1    itojun 		}
   2809        1.1    itojun 		/* now do the commit - no errors should happen here */
   2810        1.1    itojun 		for (i = 0; i < io->size; i++) {
   2811        1.1    itojun 			if (copyin(io->array+i, &ioe, sizeof(ioe))) {
   2812        1.1    itojun 				error = EFAULT;
   2813        1.1    itojun 				goto fail;
   2814        1.1    itojun 			}
   2815        1.1    itojun 			switch (ioe.rs_num) {
   2816        1.1    itojun #ifdef ALTQ
   2817        1.1    itojun 			case PF_RULESET_ALTQ:
   2818        1.1    itojun 				if ((error = pf_commit_altq(ioe.ticket)))
   2819        1.1    itojun 					goto fail; /* really bad */
   2820        1.1    itojun 				break;
   2821        1.1    itojun #endif /* ALTQ */
   2822        1.1    itojun 			case PF_RULESET_TABLE:
   2823        1.1    itojun 				bzero(&table, sizeof(table));
   2824        1.1    itojun 				strlcpy(table.pfrt_anchor, ioe.anchor,
   2825        1.1    itojun 				    sizeof(table.pfrt_anchor));
   2826        1.1    itojun 				if ((error = pfr_ina_commit(&table, ioe.ticket,
   2827        1.1    itojun 				    NULL, NULL, 0)))
   2828        1.1    itojun 					goto fail; /* really bad */
   2829        1.1    itojun 				break;
   2830        1.1    itojun 			default:
   2831        1.1    itojun 				if ((error = pf_commit_rules(ioe.ticket,
   2832       1.12      yamt 				    ioe.rs_num, ioe.anchor)))
   2833        1.1    itojun 					goto fail; /* really bad */
   2834        1.1    itojun 				break;
   2835        1.1    itojun 			}
   2836        1.1    itojun 		}
   2837        1.1    itojun 		break;
   2838        1.1    itojun 	}
   2839        1.1    itojun 
   2840        1.1    itojun 	case DIOCGETSRCNODES: {
   2841        1.1    itojun 		struct pfioc_src_nodes	*psn = (struct pfioc_src_nodes *)addr;
   2842        1.1    itojun 		struct pf_src_node	*n;
   2843        1.1    itojun 		struct pf_src_node *p, pstore;
   2844        1.1    itojun 		u_int32_t		 nr = 0;
   2845        1.1    itojun 		int			 space = psn->psn_len;
   2846        1.1    itojun 
   2847        1.1    itojun 		if (space == 0) {
   2848        1.1    itojun 			RB_FOREACH(n, pf_src_tree, &tree_src_tracking)
   2849        1.1    itojun 				nr++;
   2850        1.1    itojun 			psn->psn_len = sizeof(struct pf_src_node) * nr;
   2851       1.15     peter 			break;
   2852        1.1    itojun 		}
   2853        1.1    itojun 
   2854        1.1    itojun 		p = psn->psn_src_nodes;
   2855        1.1    itojun 		RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
   2856       1.17     peter 			int	secs = time_second, diff;
   2857        1.1    itojun 
   2858        1.1    itojun 			if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
   2859        1.1    itojun 				break;
   2860        1.1    itojun 
   2861        1.1    itojun 			bcopy(n, &pstore, sizeof(pstore));
   2862        1.1    itojun 			if (n->rule.ptr != NULL)
   2863        1.1    itojun 				pstore.rule.nr = n->rule.ptr->nr;
   2864        1.1    itojun 			pstore.creation = secs - pstore.creation;
   2865        1.1    itojun 			if (pstore.expire > secs)
   2866        1.1    itojun 				pstore.expire -= secs;
   2867        1.1    itojun 			else
   2868        1.1    itojun 				pstore.expire = 0;
   2869       1.17     peter 
   2870       1.17     peter 			/* adjust the connection rate estimate */
   2871       1.17     peter 			diff = secs - n->conn_rate.last;
   2872       1.17     peter 			if (diff >= n->conn_rate.seconds)
   2873       1.17     peter 				pstore.conn_rate.count = 0;
   2874       1.17     peter 			else
   2875       1.17     peter 				pstore.conn_rate.count -=
   2876       1.17     peter 				    n->conn_rate.count * diff /
   2877       1.17     peter 				    n->conn_rate.seconds;
   2878       1.17     peter 
   2879        1.1    itojun 			error = copyout(&pstore, p, sizeof(*p));
   2880       1.15     peter 			if (error)
   2881        1.1    itojun 				goto fail;
   2882        1.1    itojun 			p++;
   2883        1.1    itojun 			nr++;
   2884        1.1    itojun 		}
   2885        1.1    itojun 		psn->psn_len = sizeof(struct pf_src_node) * nr;
   2886        1.1    itojun 		break;
   2887        1.1    itojun 	}
   2888        1.1    itojun 
   2889        1.1    itojun 	case DIOCCLRSRCNODES: {
   2890        1.1    itojun 		struct pf_src_node	*n;
   2891        1.1    itojun 		struct pf_state		*state;
   2892        1.1    itojun 
   2893        1.1    itojun 		RB_FOREACH(state, pf_state_tree_id, &tree_id) {
   2894        1.1    itojun 			state->src_node = NULL;
   2895        1.1    itojun 			state->nat_src_node = NULL;
   2896        1.1    itojun 		}
   2897        1.1    itojun 		RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
   2898        1.1    itojun 			n->expire = 1;
   2899        1.1    itojun 			n->states = 0;
   2900        1.1    itojun 		}
   2901        1.1    itojun 		pf_purge_expired_src_nodes();
   2902        1.1    itojun 		pf_status.src_nodes = 0;
   2903        1.1    itojun 		break;
   2904        1.1    itojun 	}
   2905        1.1    itojun 
   2906        1.1    itojun 	case DIOCSETHOSTID: {
   2907        1.1    itojun 		u_int32_t	*hostid = (u_int32_t *)addr;
   2908        1.1    itojun 
   2909       1.17     peter 		if (*hostid == 0)
   2910       1.17     peter 			pf_status.hostid = arc4random();
   2911       1.17     peter 		else
   2912       1.17     peter 			pf_status.hostid = *hostid;
   2913        1.1    itojun 		break;
   2914        1.1    itojun 	}
   2915        1.1    itojun 
   2916        1.1    itojun 	case DIOCOSFPFLUSH:
   2917        1.1    itojun 		pf_osfp_flush();
   2918        1.1    itojun 		break;
   2919        1.1    itojun 
   2920        1.1    itojun 	case DIOCIGETIFACES: {
   2921        1.1    itojun 		struct pfioc_iface *io = (struct pfioc_iface *)addr;
   2922        1.1    itojun 
   2923        1.1    itojun 		if (io->pfiio_esize != sizeof(struct pfi_if)) {
   2924        1.1    itojun 			error = ENODEV;
   2925        1.1    itojun 			break;
   2926        1.1    itojun 		}
   2927        1.1    itojun 		error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer,
   2928        1.1    itojun 		    &io->pfiio_size, io->pfiio_flags);
   2929        1.1    itojun 		break;
   2930        1.1    itojun 	}
   2931        1.1    itojun 
   2932        1.1    itojun 	case DIOCICLRISTATS: {
   2933        1.1    itojun 		struct pfioc_iface *io = (struct pfioc_iface *)addr;
   2934        1.1    itojun 
   2935        1.1    itojun 		error = pfi_clr_istats(io->pfiio_name, &io->pfiio_nzero,
   2936        1.1    itojun 		    io->pfiio_flags);
   2937        1.1    itojun 		break;
   2938        1.1    itojun 	}
   2939        1.1    itojun 
   2940       1.17     peter 	case DIOCSETIFFLAG: {
   2941       1.17     peter 		struct pfioc_iface *io = (struct pfioc_iface *)addr;
   2942       1.17     peter 
   2943       1.17     peter 		error = pfi_set_flags(io->pfiio_name, io->pfiio_flags);
   2944       1.17     peter 		break;
   2945       1.17     peter 	}
   2946       1.17     peter 
   2947       1.17     peter 	case DIOCCLRIFFLAG: {
   2948       1.17     peter 		struct pfioc_iface *io = (struct pfioc_iface *)addr;
   2949       1.17     peter 
   2950       1.17     peter 		error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags);
   2951       1.17     peter 		break;
   2952       1.17     peter 	}
   2953       1.17     peter 
   2954        1.1    itojun 	default:
   2955        1.1    itojun 		error = ENODEV;
   2956        1.1    itojun 		break;
   2957        1.1    itojun 	}
   2958        1.1    itojun fail:
   2959       1.15     peter 	splx(s);
   2960        1.1    itojun 	return (error);
   2961        1.1    itojun }
   2962        1.2    itojun 
   2963        1.2    itojun #ifdef __NetBSD__
   2964       1.19      yamt #ifdef INET
   2965        1.2    itojun int
   2966        1.2    itojun pfil4_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
   2967        1.2    itojun {
   2968       1.10      yamt 	int error;
   2969       1.10      yamt 
   2970       1.10      yamt 	/*
   2971       1.10      yamt 	 * ensure that mbufs are writable beforehand
   2972       1.10      yamt 	 * as it's assumed by pf code.
   2973       1.10      yamt 	 * ip hdr (60 bytes) + tcp hdr (60 bytes) should be enough.
   2974       1.10      yamt 	 * XXX inefficient
   2975       1.10      yamt 	 */
   2976       1.10      yamt 	error = m_makewritable(mp, 0, 60 + 60, M_DONTWAIT);
   2977       1.10      yamt 	if (error) {
   2978       1.10      yamt 		m_freem(*mp);
   2979       1.10      yamt 		*mp = NULL;
   2980       1.10      yamt 		return error;
   2981       1.10      yamt 	}
   2982        1.2    itojun 
   2983        1.2    itojun 	/*
   2984        1.2    itojun 	 * If the packet is out-bound, we can't delay checksums
   2985        1.2    itojun 	 * here.  For in-bound, the checksum has already been
   2986        1.2    itojun 	 * validated.
   2987        1.2    itojun 	 */
   2988        1.2    itojun 	if (dir == PFIL_OUT) {
   2989        1.2    itojun 		if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
   2990        1.2    itojun 			in_delayed_cksum(*mp);
   2991        1.2    itojun 			(*mp)->m_pkthdr.csum_flags &=
   2992        1.2    itojun 			    ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
   2993        1.2    itojun 		}
   2994        1.2    itojun 	}
   2995        1.2    itojun 
   2996       1.12      yamt 	if (pf_test(dir == PFIL_OUT ? PF_OUT : PF_IN, ifp, mp, NULL)
   2997       1.12      yamt 	    != PF_PASS) {
   2998        1.5    itojun 		m_freem(*mp);
   2999        1.5    itojun 		*mp = NULL;
   3000        1.2    itojun 		return EHOSTUNREACH;
   3001       1.14      yamt 	}
   3002       1.14      yamt 
   3003       1.14      yamt 	/*
   3004       1.14      yamt 	 * we're not compatible with fast-forward.
   3005       1.14      yamt 	 */
   3006       1.14      yamt 
   3007       1.18     peter 	if (dir == PFIL_IN && *mp) {
   3008       1.14      yamt 		(*mp)->m_flags &= ~M_CANFASTFWD;
   3009       1.14      yamt 	}
   3010       1.14      yamt 
   3011       1.14      yamt 	return (0);
   3012        1.2    itojun }
   3013       1.19      yamt #endif /* INET */
   3014        1.2    itojun 
   3015        1.4    martin #ifdef INET6
   3016        1.2    itojun int
   3017        1.2    itojun pfil6_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
   3018        1.2    itojun {
   3019       1.10      yamt 	int error;
   3020       1.10      yamt 
   3021       1.10      yamt 	/*
   3022       1.10      yamt 	 * ensure that mbufs are writable beforehand
   3023       1.10      yamt 	 * as it's assumed by pf code.
   3024       1.10      yamt 	 * XXX inefficient
   3025       1.10      yamt 	 */
   3026       1.10      yamt 	error = m_makewritable(mp, 0, M_COPYALL, M_DONTWAIT);
   3027       1.10      yamt 	if (error) {
   3028       1.10      yamt 		m_freem(*mp);
   3029       1.10      yamt 		*mp = NULL;
   3030       1.10      yamt 		return error;
   3031       1.10      yamt 	}
   3032        1.2    itojun 
   3033       1.20      yamt 	/*
   3034       1.20      yamt 	 * If the packet is out-bound, we can't delay checksums
   3035       1.20      yamt 	 * here.  For in-bound, the checksum has already been
   3036       1.20      yamt 	 * validated.
   3037       1.20      yamt 	 */
   3038       1.20      yamt 	if (dir == PFIL_OUT) {
   3039       1.20      yamt 		if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) {
   3040       1.20      yamt 			in6_delayed_cksum(*mp);
   3041       1.20      yamt 			(*mp)->m_pkthdr.csum_flags &=
   3042       1.20      yamt 			    ~(M_CSUM_TCPv6|M_CSUM_UDPv6);
   3043       1.20      yamt 		}
   3044       1.20      yamt 	}
   3045       1.20      yamt 
   3046       1.12      yamt 	if (pf_test6(dir == PFIL_OUT ? PF_OUT : PF_IN, ifp, mp, NULL)
   3047       1.12      yamt 	    != PF_PASS) {
   3048        1.5    itojun 		m_freem(*mp);
   3049        1.5    itojun 		*mp = NULL;
   3050        1.2    itojun 		return EHOSTUNREACH;
   3051        1.5    itojun 	} else
   3052        1.2    itojun 		return (0);
   3053        1.2    itojun }
   3054        1.4    martin #endif
   3055        1.2    itojun 
   3056        1.2    itojun int
   3057        1.9      yamt pfil_ifnet_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
   3058        1.2    itojun {
   3059        1.2    itojun 	u_long cmd = (u_long)mp;
   3060        1.2    itojun 
   3061        1.2    itojun 	switch (cmd) {
   3062        1.9      yamt 	case PFIL_IFNET_ATTACH:
   3063        1.2    itojun 		pfi_attach_ifnet(ifp);
   3064        1.2    itojun 		break;
   3065        1.9      yamt 	case PFIL_IFNET_DETACH:
   3066        1.9      yamt 		pfi_detach_ifnet(ifp);
   3067        1.9      yamt 		break;
   3068        1.9      yamt 	}
   3069        1.9      yamt 
   3070        1.9      yamt 	return (0);
   3071        1.9      yamt }
   3072        1.9      yamt 
   3073        1.9      yamt int
   3074        1.9      yamt pfil_ifaddr_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
   3075        1.9      yamt {
   3076        1.9      yamt 	extern void pfi_kifaddr_update_if(struct ifnet *);
   3077        1.9      yamt 
   3078        1.9      yamt 	u_long cmd = (u_long)mp;
   3079        1.9      yamt 
   3080        1.9      yamt 	switch (cmd) {
   3081        1.2    itojun 	case SIOCSIFADDR:
   3082        1.7      yamt 	case SIOCAIFADDR:
   3083        1.2    itojun 	case SIOCDIFADDR:
   3084        1.9      yamt #ifdef INET6
   3085        1.8      yamt 	case SIOCAIFADDR_IN6:
   3086        1.8      yamt 	case SIOCDIFADDR_IN6:
   3087        1.9      yamt #endif
   3088        1.8      yamt 		pfi_kifaddr_update_if(ifp);
   3089        1.2    itojun 		break;
   3090        1.2    itojun 	default:
   3091        1.2    itojun 		panic("unexpected ioctl");
   3092        1.2    itojun 	}
   3093        1.2    itojun 
   3094        1.9      yamt 	return (0);
   3095        1.2    itojun }
   3096        1.2    itojun 
   3097        1.2    itojun static int
   3098        1.2    itojun pf_pfil_attach(void)
   3099        1.2    itojun {
   3100        1.2    itojun 	struct pfil_head *ph_inet;
   3101        1.2    itojun #ifdef INET6
   3102        1.2    itojun 	struct pfil_head *ph_inet6;
   3103        1.2    itojun #endif
   3104        1.2    itojun 	int error;
   3105        1.2    itojun 	int i;
   3106        1.2    itojun 
   3107        1.6    itojun 	if (pf_pfil_attached)
   3108        1.6    itojun 		return (0);
   3109        1.6    itojun 
   3110        1.9      yamt 	error = pfil_add_hook(pfil_ifnet_wrapper, NULL, PFIL_IFNET, &if_pfil);
   3111        1.2    itojun 	if (error)
   3112        1.9      yamt 		goto bad1;
   3113        1.9      yamt 	error = pfil_add_hook(pfil_ifaddr_wrapper, NULL, PFIL_IFADDR, &if_pfil);
   3114        1.9      yamt 	if (error)
   3115        1.9      yamt 		goto bad2;
   3116        1.9      yamt 
   3117        1.2    itojun 	ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
   3118        1.2    itojun 	if (ph_inet)
   3119        1.2    itojun 		error = pfil_add_hook((void *)pfil4_wrapper, NULL,
   3120        1.2    itojun 		    PFIL_IN|PFIL_OUT, ph_inet);
   3121        1.2    itojun 	else
   3122        1.2    itojun 		error = ENOENT;
   3123        1.9      yamt 	if (error)
   3124        1.9      yamt 		goto bad3;
   3125        1.9      yamt 
   3126        1.2    itojun #ifdef INET6
   3127        1.2    itojun 	ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
   3128        1.2    itojun 	if (ph_inet6)
   3129        1.2    itojun 		error = pfil_add_hook((void *)pfil6_wrapper, NULL,
   3130        1.2    itojun 		    PFIL_IN|PFIL_OUT, ph_inet6);
   3131        1.2    itojun 	else
   3132        1.2    itojun 		error = ENOENT;
   3133        1.9      yamt 	if (error)
   3134        1.9      yamt 		goto bad4;
   3135        1.9      yamt #endif
   3136        1.9      yamt 
   3137        1.9      yamt 	for (i = 0; i < if_indexlim; i++)
   3138        1.9      yamt 		if (ifindex2ifnet[i])
   3139        1.9      yamt 			pfi_attach_ifnet(ifindex2ifnet[i]);
   3140        1.9      yamt 	pf_pfil_attached = 1;
   3141        1.9      yamt 
   3142        1.9      yamt 	return (0);
   3143        1.9      yamt 
   3144        1.9      yamt #ifdef INET6
   3145        1.9      yamt bad4:
   3146        1.9      yamt 	pfil_remove_hook(pfil4_wrapper, NULL, PFIL_IN|PFIL_OUT, ph_inet);
   3147        1.2    itojun #endif
   3148        1.9      yamt bad3:
   3149        1.9      yamt 	pfil_remove_hook(pfil_ifaddr_wrapper, NULL, PFIL_IFADDR, &if_pfil);
   3150        1.9      yamt bad2:
   3151        1.9      yamt 	pfil_remove_hook(pfil_ifnet_wrapper, NULL, PFIL_IFNET, &if_pfil);
   3152        1.9      yamt bad1:
   3153        1.2    itojun 	return (error);
   3154        1.2    itojun }
   3155        1.2    itojun 
   3156        1.9      yamt static int
   3157        1.2    itojun pf_pfil_detach(void)
   3158        1.2    itojun {
   3159        1.2    itojun 	struct pfil_head *ph_inet;
   3160        1.2    itojun #ifdef INET6
   3161        1.2    itojun 	struct pfil_head *ph_inet6;
   3162        1.2    itojun #endif
   3163        1.2    itojun 	int i;
   3164        1.2    itojun 
   3165        1.6    itojun 	if (pf_pfil_attached == 0)
   3166        1.6    itojun 		return (0);
   3167        1.6    itojun 
   3168        1.9      yamt 	for (i = 0; i < if_indexlim; i++)
   3169        1.2    itojun 		if (pfi_index2kif[i])
   3170        1.2    itojun 			pfi_detach_ifnet(ifindex2ifnet[i]);
   3171        1.9      yamt 
   3172        1.9      yamt 	pfil_remove_hook(pfil_ifaddr_wrapper, NULL, PFIL_IFADDR, &if_pfil);
   3173        1.9      yamt 	pfil_remove_hook(pfil_ifnet_wrapper, NULL, PFIL_IFNET, &if_pfil);
   3174        1.9      yamt 
   3175        1.2    itojun 	ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
   3176        1.2    itojun 	if (ph_inet)
   3177        1.2    itojun 		pfil_remove_hook((void *)pfil4_wrapper, NULL,
   3178        1.2    itojun 		    PFIL_IN|PFIL_OUT, ph_inet);
   3179        1.2    itojun #ifdef INET6
   3180        1.2    itojun 	ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
   3181        1.6    itojun 	if (ph_inet6)
   3182        1.2    itojun 		pfil_remove_hook((void *)pfil6_wrapper, NULL,
   3183        1.2    itojun 		    PFIL_IN|PFIL_OUT, ph_inet6);
   3184        1.2    itojun #endif
   3185        1.6    itojun 	pf_pfil_attached = 0;
   3186        1.6    itojun 
   3187        1.2    itojun 	return (0);
   3188        1.2    itojun }
   3189        1.2    itojun #endif
   3190