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