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