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