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.14 2008/04/11 18:21:48 dillon 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 state->hash = pf_state_hash(state); 1498 1499 if (pf_insert_state(kif, state)) { 1500 pfi_maybe_destroy(kif); 1501 pool_put(&pf_state_pl, state); 1502 error = ENOMEM; 1503 } 1504 crit_exit(); 1505 break; 1506 } 1507 1508 case DIOCGETSTATE: { 1509 struct pfioc_state *ps = (struct pfioc_state *)addr; 1510 struct pf_state *state; 1511 u_int32_t nr; 1512 1513 nr = 0; 1514 crit_enter(); 1515 RB_FOREACH(state, pf_state_tree_id, &tree_id) { 1516 if (nr >= ps->nr) 1517 break; 1518 nr++; 1519 } 1520 if (state == NULL) { 1521 error = EBUSY; 1522 crit_exit(); 1523 break; 1524 } 1525 bcopy(state, &ps->state, sizeof(struct pf_state)); 1526 ps->state.rule.nr = state->rule.ptr->nr; 1527 ps->state.nat_rule.nr = (state->nat_rule.ptr == NULL) ? 1528 (uint32_t)(-1) : state->nat_rule.ptr->nr; 1529 ps->state.anchor.nr = (state->anchor.ptr == NULL) ? 1530 (uint32_t)(-1) : state->anchor.ptr->nr; 1531 crit_exit(); 1532 ps->state.expire = pf_state_expires(state); 1533 if (ps->state.expire > time_second) 1534 ps->state.expire -= time_second; 1535 else 1536 ps->state.expire = 0; 1537 break; 1538 } 1539 1540 case DIOCGETSTATES: { 1541 struct pfioc_states *ps = (struct pfioc_states *)addr; 1542 struct pf_state *state; 1543 struct pf_state *p, pstore; 1544 struct pfi_kif *kif; 1545 u_int32_t nr = 0; 1546 int space = ps->ps_len; 1547 1548 if (space == 0) { 1549 crit_enter(); 1550 TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) 1551 nr += kif->pfik_states; 1552 crit_exit(); 1553 ps->ps_len = sizeof(struct pf_state) * nr; 1554 return (0); 1555 } 1556 1557 crit_enter(); 1558 p = ps->ps_states; 1559 TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) 1560 RB_FOREACH(state, pf_state_tree_ext_gwy, 1561 &kif->pfik_ext_gwy) { 1562 int secs = time_second; 1563 1564 if ((nr+1) * sizeof(*p) > (unsigned)ps->ps_len) 1565 break; 1566 1567 bcopy(state, &pstore, sizeof(pstore)); 1568 strlcpy(pstore.u.ifname, kif->pfik_name, 1569 sizeof(pstore.u.ifname)); 1570 pstore.rule.nr = state->rule.ptr->nr; 1571 pstore.nat_rule.nr = (state->nat_rule.ptr == 1572 NULL) ? (uint32_t)(-1) 1573 : state->nat_rule.ptr->nr; 1574 pstore.anchor.nr = (state->anchor.ptr == 1575 NULL) ? (uint32_t)(-1) 1576 : state->anchor.ptr->nr; 1577 pstore.creation = secs - pstore.creation; 1578 pstore.expire = pf_state_expires(state); 1579 if (pstore.expire > secs) 1580 pstore.expire -= secs; 1581 else 1582 pstore.expire = 0; 1583 error = copyout(&pstore, p, sizeof(*p)); 1584 if (error) { 1585 crit_exit(); 1586 goto fail; 1587 } 1588 p++; 1589 nr++; 1590 } 1591 ps->ps_len = sizeof(struct pf_state) * nr; 1592 crit_exit(); 1593 break; 1594 } 1595 1596 case DIOCGETSTATUS: { 1597 struct pf_status *s = (struct pf_status *)addr; 1598 bcopy(&pf_status, s, sizeof(struct pf_status)); 1599 pfi_fill_oldstatus(s); 1600 break; 1601 } 1602 1603 case DIOCSETSTATUSIF: { 1604 struct pfioc_if *pi = (struct pfioc_if *)addr; 1605 1606 if (pi->ifname[0] == 0) { 1607 bzero(pf_status.ifname, IFNAMSIZ); 1608 break; 1609 } 1610 if (ifunit(pi->ifname) == NULL) { 1611 error = EINVAL; 1612 break; 1613 } 1614 strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ); 1615 break; 1616 } 1617 1618 case DIOCCLRSTATUS: { 1619 bzero(pf_status.counters, sizeof(pf_status.counters)); 1620 bzero(pf_status.fcounters, sizeof(pf_status.fcounters)); 1621 bzero(pf_status.scounters, sizeof(pf_status.scounters)); 1622 if (*pf_status.ifname) 1623 pfi_clr_istats(pf_status.ifname, NULL, 1624 PFI_FLAG_INSTANCE); 1625 break; 1626 } 1627 1628 case DIOCNATLOOK: { 1629 struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr; 1630 struct pf_state *state; 1631 struct pf_state key; 1632 int m = 0, direction = pnl->direction; 1633 1634 key.af = pnl->af; 1635 key.proto = pnl->proto; 1636 1637 if (!pnl->proto || 1638 PF_AZERO(&pnl->saddr, pnl->af) || 1639 PF_AZERO(&pnl->daddr, pnl->af) || 1640 !pnl->dport || !pnl->sport) 1641 error = EINVAL; 1642 else { 1643 crit_enter(); 1644 1645 /* 1646 * userland gives us source and dest of connection, 1647 * reverse the lookup so we ask for what happens with 1648 * the return traffic, enabling us to find it in the 1649 * state tree. 1650 */ 1651 if (direction == PF_IN) { 1652 PF_ACPY(&key.ext.addr, &pnl->daddr, pnl->af); 1653 key.ext.port = pnl->dport; 1654 PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af); 1655 key.gwy.port = pnl->sport; 1656 state = pf_find_state_all(&key, PF_EXT_GWY, &m); 1657 } else { 1658 PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af); 1659 key.lan.port = pnl->dport; 1660 PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af); 1661 key.ext.port = pnl->sport; 1662 state = pf_find_state_all(&key, PF_LAN_EXT, &m); 1663 } 1664 if (m > 1) 1665 error = E2BIG; /* more than one state */ 1666 else if (state != NULL) { 1667 if (direction == PF_IN) { 1668 PF_ACPY(&pnl->rsaddr, &state->lan.addr, 1669 state->af); 1670 pnl->rsport = state->lan.port; 1671 PF_ACPY(&pnl->rdaddr, &pnl->daddr, 1672 pnl->af); 1673 pnl->rdport = pnl->dport; 1674 } else { 1675 PF_ACPY(&pnl->rdaddr, &state->gwy.addr, 1676 state->af); 1677 pnl->rdport = state->gwy.port; 1678 PF_ACPY(&pnl->rsaddr, &pnl->saddr, 1679 pnl->af); 1680 pnl->rsport = pnl->sport; 1681 } 1682 } else 1683 error = ENOENT; 1684 crit_exit(); 1685 } 1686 break; 1687 } 1688 1689 case DIOCSETTIMEOUT: { 1690 struct pfioc_tm *pt = (struct pfioc_tm *)addr; 1691 int old; 1692 1693 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX || 1694 pt->seconds < 0) { 1695 error = EINVAL; 1696 goto fail; 1697 } 1698 old = pf_default_rule.timeout[pt->timeout]; 1699 pf_default_rule.timeout[pt->timeout] = pt->seconds; 1700 pt->seconds = old; 1701 break; 1702 } 1703 1704 case DIOCGETTIMEOUT: { 1705 struct pfioc_tm *pt = (struct pfioc_tm *)addr; 1706 1707 if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) { 1708 error = EINVAL; 1709 goto fail; 1710 } 1711 pt->seconds = pf_default_rule.timeout[pt->timeout]; 1712 break; 1713 } 1714 1715 case DIOCGETLIMIT: { 1716 struct pfioc_limit *pl = (struct pfioc_limit *)addr; 1717 1718 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) { 1719 error = EINVAL; 1720 goto fail; 1721 } 1722 pl->limit = pf_pool_limits[pl->index].limit; 1723 break; 1724 } 1725 1726 case DIOCSETLIMIT: { 1727 struct pfioc_limit *pl = (struct pfioc_limit *)addr; 1728 int old_limit; 1729 1730 if (pl->index < 0 || pl->index >= PF_LIMIT_MAX || 1731 pf_pool_limits[pl->index].pp == NULL) { 1732 error = EINVAL; 1733 goto fail; 1734 } 1735 1736 /* XXX Get an API to set limits on the zone/pool */ 1737 old_limit = pf_pool_limits[pl->index].limit; 1738 pf_pool_limits[pl->index].limit = pl->limit; 1739 pl->limit = old_limit; 1740 break; 1741 } 1742 1743 case DIOCSETDEBUG: { 1744 u_int32_t *level = (u_int32_t *)addr; 1745 1746 pf_status.debug = *level; 1747 break; 1748 } 1749 1750 case DIOCCLRRULECTRS: { 1751 struct pf_ruleset *ruleset = &pf_main_ruleset; 1752 struct pf_rule *rule; 1753 1754 crit_enter(); 1755 TAILQ_FOREACH(rule, 1756 ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) 1757 rule->evaluations = rule->packets = 1758 rule->bytes = 0; 1759 crit_exit(); 1760 break; 1761 } 1762 1763 case DIOCGIFSPEED: { 1764 struct pf_ifspeed *psp = (struct pf_ifspeed *)addr; 1765 struct pf_ifspeed ps; 1766 struct ifnet *ifp; 1767 1768 if (psp->ifname[0] != 0) { 1769 /* Can we completely trust user-land? */ 1770 strlcpy(ps.ifname, psp->ifname, IFNAMSIZ); 1771 ifp = ifunit(ps.ifname); 1772 if (ifp ) 1773 psp->baudrate = ifp->if_baudrate; 1774 else 1775 error = EINVAL; 1776 } else 1777 error = EINVAL; 1778 break; 1779 } 1780 #ifdef ALTQ 1781 case DIOCSTARTALTQ: { 1782 struct pf_altq *altq; 1783 struct ifnet *ifp; 1784 struct tb_profile tb; 1785 1786 /* enable all altq interfaces on active list */ 1787 crit_enter(); 1788 TAILQ_FOREACH(altq, pf_altqs_active, entries) { 1789 if (altq->qname[0] == 0) { 1790 if ((ifp = ifunit(altq->ifname)) == NULL) { 1791 error = EINVAL; 1792 break; 1793 } 1794 if (ifp->if_snd.altq_type != ALTQT_NONE) 1795 error = altq_enable(&ifp->if_snd); 1796 if (error != 0) 1797 break; 1798 /* set tokenbucket regulator */ 1799 tb.rate = altq->ifbandwidth; 1800 tb.depth = altq->tbrsize; 1801 error = tbr_set(&ifp->if_snd, &tb); 1802 if (error != 0) 1803 break; 1804 } 1805 } 1806 crit_exit(); 1807 DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n")); 1808 break; 1809 } 1810 1811 case DIOCSTOPALTQ: { 1812 struct pf_altq *altq; 1813 struct ifnet *ifp; 1814 struct tb_profile tb; 1815 int err; 1816 1817 /* disable all altq interfaces on active list */ 1818 crit_enter(); 1819 TAILQ_FOREACH(altq, pf_altqs_active, entries) { 1820 if (altq->qname[0] == 0) { 1821 if ((ifp = ifunit(altq->ifname)) == NULL) { 1822 error = EINVAL; 1823 break; 1824 } 1825 if (ifp->if_snd.altq_type != ALTQT_NONE) { 1826 err = altq_disable(&ifp->if_snd); 1827 if (err != 0 && error == 0) 1828 error = err; 1829 } 1830 /* clear tokenbucket regulator */ 1831 tb.rate = 0; 1832 err = tbr_set(&ifp->if_snd, &tb); 1833 if (err != 0 && error == 0) 1834 error = err; 1835 } 1836 } 1837 crit_exit(); 1838 DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n")); 1839 break; 1840 } 1841 1842 case DIOCBEGINALTQS: { 1843 u_int32_t *ticket = (u_int32_t *)addr; 1844 1845 error = pf_begin_altq(ticket); 1846 break; 1847 } 1848 1849 case DIOCADDALTQ: { 1850 struct pfioc_altq *pa = (struct pfioc_altq *)addr; 1851 struct pf_altq *altq, *a; 1852 1853 if (pa->ticket != ticket_altqs_inactive) { 1854 error = EBUSY; 1855 break; 1856 } 1857 altq = pool_get(&pf_altq_pl, PR_NOWAIT); 1858 if (altq == NULL) { 1859 error = ENOMEM; 1860 break; 1861 } 1862 bcopy(&pa->altq, altq, sizeof(struct pf_altq)); 1863 1864 /* 1865 * if this is for a queue, find the discipline and 1866 * copy the necessary fields 1867 */ 1868 if (altq->qname[0] != 0) { 1869 if ((altq->qid = pf_qname2qid(altq->qname)) == 0) { 1870 error = EBUSY; 1871 pool_put(&pf_altq_pl, altq); 1872 break; 1873 } 1874 TAILQ_FOREACH(a, pf_altqs_inactive, entries) { 1875 if (strncmp(a->ifname, altq->ifname, 1876 IFNAMSIZ) == 0 && a->qname[0] == 0) { 1877 altq->altq_disc = a->altq_disc; 1878 break; 1879 } 1880 } 1881 } 1882 1883 error = altq_add(altq); 1884 if (error) { 1885 pool_put(&pf_altq_pl, altq); 1886 break; 1887 } 1888 1889 TAILQ_INSERT_TAIL(pf_altqs_inactive, altq, entries); 1890 bcopy(altq, &pa->altq, sizeof(struct pf_altq)); 1891 break; 1892 } 1893 1894 case DIOCCOMMITALTQS: { 1895 u_int32_t ticket = *(u_int32_t *)addr; 1896 1897 error = pf_commit_altq(ticket); 1898 break; 1899 } 1900 1901 case DIOCGETALTQS: { 1902 struct pfioc_altq *pa = (struct pfioc_altq *)addr; 1903 struct pf_altq *altq; 1904 1905 pa->nr = 0; 1906 crit_enter(); 1907 TAILQ_FOREACH(altq, pf_altqs_active, entries) 1908 pa->nr++; 1909 pa->ticket = ticket_altqs_active; 1910 crit_exit(); 1911 break; 1912 } 1913 1914 case DIOCGETALTQ: { 1915 struct pfioc_altq *pa = (struct pfioc_altq *)addr; 1916 struct pf_altq *altq; 1917 u_int32_t nr; 1918 1919 if (pa->ticket != ticket_altqs_active) { 1920 error = EBUSY; 1921 break; 1922 } 1923 nr = 0; 1924 crit_enter(); 1925 altq = TAILQ_FIRST(pf_altqs_active); 1926 while ((altq != NULL) && (nr < pa->nr)) { 1927 altq = TAILQ_NEXT(altq, entries); 1928 nr++; 1929 } 1930 if (altq == NULL) { 1931 error = EBUSY; 1932 crit_exit(); 1933 break; 1934 } 1935 bcopy(altq, &pa->altq, sizeof(struct pf_altq)); 1936 crit_exit(); 1937 break; 1938 } 1939 1940 case DIOCCHANGEALTQ: 1941 /* CHANGEALTQ not supported yet! */ 1942 error = ENODEV; 1943 break; 1944 1945 case DIOCGETQSTATS: { 1946 struct pfioc_qstats *pq = (struct pfioc_qstats *)addr; 1947 struct pf_altq *altq; 1948 u_int32_t nr; 1949 int nbytes; 1950 1951 if (pq->ticket != ticket_altqs_active) { 1952 error = EBUSY; 1953 break; 1954 } 1955 nbytes = pq->nbytes; 1956 nr = 0; 1957 crit_enter(); 1958 altq = TAILQ_FIRST(pf_altqs_active); 1959 while ((altq != NULL) && (nr < pq->nr)) { 1960 altq = TAILQ_NEXT(altq, entries); 1961 nr++; 1962 } 1963 if (altq == NULL) { 1964 error = EBUSY; 1965 crit_exit(); 1966 break; 1967 } 1968 error = altq_getqstats(altq, pq->buf, &nbytes); 1969 crit_exit(); 1970 if (error == 0) { 1971 pq->scheduler = altq->scheduler; 1972 pq->nbytes = nbytes; 1973 } 1974 break; 1975 } 1976 #endif /* ALTQ */ 1977 1978 case DIOCBEGINADDRS: { 1979 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 1980 1981 pf_empty_pool(&pf_pabuf); 1982 pp->ticket = ++ticket_pabuf; 1983 break; 1984 } 1985 1986 case DIOCADDADDR: { 1987 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 1988 1989 #ifndef INET 1990 if (pp->af == AF_INET) { 1991 error = EAFNOSUPPORT; 1992 break; 1993 } 1994 #endif /* INET */ 1995 #ifndef INET6 1996 if (pp->af == AF_INET6) { 1997 error = EAFNOSUPPORT; 1998 break; 1999 } 2000 #endif /* INET6 */ 2001 if (pp->addr.addr.type != PF_ADDR_ADDRMASK && 2002 pp->addr.addr.type != PF_ADDR_DYNIFTL && 2003 pp->addr.addr.type != PF_ADDR_TABLE) { 2004 error = EINVAL; 2005 break; 2006 } 2007 pa = pool_get(&pf_pooladdr_pl, PR_NOWAIT); 2008 if (pa == NULL) { 2009 error = ENOMEM; 2010 break; 2011 } 2012 bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr)); 2013 if (pa->ifname[0]) { 2014 pa->kif = pfi_attach_rule(pa->ifname); 2015 if (pa->kif == NULL) { 2016 pool_put(&pf_pooladdr_pl, pa); 2017 error = EINVAL; 2018 break; 2019 } 2020 } 2021 if (pfi_dynaddr_setup(&pa->addr, pp->af)) { 2022 pfi_dynaddr_remove(&pa->addr); 2023 pfi_detach_rule(pa->kif); 2024 pool_put(&pf_pooladdr_pl, pa); 2025 error = EINVAL; 2026 break; 2027 } 2028 TAILQ_INSERT_TAIL(&pf_pabuf, pa, entries); 2029 break; 2030 } 2031 2032 case DIOCGETADDRS: { 2033 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 2034 2035 pp->nr = 0; 2036 crit_enter(); 2037 pool = pf_get_pool(pp->anchor, pp->ruleset, pp->ticket, 2038 pp->r_action, pp->r_num, 0, 1, 0); 2039 if (pool == NULL) { 2040 error = EBUSY; 2041 crit_exit(); 2042 break; 2043 } 2044 TAILQ_FOREACH(pa, &pool->list, entries) 2045 pp->nr++; 2046 crit_exit(); 2047 break; 2048 } 2049 2050 case DIOCGETADDR: { 2051 struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr; 2052 u_int32_t nr = 0; 2053 2054 crit_enter(); 2055 pool = pf_get_pool(pp->anchor, pp->ruleset, pp->ticket, 2056 pp->r_action, pp->r_num, 0, 1, 1); 2057 if (pool == NULL) { 2058 error = EBUSY; 2059 crit_exit(); 2060 break; 2061 } 2062 pa = TAILQ_FIRST(&pool->list); 2063 while ((pa != NULL) && (nr < pp->nr)) { 2064 pa = TAILQ_NEXT(pa, entries); 2065 nr++; 2066 } 2067 if (pa == NULL) { 2068 error = EBUSY; 2069 crit_exit(); 2070 break; 2071 } 2072 bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr)); 2073 pfi_dynaddr_copyout(&pp->addr.addr); 2074 pf_tbladdr_copyout(&pp->addr.addr); 2075 crit_exit(); 2076 break; 2077 } 2078 2079 case DIOCCHANGEADDR: { 2080 struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr; 2081 struct pf_pooladdr *oldpa = NULL, *newpa = NULL; 2082 struct pf_ruleset *ruleset; 2083 2084 if (pca->action < PF_CHANGE_ADD_HEAD || 2085 pca->action > PF_CHANGE_REMOVE) { 2086 error = EINVAL; 2087 break; 2088 } 2089 if (pca->addr.addr.type != PF_ADDR_ADDRMASK && 2090 pca->addr.addr.type != PF_ADDR_DYNIFTL && 2091 pca->addr.addr.type != PF_ADDR_TABLE) { 2092 error = EINVAL; 2093 break; 2094 } 2095 2096 ruleset = pf_find_ruleset(pca->anchor, pca->ruleset); 2097 if (ruleset == NULL) { 2098 error = EBUSY; 2099 break; 2100 } 2101 pool = pf_get_pool(pca->anchor, pca->ruleset, pca->ticket, 2102 pca->r_action, pca->r_num, pca->r_last, 1, 1); 2103 if (pool == NULL) { 2104 error = EBUSY; 2105 break; 2106 } 2107 if (pca->action != PF_CHANGE_REMOVE) { 2108 newpa = pool_get(&pf_pooladdr_pl, PR_NOWAIT); 2109 if (newpa == NULL) { 2110 error = ENOMEM; 2111 break; 2112 } 2113 bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr)); 2114 #ifndef INET 2115 if (pca->af == AF_INET) { 2116 pool_put(&pf_pooladdr_pl, newpa); 2117 error = EAFNOSUPPORT; 2118 break; 2119 } 2120 #endif /* INET */ 2121 #ifndef INET6 2122 if (pca->af == AF_INET6) { 2123 pool_put(&pf_pooladdr_pl, newpa); 2124 error = EAFNOSUPPORT; 2125 break; 2126 } 2127 #endif /* INET6 */ 2128 if (newpa->ifname[0]) { 2129 newpa->kif = pfi_attach_rule(newpa->ifname); 2130 if (newpa->kif == NULL) { 2131 pool_put(&pf_pooladdr_pl, newpa); 2132 error = EINVAL; 2133 break; 2134 } 2135 } else 2136 newpa->kif = NULL; 2137 if (pfi_dynaddr_setup(&newpa->addr, pca->af) || 2138 pf_tbladdr_setup(ruleset, &newpa->addr)) { 2139 pfi_dynaddr_remove(&newpa->addr); 2140 pfi_detach_rule(newpa->kif); 2141 pool_put(&pf_pooladdr_pl, newpa); 2142 error = EINVAL; 2143 break; 2144 } 2145 } 2146 2147 crit_enter(); 2148 2149 if (pca->action == PF_CHANGE_ADD_HEAD) 2150 oldpa = TAILQ_FIRST(&pool->list); 2151 else if (pca->action == PF_CHANGE_ADD_TAIL) 2152 oldpa = TAILQ_LAST(&pool->list, pf_palist); 2153 else { 2154 int i = 0; 2155 2156 oldpa = TAILQ_FIRST(&pool->list); 2157 while ((oldpa != NULL) && (i < pca->nr)) { 2158 oldpa = TAILQ_NEXT(oldpa, entries); 2159 i++; 2160 } 2161 if (oldpa == NULL) { 2162 error = EINVAL; 2163 crit_exit(); 2164 break; 2165 } 2166 } 2167 2168 if (pca->action == PF_CHANGE_REMOVE) { 2169 TAILQ_REMOVE(&pool->list, oldpa, entries); 2170 pfi_dynaddr_remove(&oldpa->addr); 2171 pf_tbladdr_remove(&oldpa->addr); 2172 pfi_detach_rule(oldpa->kif); 2173 pool_put(&pf_pooladdr_pl, oldpa); 2174 } else { 2175 if (oldpa == NULL) 2176 TAILQ_INSERT_TAIL(&pool->list, newpa, entries); 2177 else if (pca->action == PF_CHANGE_ADD_HEAD || 2178 pca->action == PF_CHANGE_ADD_BEFORE) 2179 TAILQ_INSERT_BEFORE(oldpa, newpa, entries); 2180 else 2181 TAILQ_INSERT_AFTER(&pool->list, oldpa, 2182 newpa, entries); 2183 } 2184 2185 pool->cur = TAILQ_FIRST(&pool->list); 2186 PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr, 2187 pca->af); 2188 crit_exit(); 2189 break; 2190 } 2191 2192 case DIOCGETANCHORS: { 2193 struct pfioc_anchor *pa = (struct pfioc_anchor *)addr; 2194 struct pf_anchor *anchor; 2195 2196 pa->nr = 0; 2197 TAILQ_FOREACH(anchor, &pf_anchors, entries) 2198 pa->nr++; 2199 break; 2200 } 2201 2202 case DIOCGETANCHOR: { 2203 struct pfioc_anchor *pa = (struct pfioc_anchor *)addr; 2204 struct pf_anchor *anchor; 2205 u_int32_t nr = 0; 2206 2207 anchor = TAILQ_FIRST(&pf_anchors); 2208 while (anchor != NULL && nr < pa->nr) { 2209 anchor = TAILQ_NEXT(anchor, entries); 2210 nr++; 2211 } 2212 if (anchor == NULL) 2213 error = EBUSY; 2214 else 2215 bcopy(anchor->name, pa->name, sizeof(pa->name)); 2216 break; 2217 } 2218 2219 case DIOCGETRULESETS: { 2220 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; 2221 struct pf_anchor *anchor; 2222 struct pf_ruleset *ruleset; 2223 2224 pr->anchor[PF_ANCHOR_NAME_SIZE-1] = 0; 2225 if ((anchor = pf_find_anchor(pr->anchor)) == NULL) { 2226 error = EINVAL; 2227 break; 2228 } 2229 pr->nr = 0; 2230 TAILQ_FOREACH(ruleset, &anchor->rulesets, entries) 2231 pr->nr++; 2232 break; 2233 } 2234 2235 case DIOCGETRULESET: { 2236 struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; 2237 struct pf_anchor *anchor; 2238 struct pf_ruleset *ruleset; 2239 u_int32_t nr = 0; 2240 2241 if ((anchor = pf_find_anchor(pr->anchor)) == NULL) { 2242 error = EINVAL; 2243 break; 2244 } 2245 ruleset = TAILQ_FIRST(&anchor->rulesets); 2246 while (ruleset != NULL && nr < pr->nr) { 2247 ruleset = TAILQ_NEXT(ruleset, entries); 2248 nr++; 2249 } 2250 if (ruleset == NULL) 2251 error = EBUSY; 2252 else 2253 bcopy(ruleset->name, pr->name, sizeof(pr->name)); 2254 break; 2255 } 2256 2257 case DIOCRCLRTABLES: { 2258 struct pfioc_table *io = (struct pfioc_table *)addr; 2259 2260 if (io->pfrio_esize != 0) { 2261 error = ENODEV; 2262 break; 2263 } 2264 error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel, 2265 io->pfrio_flags | PFR_FLAG_USERIOCTL); 2266 break; 2267 } 2268 2269 case DIOCRADDTABLES: { 2270 struct pfioc_table *io = (struct pfioc_table *)addr; 2271 2272 if (io->pfrio_esize != sizeof(struct pfr_table)) { 2273 error = ENODEV; 2274 break; 2275 } 2276 error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size, 2277 &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL); 2278 break; 2279 } 2280 2281 case DIOCRDELTABLES: { 2282 struct pfioc_table *io = (struct pfioc_table *)addr; 2283 2284 if (io->pfrio_esize != sizeof(struct pfr_table)) { 2285 error = ENODEV; 2286 break; 2287 } 2288 error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size, 2289 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); 2290 break; 2291 } 2292 2293 case DIOCRGETTABLES: { 2294 struct pfioc_table *io = (struct pfioc_table *)addr; 2295 2296 if (io->pfrio_esize != sizeof(struct pfr_table)) { 2297 error = ENODEV; 2298 break; 2299 } 2300 error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer, 2301 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); 2302 break; 2303 } 2304 2305 case DIOCRGETTSTATS: { 2306 struct pfioc_table *io = (struct pfioc_table *)addr; 2307 2308 if (io->pfrio_esize != sizeof(struct pfr_tstats)) { 2309 error = ENODEV; 2310 break; 2311 } 2312 error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer, 2313 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); 2314 break; 2315 } 2316 2317 case DIOCRCLRTSTATS: { 2318 struct pfioc_table *io = (struct pfioc_table *)addr; 2319 2320 if (io->pfrio_esize != sizeof(struct pfr_table)) { 2321 error = ENODEV; 2322 break; 2323 } 2324 error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size, 2325 &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL); 2326 break; 2327 } 2328 2329 case DIOCRSETTFLAGS: { 2330 struct pfioc_table *io = (struct pfioc_table *)addr; 2331 2332 if (io->pfrio_esize != sizeof(struct pfr_table)) { 2333 error = ENODEV; 2334 break; 2335 } 2336 error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size, 2337 io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange, 2338 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); 2339 break; 2340 } 2341 2342 case DIOCRCLRADDRS: { 2343 struct pfioc_table *io = (struct pfioc_table *)addr; 2344 2345 if (io->pfrio_esize != 0) { 2346 error = ENODEV; 2347 break; 2348 } 2349 error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel, 2350 io->pfrio_flags | PFR_FLAG_USERIOCTL); 2351 break; 2352 } 2353 2354 case DIOCRADDADDRS: { 2355 struct pfioc_table *io = (struct pfioc_table *)addr; 2356 2357 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2358 error = ENODEV; 2359 break; 2360 } 2361 error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer, 2362 io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags | 2363 PFR_FLAG_USERIOCTL); 2364 break; 2365 } 2366 2367 case DIOCRDELADDRS: { 2368 struct pfioc_table *io = (struct pfioc_table *)addr; 2369 2370 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2371 error = ENODEV; 2372 break; 2373 } 2374 error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer, 2375 io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags | 2376 PFR_FLAG_USERIOCTL); 2377 break; 2378 } 2379 2380 case DIOCRSETADDRS: { 2381 struct pfioc_table *io = (struct pfioc_table *)addr; 2382 2383 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2384 error = ENODEV; 2385 break; 2386 } 2387 error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer, 2388 io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd, 2389 &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags | 2390 PFR_FLAG_USERIOCTL); 2391 break; 2392 } 2393 2394 case DIOCRGETADDRS: { 2395 struct pfioc_table *io = (struct pfioc_table *)addr; 2396 2397 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2398 error = ENODEV; 2399 break; 2400 } 2401 error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer, 2402 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); 2403 break; 2404 } 2405 2406 case DIOCRGETASTATS: { 2407 struct pfioc_table *io = (struct pfioc_table *)addr; 2408 2409 if (io->pfrio_esize != sizeof(struct pfr_astats)) { 2410 error = ENODEV; 2411 break; 2412 } 2413 error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer, 2414 &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL); 2415 break; 2416 } 2417 2418 case DIOCRCLRASTATS: { 2419 struct pfioc_table *io = (struct pfioc_table *)addr; 2420 2421 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2422 error = ENODEV; 2423 break; 2424 } 2425 error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer, 2426 io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags | 2427 PFR_FLAG_USERIOCTL); 2428 break; 2429 } 2430 2431 case DIOCRTSTADDRS: { 2432 struct pfioc_table *io = (struct pfioc_table *)addr; 2433 2434 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2435 error = ENODEV; 2436 break; 2437 } 2438 error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer, 2439 io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags | 2440 PFR_FLAG_USERIOCTL); 2441 break; 2442 } 2443 2444 case DIOCRINABEGIN: { 2445 struct pfioc_table *io = (struct pfioc_table *)addr; 2446 2447 if (io->pfrio_esize != 0) { 2448 error = ENODEV; 2449 break; 2450 } 2451 error = pfr_ina_begin(&io->pfrio_table, &io->pfrio_ticket, 2452 &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); 2453 break; 2454 } 2455 2456 case DIOCRINACOMMIT: { 2457 struct pfioc_table *io = (struct pfioc_table *)addr; 2458 2459 if (io->pfrio_esize != 0) { 2460 error = ENODEV; 2461 break; 2462 } 2463 error = pfr_ina_commit(&io->pfrio_table, io->pfrio_ticket, 2464 &io->pfrio_nadd, &io->pfrio_nchange, io->pfrio_flags | 2465 PFR_FLAG_USERIOCTL); 2466 break; 2467 } 2468 2469 case DIOCRINADEFINE: { 2470 struct pfioc_table *io = (struct pfioc_table *)addr; 2471 2472 if (io->pfrio_esize != sizeof(struct pfr_addr)) { 2473 error = ENODEV; 2474 break; 2475 } 2476 error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer, 2477 io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr, 2478 io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL); 2479 break; 2480 } 2481 2482 case DIOCOSFPADD: { 2483 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr; 2484 crit_enter(); 2485 error = pf_osfp_add(io); 2486 crit_exit(); 2487 break; 2488 } 2489 2490 case DIOCOSFPGET: { 2491 struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr; 2492 crit_enter(); 2493 error = pf_osfp_get(io); 2494 crit_exit(); 2495 break; 2496 } 2497 2498 case DIOCXBEGIN: { 2499 struct pfioc_trans *io = (struct pfioc_trans *)addr; 2500 struct pfioc_trans_e ioe; 2501 struct pfr_table table; 2502 int i; 2503 2504 if (io->esize != sizeof(ioe)) { 2505 error = ENODEV; 2506 goto fail; 2507 } 2508 for (i = 0; i < io->size; i++) { 2509 if (copyin(io->array+i, &ioe, sizeof(ioe))) { 2510 error = EFAULT; 2511 goto fail; 2512 } 2513 switch (ioe.rs_num) { 2514 #ifdef ALTQ 2515 case PF_RULESET_ALTQ: 2516 if (ioe.anchor[0] || ioe.ruleset[0]) { 2517 error = EINVAL; 2518 goto fail; 2519 } 2520 if ((error = pf_begin_altq(&ioe.ticket))) 2521 goto fail; 2522 break; 2523 #endif /* ALTQ */ 2524 case PF_RULESET_TABLE: 2525 bzero(&table, sizeof(table)); 2526 strlcpy(table.pfrt_anchor, ioe.anchor, 2527 sizeof(table.pfrt_anchor)); 2528 strlcpy(table.pfrt_ruleset, ioe.ruleset, 2529 sizeof(table.pfrt_ruleset)); 2530 if ((error = pfr_ina_begin(&table, 2531 &ioe.ticket, NULL, 0))) 2532 goto fail; 2533 break; 2534 default: 2535 if ((error = pf_begin_rules(&ioe.ticket, 2536 ioe.rs_num, ioe.anchor, ioe.ruleset))) 2537 goto fail; 2538 break; 2539 } 2540 if (copyout(&ioe, io->array+i, sizeof(io->array[i]))) { 2541 error = EFAULT; 2542 goto fail; 2543 } 2544 } 2545 break; 2546 } 2547 2548 case DIOCXROLLBACK: { 2549 struct pfioc_trans *io = (struct pfioc_trans *)addr; 2550 struct pfioc_trans_e ioe; 2551 struct pfr_table table; 2552 int i; 2553 2554 if (io->esize != sizeof(ioe)) { 2555 error = ENODEV; 2556 goto fail; 2557 } 2558 for (i = 0; i < io->size; i++) { 2559 if (copyin(io->array+i, &ioe, sizeof(ioe))) { 2560 error = EFAULT; 2561 goto fail; 2562 } 2563 switch (ioe.rs_num) { 2564 #ifdef ALTQ 2565 case PF_RULESET_ALTQ: 2566 if (ioe.anchor[0] || ioe.ruleset[0]) { 2567 error = EINVAL; 2568 goto fail; 2569 } 2570 if ((error = pf_rollback_altq(ioe.ticket))) 2571 goto fail; /* really bad */ 2572 break; 2573 #endif /* ALTQ */ 2574 case PF_RULESET_TABLE: 2575 bzero(&table, sizeof(table)); 2576 strlcpy(table.pfrt_anchor, ioe.anchor, 2577 sizeof(table.pfrt_anchor)); 2578 strlcpy(table.pfrt_ruleset, ioe.ruleset, 2579 sizeof(table.pfrt_ruleset)); 2580 if ((error = pfr_ina_rollback(&table, 2581 ioe.ticket, NULL, 0))) 2582 goto fail; /* really bad */ 2583 break; 2584 default: 2585 if ((error = pf_rollback_rules(ioe.ticket, 2586 ioe.rs_num, ioe.anchor, ioe.ruleset))) 2587 goto fail; /* really bad */ 2588 break; 2589 } 2590 } 2591 break; 2592 } 2593 2594 case DIOCXCOMMIT: { 2595 struct pfioc_trans *io = (struct pfioc_trans *)addr; 2596 struct pfioc_trans_e ioe; 2597 struct pfr_table table; 2598 struct pf_ruleset *rs; 2599 int i; 2600 2601 if (io->esize != sizeof(ioe)) { 2602 error = ENODEV; 2603 goto fail; 2604 } 2605 /* first makes sure everything will succeed */ 2606 for (i = 0; i < io->size; i++) { 2607 if (copyin(io->array+i, &ioe, sizeof(ioe))) { 2608 error = EFAULT; 2609 goto fail; 2610 } 2611 switch (ioe.rs_num) { 2612 #ifdef ALTQ 2613 case PF_RULESET_ALTQ: 2614 if (ioe.anchor[0] || ioe.ruleset[0]) { 2615 error = EINVAL; 2616 goto fail; 2617 } 2618 if (!altqs_inactive_open || ioe.ticket != 2619 ticket_altqs_inactive) { 2620 error = EBUSY; 2621 goto fail; 2622 } 2623 break; 2624 #endif /* ALTQ */ 2625 case PF_RULESET_TABLE: 2626 rs = pf_find_ruleset(ioe.anchor, ioe.ruleset); 2627 if (rs == NULL || !rs->topen || ioe.ticket != 2628 rs->tticket) { 2629 error = EBUSY; 2630 goto fail; 2631 } 2632 break; 2633 default: 2634 if (ioe.rs_num < 0 || ioe.rs_num >= 2635 PF_RULESET_MAX) { 2636 error = EINVAL; 2637 goto fail; 2638 } 2639 rs = pf_find_ruleset(ioe.anchor, ioe.ruleset); 2640 if (rs == NULL || 2641 !rs->rules[ioe.rs_num].inactive.open || 2642 rs->rules[ioe.rs_num].inactive.ticket != 2643 ioe.ticket) { 2644 error = EBUSY; 2645 goto fail; 2646 } 2647 break; 2648 } 2649 } 2650 /* now do the commit - no errors should happen here */ 2651 for (i = 0; i < io->size; i++) { 2652 if (copyin(io->array+i, &ioe, sizeof(ioe))) { 2653 error = EFAULT; 2654 goto fail; 2655 } 2656 switch (ioe.rs_num) { 2657 #ifdef ALTQ 2658 case PF_RULESET_ALTQ: 2659 if ((error = pf_commit_altq(ioe.ticket))) 2660 goto fail; /* really bad */ 2661 break; 2662 #endif /* ALTQ */ 2663 case PF_RULESET_TABLE: 2664 bzero(&table, sizeof(table)); 2665 strlcpy(table.pfrt_anchor, ioe.anchor, 2666 sizeof(table.pfrt_anchor)); 2667 strlcpy(table.pfrt_ruleset, ioe.ruleset, 2668 sizeof(table.pfrt_ruleset)); 2669 if ((error = pfr_ina_commit(&table, ioe.ticket, 2670 NULL, NULL, 0))) 2671 goto fail; /* really bad */ 2672 break; 2673 default: 2674 if ((error = pf_commit_rules(ioe.ticket, 2675 ioe.rs_num, ioe.anchor, ioe.ruleset))) 2676 goto fail; /* really bad */ 2677 break; 2678 } 2679 } 2680 break; 2681 } 2682 2683 case DIOCGETSRCNODES: { 2684 struct pfioc_src_nodes *psn = (struct pfioc_src_nodes *)addr; 2685 struct pf_src_node *n; 2686 struct pf_src_node *p, pstore; 2687 u_int32_t nr = 0; 2688 int space = psn->psn_len; 2689 2690 if (space == 0) { 2691 crit_enter(); 2692 RB_FOREACH(n, pf_src_tree, &tree_src_tracking) 2693 nr++; 2694 crit_exit(); 2695 psn->psn_len = sizeof(struct pf_src_node) * nr; 2696 return (0); 2697 } 2698 2699 crit_enter(); 2700 p = psn->psn_src_nodes; 2701 RB_FOREACH(n, pf_src_tree, &tree_src_tracking) { 2702 int secs = time_second; 2703 2704 if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len) 2705 break; 2706 2707 bcopy(n, &pstore, sizeof(pstore)); 2708 if (n->rule.ptr != NULL) 2709 pstore.rule.nr = n->rule.ptr->nr; 2710 pstore.creation = secs - pstore.creation; 2711 if (pstore.expire > secs) 2712 pstore.expire -= secs; 2713 else 2714 pstore.expire = 0; 2715 error = copyout(&pstore, p, sizeof(*p)); 2716 if (error) { 2717 crit_exit(); 2718 goto fail; 2719 } 2720 p++; 2721 nr++; 2722 } 2723 psn->psn_len = sizeof(struct pf_src_node) * nr; 2724 crit_exit(); 2725 break; 2726 } 2727 2728 case DIOCCLRSRCNODES: { 2729 struct pf_src_node *n; 2730 struct pf_state *state; 2731 2732 crit_enter(); 2733 RB_FOREACH(state, pf_state_tree_id, &tree_id) { 2734 state->src_node = NULL; 2735 state->nat_src_node = NULL; 2736 } 2737 RB_FOREACH(n, pf_src_tree, &tree_src_tracking) { 2738 n->expire = 1; 2739 n->states = 0; 2740 } 2741 pf_purge_expired_src_nodes(); 2742 pf_status.src_nodes = 0; 2743 crit_exit(); 2744 break; 2745 } 2746 2747 case DIOCSETHOSTID: { 2748 u_int32_t *hostid = (u_int32_t *)addr; 2749 2750 if (*hostid == 0) { 2751 error = EINVAL; 2752 goto fail; 2753 } 2754 pf_status.hostid = *hostid; 2755 break; 2756 } 2757 2758 case DIOCOSFPFLUSH: 2759 crit_enter(); 2760 pf_osfp_flush(); 2761 crit_exit(); 2762 break; 2763 2764 case DIOCIGETIFACES: { 2765 struct pfioc_iface *io = (struct pfioc_iface *)addr; 2766 2767 if (io->pfiio_esize != sizeof(struct pfi_if)) { 2768 error = ENODEV; 2769 break; 2770 } 2771 error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer, 2772 &io->pfiio_size, io->pfiio_flags); 2773 break; 2774 } 2775 2776 case DIOCICLRISTATS: { 2777 struct pfioc_iface *io = (struct pfioc_iface *)addr; 2778 2779 error = pfi_clr_istats(io->pfiio_name, &io->pfiio_nzero, 2780 io->pfiio_flags); 2781 break; 2782 } 2783 2784 default: 2785 error = ENODEV; 2786 break; 2787 } 2788 fail: 2789 return (error); 2790 } 2791 2792 /* 2793 * XXX - Check for version missmatch!!! 2794 */ 2795 static void 2796 pf_clear_states(void) 2797 { 2798 struct pf_state *state; 2799 2800 RB_FOREACH(state, pf_state_tree_id, &tree_id) { 2801 state->timeout = PFTM_PURGE; 2802 #if NPFSYNC 2803 /* don't send out individual delete messages */ 2804 state->sync_flags = PFSTATE_NOSYNC; 2805 #endif 2806 } 2807 pf_purge_expired_states(); 2808 pf_status.states = 0; 2809 #if 0 /* NPFSYNC */ 2810 /* 2811 * XXX This is called on module unload, we do not want to sync that over? */ 2812 */ 2813 pfsync_clear_states(pf_status.hostid, psk->psk_ifname); 2814 #endif 2815 } 2816 2817 static int 2818 pf_clear_tables(void) 2819 { 2820 struct pfioc_table io; 2821 int error; 2822 2823 bzero(&io, sizeof(io)); 2824 2825 error = pfr_clr_tables(&io.pfrio_table, &io.pfrio_ndel, 2826 io.pfrio_flags); 2827 2828 return (error); 2829 } 2830 2831 static void 2832 pf_clear_srcnodes(void) 2833 { 2834 struct pf_src_node *n; 2835 struct pf_state *state; 2836 2837 RB_FOREACH(state, pf_state_tree_id, &tree_id) { 2838 state->src_node = NULL; 2839 state->nat_src_node = NULL; 2840 } 2841 RB_FOREACH(n, pf_src_tree, &tree_src_tracking) { 2842 n->expire = 1; 2843 n->states = 0; 2844 } 2845 pf_purge_expired_src_nodes(); 2846 pf_status.src_nodes = 0; 2847 } 2848 /* 2849 * XXX - Check for version missmatch!!! 2850 */ 2851 2852 /* 2853 * Duplicate pfctl -Fa operation to get rid of as much as we can. 2854 */ 2855 static int 2856 shutdown_pf(void) 2857 { 2858 int error = 0; 2859 u_int32_t t[5]; 2860 char nn = '\0'; 2861 2862 callout_stop(&pf_expire_to); 2863 2864 pf_status.running = 0; 2865 do { 2866 if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn, 2867 &nn)) != 0) { 2868 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: SCRUB\n")); 2869 break; 2870 } 2871 if ((error = pf_begin_rules(&t[1], PF_RULESET_FILTER, &nn, 2872 &nn)) != 0) { 2873 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: FILTER\n")); 2874 break; /* XXX: rollback? */ 2875 } 2876 if ((error = pf_begin_rules(&t[2], PF_RULESET_NAT, &nn, &nn)) 2877 != 0) { 2878 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: NAT\n")); 2879 break; /* XXX: rollback? */ 2880 } 2881 if ((error = pf_begin_rules(&t[3], PF_RULESET_BINAT, &nn, &nn)) 2882 != 0) { 2883 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: BINAT\n")); 2884 break; /* XXX: rollback? */ 2885 } 2886 if ((error = pf_begin_rules(&t[4], PF_RULESET_RDR, &nn, &nn)) 2887 != 0) { 2888 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: RDR\n")); 2889 break; /* XXX: rollback? */ 2890 } 2891 2892 /* XXX: these should always succeed here */ 2893 pf_commit_rules(t[0], PF_RULESET_SCRUB, &nn, &nn); 2894 pf_commit_rules(t[1], PF_RULESET_FILTER, &nn, &nn); 2895 pf_commit_rules(t[2], PF_RULESET_NAT, &nn, &nn); 2896 pf_commit_rules(t[3], PF_RULESET_BINAT, &nn, &nn); 2897 pf_commit_rules(t[4], PF_RULESET_RDR, &nn, &nn); 2898 2899 if ((error = pf_clear_tables()) != 0) 2900 break; 2901 2902 #ifdef ALTQ 2903 if ((error = pf_begin_altq(&t[0])) != 0) { 2904 DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: ALTQ\n")); 2905 break; 2906 } 2907 pf_commit_altq(t[0]); 2908 #endif 2909 2910 pf_clear_states(); 2911 2912 pf_clear_srcnodes(); 2913 2914 /* status does not use malloced mem so no need to cleanup */ 2915 /* fingerprints and interfaces have their own cleanup code */ 2916 } while(0); 2917 2918 return (error); 2919 } 2920 2921 static int 2922 pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir) 2923 { 2924 /* 2925 * DragonFly's version of pf uses FreeBSD's native host byte ordering 2926 * for ip_len/ip_off. This is why we don't have to change byte order 2927 * like the FreeBSD-5 version does. 2928 */ 2929 int chk; 2930 2931 chk = pf_test(PF_IN, ifp, m); 2932 if (chk && *m) { 2933 m_freem(*m); 2934 *m = NULL; 2935 } 2936 return chk; 2937 } 2938 2939 static int 2940 pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir) 2941 { 2942 /* 2943 * DragonFly's version of pf uses FreeBSD's native host byte ordering 2944 * for ip_len/ip_off. This is why we don't have to change byte order 2945 * like the FreeBSD-5 version does. 2946 */ 2947 int chk; 2948 2949 /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */ 2950 if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 2951 in_delayed_cksum(*m); 2952 (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 2953 } 2954 chk = pf_test(PF_OUT, ifp, m); 2955 if (chk && *m) { 2956 m_freem(*m); 2957 *m = NULL; 2958 } 2959 return chk; 2960 } 2961 2962 #ifdef INET6 2963 static int 2964 pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir) 2965 { 2966 /* 2967 * IPv6 is not affected by ip_len/ip_off byte order changes. 2968 */ 2969 int chk; 2970 2971 chk = pf_test6(PF_IN, ifp, m); 2972 if (chk && *m) { 2973 m_freem(*m); 2974 *m = NULL; 2975 } 2976 return chk; 2977 } 2978 2979 static int 2980 pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir) 2981 { 2982 /* 2983 * IPv6 is not affected by ip_len/ip_off byte order changes. 2984 */ 2985 int chk; 2986 2987 /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */ 2988 if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 2989 in_delayed_cksum(*m); 2990 (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 2991 } 2992 chk = pf_test6(PF_OUT, ifp, m); 2993 if (chk && *m) { 2994 m_freem(*m); 2995 *m = NULL; 2996 } 2997 return chk; 2998 } 2999 #endif /* INET6 */ 3000 3001 static int 3002 hook_pf(void) 3003 { 3004 struct pfil_head *pfh_inet; 3005 #ifdef INET6 3006 struct pfil_head *pfh_inet6; 3007 #endif 3008 3009 if (pf_pfil_hooked) 3010 return (0); 3011 3012 pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); 3013 if (pfh_inet == NULL) 3014 return (ENODEV); 3015 pfil_add_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet); 3016 pfil_add_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet); 3017 #ifdef INET6 3018 pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); 3019 if (pfh_inet6 == NULL) { 3020 pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, 3021 pfh_inet); 3022 pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, 3023 pfh_inet); 3024 return (ENODEV); 3025 } 3026 pfil_add_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6); 3027 pfil_add_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6); 3028 #endif 3029 3030 pf_pfil_hooked = 1; 3031 return (0); 3032 } 3033 3034 static int 3035 dehook_pf(void) 3036 { 3037 struct pfil_head *pfh_inet; 3038 #ifdef INET6 3039 struct pfil_head *pfh_inet6; 3040 #endif 3041 3042 if (pf_pfil_hooked == 0) 3043 return (0); 3044 3045 pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET); 3046 if (pfh_inet == NULL) 3047 return (ENODEV); 3048 pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, 3049 pfh_inet); 3050 pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, 3051 pfh_inet); 3052 #ifdef INET6 3053 pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6); 3054 if (pfh_inet6 == NULL) 3055 return (ENODEV); 3056 pfil_remove_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, 3057 pfh_inet6); 3058 pfil_remove_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, 3059 pfh_inet6); 3060 #endif 3061 3062 pf_pfil_hooked = 0; 3063 return (0); 3064 } 3065 3066 static int 3067 pf_load(void) 3068 { 3069 int error; 3070 3071 init_zone_var(); 3072 error = dev_ops_add(&pf_ops, 0, 0); 3073 if (error) 3074 return (error); 3075 pf_dev = make_dev(&pf_ops, 0, 0, 0, 0600, PF_NAME); 3076 error = pfattach(); 3077 if (error) { 3078 dev_ops_remove(&pf_ops, 0, 0); 3079 return (error); 3080 } 3081 return (0); 3082 } 3083 3084 static int 3085 pf_unload(void) 3086 { 3087 int error; 3088 3089 pf_status.running = 0; 3090 error = dehook_pf(); 3091 if (error) { 3092 /* 3093 * Should not happen! 3094 * XXX Due to error code ESRCH, kldunload will show 3095 * a message like 'No such process'. 3096 */ 3097 kprintf("pfil unregistration fail\n"); 3098 return error; 3099 } 3100 shutdown_pf(); 3101 pfi_cleanup(); 3102 pf_osfp_flush(); 3103 pf_osfp_cleanup(); 3104 cleanup_pf_zone(); 3105 dev_ops_remove(&pf_ops, 0, 0); 3106 return 0; 3107 } 3108 3109 static int 3110 pf_modevent(module_t mod, int type, void *data) 3111 { 3112 int error = 0; 3113 3114 switch(type) { 3115 case MOD_LOAD: 3116 error = pf_load(); 3117 break; 3118 3119 case MOD_UNLOAD: 3120 error = pf_unload(); 3121 break; 3122 default: 3123 error = EINVAL; 3124 break; 3125 } 3126 return error; 3127 } 3128 3129 static moduledata_t pf_mod = { 3130 "pf", 3131 pf_modevent, 3132 0 3133 }; 3134 3135 DECLARE_MODULE(pf, pf_mod, SI_SUB_PSEUDO, SI_ORDER_FIRST); 3136 MODULE_VERSION(pf, PF_MODVER); 3137