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