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