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