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.11 2006/12/22 23:44:57 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); 605 if (tag == NULL) 606 return (0); 607 bzero(tag, sizeof(struct pf_tagname)); 608 strlcpy(tag->name, tagname, sizeof(tag->name)); 609 tag->tag = new_tagid; 610 tag->ref++; 611 612 if (p != NULL) /* insert new entry before p */ 613 TAILQ_INSERT_BEFORE(p, tag, entries); 614 else /* either list empty or no free slot in between */ 615 TAILQ_INSERT_TAIL(head, tag, entries); 616 617 return (tag->tag); 618 } 619 620 static void 621 tag2tagname(struct pf_tags *head, u_int16_t tagid, char *p) 622 { 623 struct pf_tagname *tag; 624 625 TAILQ_FOREACH(tag, head, entries) 626 if (tag->tag == tagid) { 627 strlcpy(p, tag->name, PF_TAG_NAME_SIZE); 628 return; 629 } 630 } 631 632 static void 633 tag_unref(struct pf_tags *head, u_int16_t tag) 634 { 635 struct pf_tagname *p, *next; 636 637 if (tag == 0) 638 return; 639 640 for (p = TAILQ_FIRST(head); p != NULL; p = next) { 641 next = TAILQ_NEXT(p, entries); 642 if (tag == p->tag) { 643 if (--p->ref == 0) { 644 TAILQ_REMOVE(head, p, entries); 645 kfree(p, M_TEMP); 646 } 647 break; 648 } 649 } 650 } 651 652 u_int16_t 653 pf_tagname2tag(char *tagname) 654 { 655 return (tagname2tag(&pf_tags, tagname)); 656 } 657 658 void 659 pf_tag2tagname(u_int16_t tagid, char *p) 660 { 661 return (tag2tagname(&pf_tags, tagid, p)); 662 } 663 664 void 665 pf_tag_unref(u_int16_t tag) 666 { 667 return (tag_unref(&pf_tags, tag)); 668 } 669 670 #ifdef ALTQ 671 u_int32_t 672 pf_qname2qid(char *qname) 673 { 674 return ((u_int32_t)tagname2tag(&pf_qids, qname)); 675 } 676 677 void 678 pf_qid2qname(u_int32_t qid, char *p) 679 { 680 return (tag2tagname(&pf_qids, (u_int16_t)qid, p)); 681 } 682 683 void 684 pf_qid_unref(u_int32_t qid) 685 { 686 return (tag_unref(&pf_qids, (u_int16_t)qid)); 687 } 688 689 int 690 pf_begin_altq(u_int32_t *ticket) 691 { 692 struct pf_altq *altq; 693 int error = 0; 694 695 /* Purge the old altq list */ 696 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) { 697 TAILQ_REMOVE(pf_altqs_inactive, altq, entries); 698 if (altq->qname[0] == 0) { 699 /* detach and destroy the discipline */ 700 error = altq_remove(altq); 701 } else 702 pf_qid_unref(altq->qid); 703 pool_put(&pf_altq_pl, altq); 704 } 705 if (error) 706 return (error); 707 *ticket = ++ticket_altqs_inactive; 708 altqs_inactive_open = 1; 709 return (0); 710 } 711 712 int 713 pf_rollback_altq(u_int32_t ticket) 714 { 715 struct pf_altq *altq; 716 int error = 0; 717 718 if (!altqs_inactive_open || ticket != ticket_altqs_inactive) 719 return (0); 720 /* Purge the old altq list */ 721 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) { 722 TAILQ_REMOVE(pf_altqs_inactive, altq, entries); 723 if (altq->qname[0] == 0) { 724 /* detach and destroy the discipline */ 725 error = altq_remove(altq); 726 } else 727 pf_qid_unref(altq->qid); 728 pool_put(&pf_altq_pl, altq); 729 } 730 altqs_inactive_open = 0; 731 return (error); 732 } 733 734 int 735 pf_commit_altq(u_int32_t ticket) 736 { 737 struct pf_altqqueue *old_altqs; 738 struct pf_altq *altq; 739 int err, error = 0; 740 741 if (!altqs_inactive_open || ticket != ticket_altqs_inactive) 742 return (EBUSY); 743 744 /* swap altqs, keep the old. */ 745 crit_enter(); 746 old_altqs = pf_altqs_active; 747 pf_altqs_active = pf_altqs_inactive; 748 pf_altqs_inactive = old_altqs; 749 ticket_altqs_active = ticket_altqs_inactive; 750 751 /* Attach new disciplines */ 752 TAILQ_FOREACH(altq, pf_altqs_active, entries) { 753 if (altq->qname[0] == 0) { 754 /* attach the discipline */ 755 error = altq_pfattach(altq); 756 if (error) { 757 crit_exit(); 758 return (error); 759 } 760 } 761 } 762 763 /* Purge the old altq list */ 764 while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) { 765 TAILQ_REMOVE(pf_altqs_inactive, altq, entries); 766 if (altq->qname[0] == 0) { 767 /* detach and destroy the discipline */ 768 err = altq_pfdetach(altq); 769 if (err != 0 && error == 0) 770 error = err; 771 err = altq_remove(altq); 772 if (err != 0 && error == 0) 773 error = err; 774 } else 775 pf_qid_unref(altq->qid); 776 pool_put(&pf_altq_pl, altq); 777 } 778 crit_exit(); 779 780 altqs_inactive_open = 0; 781 return (error); 782 } 783 #endif /* ALTQ */ 784 785 int 786 pf_begin_rules(u_int32_t *ticket, int rs_num, char *anchor, char *ruleset) 787 { 788 struct pf_ruleset *rs; 789 struct pf_rule *rule; 790 791 if (rs_num < 0 || rs_num >= PF_RULESET_MAX) 792 return (EINVAL); 793 rs = pf_find_or_create_ruleset(anchor, ruleset); 794 if (rs == NULL) 795 return (EINVAL); 796 while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) 797 pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule); 798 *ticket = ++rs->rules[rs_num].inactive.ticket; 799 rs->rules[rs_num].inactive.open = 1; 800 return (0); 801 } 802 803 int 804 pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset) 805 { 806 struct pf_ruleset *rs; 807 struct pf_rule *rule; 808 809 if (rs_num < 0 || rs_num >= PF_RULESET_MAX) 810 return (EINVAL); 811 rs = pf_find_ruleset(anchor, ruleset); 812 if (rs == NULL || !rs->rules[rs_num].inactive.open || 813 rs->rules[rs_num].inactive.ticket != ticket) 814 return (0); 815 while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) 816 pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule); 817 rs->rules[rs_num].inactive.open = 0; 818 return (0); 819 } 820 821 int 822 pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor, char *ruleset) 823 { 824 struct pf_ruleset *rs; 825 struct pf_rule *rule; 826 struct pf_rulequeue *old_rules; 827 828 if (rs_num < 0 || rs_num >= PF_RULESET_MAX) 829 return (EINVAL); 830 rs = pf_find_ruleset(anchor, ruleset); 831 if (rs == NULL || !rs->rules[rs_num].inactive.open || 832 ticket != rs->rules[rs_num].inactive.ticket) 833 return (EBUSY); 834 835 /* Swap rules, keep the old. */ 836 crit_enter(); 837 old_rules = rs->rules[rs_num].active.ptr; 838 rs->rules[rs_num].active.ptr = 839 rs->rules[rs_num].inactive.ptr; 840 rs->rules[rs_num].inactive.ptr = old_rules; 841 rs->rules[rs_num].active.ticket = 842 rs->rules[rs_num].inactive.ticket; 843 pf_calc_skip_steps(rs->rules[rs_num].active.ptr); 844 845 /* Purge the old rule list. */ 846 while ((rule = TAILQ_FIRST(old_rules)) != NULL) 847 pf_rm_rule(old_rules, rule); 848 rs->rules[rs_num].inactive.open = 0; 849 pf_remove_if_empty_ruleset(rs); 850 pf_update_anchor_rules(); 851 crit_exit(); 852 return (0); 853 } 854 855 int 856 pfioctl(struct dev_ioctl_args *ap) 857 { 858 u_long cmd = ap->a_cmd; 859 caddr_t addr = ap->a_data; 860 struct pf_pooladdr *pa = NULL; 861 struct pf_pool *pool = NULL; 862 int error = 0; 863 864 /* XXX keep in sync with switch() below */ 865 if (securelevel > 1) 866 switch (cmd) { 867 case DIOCGETRULES: 868 case DIOCGETRULE: 869 case DIOCGETADDRS: 870 case DIOCGETADDR: 871 case DIOCGETSTATE: 872 case DIOCSETSTATUSIF: 873 case DIOCGETSTATUS: 874 case DIOCCLRSTATUS: 875 case DIOCNATLOOK: 876 case DIOCSETDEBUG: 877 case DIOCGETSTATES: 878 case DIOCGETTIMEOUT: 879 case DIOCCLRRULECTRS: 880 case DIOCGETLIMIT: 881 case DIOCGETALTQS: 882 case DIOCGETALTQ: 883 case DIOCGETQSTATS: 884 case DIOCGETANCHORS: 885 case DIOCGETANCHOR: 886 case DIOCGETRULESETS: 887 case DIOCGETRULESET: 888 case DIOCRGETTABLES: 889 case DIOCRGETTSTATS: 890 case DIOCRCLRTSTATS: 891 case DIOCRCLRADDRS: 892 case DIOCRADDADDRS: 893 case DIOCRDELADDRS: 894 case DIOCRSETADDRS: 895 case DIOCRGETADDRS: 896 case DIOCRGETASTATS: 897 case DIOCRCLRASTATS: 898 case DIOCRTSTADDRS: 899 case DIOCOSFPGET: 900 case DIOCGETSRCNODES: 901 case DIOCCLRSRCNODES: 902 case DIOCIGETIFACES: 903 case DIOCICLRISTATS: 904 case DIOCGIFSPEED: 905 break; 906 case DIOCRCLRTABLES: 907 case DIOCRADDTABLES: 908 case DIOCRDELTABLES: 909 case DIOCRSETTFLAGS: 910 if (((struct pfioc_table *)addr)->pfrio_flags & 911 PFR_FLAG_DUMMY) 912 break; /* dummy operation ok */ 913 return (EPERM); 914 default: 915 return (EPERM); 916 } 917 918 if (!(ap->a_fflag & FWRITE)) 919 switch (cmd) { 920 case DIOCGETRULES: 921 case DIOCGETRULE: 922 case DIOCGETADDRS: 923 case DIOCGETADDR: 924 case DIOCGETSTATE: 925 case DIOCGETSTATUS: 926 case DIOCGETSTATES: 927 case DIOCGETTIMEOUT: 928 case DIOCGETLIMIT: 929 case DIOCGETALTQS: 930 case DIOCGETALTQ: 931 case DIOCGETQSTATS: 932 case DIOCGETANCHORS: 933 case DIOCGETANCHOR: 934 case DIOCGETRULESETS: 935 case DIOCGETRULESET: 936 case DIOCRGETTABLES: 937 case DIOCRGETTSTATS: 938 case DIOCRGETADDRS: 939 case DIOCRGETASTATS: 940 case DIOCRTSTADDRS: 941 case DIOCOSFPGET: 942 case DIOCGETSRCNODES: 943 case DIOCIGETIFACES: 944 case DIOCGIFSPEED: 945 break; 946 case DIOCRCLRTABLES: 947 case DIOCRADDTABLES: 948 case DIOCRDELTABLES: 949 case DIOCRCLRTSTATS: 950 case DIOCRCLRADDRS: 951 case DIOCRADDADDRS: 952 case DIOCRDELADDRS: 953 case DIOCRSETADDRS: 954 case DIOCRSETTFLAGS: 955 if (((struct pfioc_table *)addr)->pfrio_flags & 956 PFR_FLAG_DUMMY) 957 break; /* dummy operation ok */ 958 return (EACCES); 959 default: 960 return (EACCES); 961 } 962 963 switch (cmd) { 964 965 case DIOCSTART: 966 if (pf_status.running) 967 error = EEXIST; 968 else { 969 error = hook_pf(); 970 if (error) { 971 DPFPRINTF(PF_DEBUG_MISC, 972 ("pf: pfil registeration fail\n")); 973 break; 974 } 975 pf_status.running = 1; 976 pf_status.since = time_second; 977 if (pf_status.stateid == 0) { 978 pf_status.stateid = time_second; 979 pf_status.stateid = pf_status.stateid << 32; 980 } 981 DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n")); 982 } 983 break; 984 985 case DIOCSTOP: 986 if (!pf_status.running) 987 error = ENOENT; 988 else { 989 pf_status.running = 0; 990 error = dehook_pf(); 991 if (error) { 992 pf_status.running = 1; 993 DPFPRINTF(PF_DEBUG_MISC, 994 ("pf: pfil unregisteration failed\n")); 995 } 996 pf_status.since = time_second; 997 DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n")); 998 } 999 break; 1000 1001 case DIOCBEGINRULES: { 1002 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 1003 1004 error = pf_begin_rules(&pr->ticket, pf_get_ruleset_number( 1005 pr->rule.action), pr->anchor, pr->ruleset); 1006 break; 1007 } 1008 1009 case DIOCADDRULE: { 1010 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 1011 struct pf_ruleset *ruleset; 1012 struct pf_rule *rule, *tail; 1013 struct pf_pooladdr *pa; 1014 int rs_num; 1015 1016 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset); 1017 if (ruleset == NULL) { 1018 error = EINVAL; 1019 break; 1020 } 1021 rs_num = pf_get_ruleset_number(pr->rule.action); 1022 if (rs_num >= PF_RULESET_MAX) { 1023 error = EINVAL; 1024 break; 1025 } 1026 if (pr->rule.anchorname[0] && ruleset != &pf_main_ruleset) { 1027 error = EINVAL; 1028 break; 1029 } 1030 if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { 1031 error = EINVAL; 1032 break; 1033 } 1034 if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) { 1035 error = EBUSY; 1036 break; 1037 } 1038 if (pr->pool_ticket != ticket_pabuf) { 1039 error = EBUSY; 1040 break; 1041 } 1042 rule = pool_get(&pf_rule_pl, PR_NOWAIT); 1043 if (rule == NULL) { 1044 error = ENOMEM; 1045 break; 1046 } 1047 bcopy(&pr->rule, rule, sizeof(struct pf_rule)); 1048 rule->anchor = NULL; 1049 rule->kif = NULL; 1050 TAILQ_INIT(&rule->rpool.list); 1051 /* initialize refcounting */ 1052 rule->states = 0; 1053 rule->src_nodes = 0; 1054 rule->entries.tqe_prev = NULL; 1055 #ifndef INET 1056 if (rule->af == AF_INET) { 1057 pool_put(&pf_rule_pl, rule); 1058 error = EAFNOSUPPORT; 1059 break; 1060 } 1061 #endif /* INET */ 1062 #ifndef INET6 1063 if (rule->af == AF_INET6) { 1064 pool_put(&pf_rule_pl, rule); 1065 error = EAFNOSUPPORT; 1066 break; 1067 } 1068 #endif /* INET6 */ 1069 tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr, 1070 pf_rulequeue); 1071 if (tail) 1072 rule->nr = tail->nr + 1; 1073 else 1074 rule->nr = 0; 1075 if (rule->ifname[0]) { 1076 rule->kif = pfi_attach_rule(rule->ifname); 1077 if (rule->kif == NULL) { 1078 pool_put(&pf_rule_pl, rule); 1079 error = EINVAL; 1080 break; 1081 } 1082 } 1083 1084 #ifdef ALTQ 1085 /* set queue IDs */ 1086 if (rule->qname[0] != 0) { 1087 if ((rule->qid = pf_qname2qid(rule->qname)) == 0) 1088 error = EBUSY; 1089 else if (rule->pqname[0] != 0) { 1090 if ((rule->pqid = 1091 pf_qname2qid(rule->pqname)) == 0) 1092 error = EBUSY; 1093 } else 1094 rule->pqid = rule->qid; 1095 } 1096 #endif 1097 if (rule->tagname[0]) 1098 if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0) 1099 error = EBUSY; 1100 if (rule->match_tagname[0]) 1101 if ((rule->match_tag = 1102 pf_tagname2tag(rule->match_tagname)) == 0) 1103 error = EBUSY; 1104 if (rule->rt && !rule->direction) 1105 error = EINVAL; 1106 if (pfi_dynaddr_setup(&rule->src.addr, rule->af)) 1107 error = EINVAL; 1108 if (pfi_dynaddr_setup(&rule->dst.addr, rule->af)) 1109 error = EINVAL; 1110 if (pf_tbladdr_setup(ruleset, &rule->src.addr)) 1111 error = EINVAL; 1112 if (pf_tbladdr_setup(ruleset, &rule->dst.addr)) 1113 error = EINVAL; 1114 TAILQ_FOREACH(pa, &pf_pabuf, entries) 1115 if (pf_tbladdr_setup(ruleset, &pa->addr)) 1116 error = EINVAL; 1117 1118 pf_mv_pool(&pf_pabuf, &rule->rpool.list); 1119 if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) || 1120 (rule->action == PF_BINAT)) && !rule->anchorname[0]) || 1121 (rule->rt > PF_FASTROUTE)) && 1122 (TAILQ_FIRST(&rule->rpool.list) == NULL)) 1123 error = EINVAL; 1124 1125 if (error) { 1126 pf_rm_rule(NULL, rule); 1127 break; 1128 } 1129 rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list); 1130 rule->evaluations = rule->packets = rule->bytes = 0; 1131 TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr, 1132 rule, entries); 1133 break; 1134 } 1135 1136 case DIOCCOMMITRULES: { 1137 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 1138 1139 error = pf_commit_rules(pr->ticket, pf_get_ruleset_number( 1140 pr->rule.action), pr->anchor, pr->ruleset); 1141 break; 1142 } 1143 1144 case DIOCGETRULES: { 1145 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 1146 struct pf_ruleset *ruleset; 1147 struct pf_rule *tail; 1148 int rs_num; 1149 1150 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset); 1151 if (ruleset == NULL) { 1152 error = EINVAL; 1153 break; 1154 } 1155 rs_num = pf_get_ruleset_number(pr->rule.action); 1156 if (rs_num >= PF_RULESET_MAX) { 1157 error = EINVAL; 1158 break; 1159 } 1160 crit_enter(); 1161 tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, 1162 pf_rulequeue); 1163 if (tail) 1164 pr->nr = tail->nr + 1; 1165 else 1166 pr->nr = 0; 1167 pr->ticket = ruleset->rules[rs_num].active.ticket; 1168 crit_exit(); 1169 break; 1170 } 1171 1172 case DIOCGETRULE: { 1173 struct pfioc_rule *pr = (struct pfioc_rule *)addr; 1174 struct pf_ruleset *ruleset; 1175 struct pf_rule *rule; 1176 int rs_num, i; 1177 1178 ruleset = pf_find_ruleset(pr->anchor, pr->ruleset); 1179 if (ruleset == NULL) { 1180 error = EINVAL; 1181 break; 1182 } 1183 rs_num = pf_get_ruleset_number(pr->rule.action); 1184 if (rs_num >= PF_RULESET_MAX) { 1185 error = EINVAL; 1186 break; 1187 } 1188 if (pr->ticket != ruleset->rules[rs_num].active.ticket) { 1189 error = EBUSY; 1190 break; 1191 } 1192 crit_enter(); 1193 rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr); 1194 while ((rule != NULL) && (rule->nr != pr->nr)) 1195 rule = TAILQ_NEXT(rule, entries); 1196 if (rule == NULL) { 1197 error = EBUSY; 1198 crit_exit(); 1199 break; 1200 } 1201 bcopy(rule, &pr->rule, sizeof(struct pf_rule)); 1202 pfi_dynaddr_copyout(&pr->rule.src.addr); 1203 pfi_dynaddr_copyout(&pr->rule.dst.addr); 1204 pf_tbladdr_copyout(&pr->rule.src.addr); 1205 pf_tbladdr_copyout(&pr->rule.dst.addr); 1206 for (i = 0; i < PF_SKIP_COUNT; ++i) 1207 if (rule->skip[i].ptr == NULL) 1208 pr->rule.skip[i].nr = (uint32_t)(-1); 1209 else 1210 pr->rule.skip[i].nr = 1211 rule->skip[i].ptr->nr; 1212 crit_exit(); 1213 break; 1214 } 1215 1216 case DIOCCHANGERULE: { 1217 struct pfioc_rule *pcr = (struct pfioc_rule *)addr; 1218 struct pf_ruleset *ruleset; 1219 struct pf_rule *oldrule = NULL, *newrule = NULL; 1220 u_int32_t nr = 0; 1221 int rs_num; 1222 1223 if (!(pcr->action == PF_CHANGE_REMOVE || 1224 pcr->action == PF_CHANGE_GET_TICKET) && 1225 pcr->pool_ticket != ticket_pabuf) { 1226 error = EBUSY; 1227 break; 1228 } 1229 1230 if (pcr->action < PF_CHANGE_ADD_HEAD || 1231 pcr->action > PF_CHANGE_GET_TICKET) { 1232 error = EINVAL; 1233 break; 1234 } 1235 ruleset = pf_find_ruleset(pcr->anchor, pcr->ruleset); 1236 if (ruleset == NULL) { 1237 error = EINVAL; 1238 break; 1239 } 1240 rs_num = pf_get_ruleset_number(pcr->rule.action); 1241 if (rs_num >= PF_RULESET_MAX) { 1242 error = EINVAL; 1243 break; 1244 } 1245 1246 if (pcr->action == PF_CHANGE_GET_TICKET) { 1247 pcr->ticket = ++ruleset->rules[rs_num].active.ticket; 1248 break; 1249 } else { 1250 if (pcr->ticket != 1251 ruleset->rules[rs_num].active.ticket) { 1252 error = EINVAL; 1253 break; 1254 } 1255 if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { 1256 error = EINVAL; 1257 break; 1258 } 1259 } 1260 1261 if (pcr->action != PF_CHANGE_REMOVE) { 1262 newrule = pool_get(&pf_rule_pl, PR_NOWAIT); 1263 if (newrule == NULL) { 1264 error = ENOMEM; 1265 break; 1266 } 1267 bcopy(&pcr->rule, newrule, sizeof(struct pf_rule)); 1268 TAILQ_INIT(&newrule->rpool.list); 1269 /* initialize refcounting */ 1270 newrule->states = 0; 1271 newrule->entries.tqe_prev = NULL; 1272 #ifndef INET 1273 if (newrule->af == AF_INET) { 1274 pool_put(&pf_rule_pl, newrule); 1275 error = EAFNOSUPPORT; 1276 break; 1277 } 1278 #endif /* INET */ 1279 #ifndef INET6 1280 if (newrule->af == AF_INET6) { 1281 pool_put(&pf_rule_pl, newrule); 1282 error = EAFNOSUPPORT; 1283 break; 1284 } 1285 #endif /* INET6 */ 1286 if (newrule->ifname[0]) { 1287 newrule->kif = pfi_attach_rule(newrule->ifname); 1288 if (newrule->kif == NULL) { 1289 pool_put(&pf_rule_pl, newrule); 1290 error = EINVAL; 1291 break; 1292 } 1293 } else 1294 newrule->kif = NULL; 1295 1296 #ifdef ALTQ 1297 /* set queue IDs */ 1298 if (newrule->qname[0] != 0) { 1299 if ((newrule->qid = 1300 pf_qname2qid(newrule->qname)) == 0) 1301 error = EBUSY; 1302 else if (newrule->pqname[0] != 0) { 1303 if ((newrule->pqid = 1304 pf_qname2qid(newrule->pqname)) == 0) 1305 error = EBUSY; 1306 } else 1307 newrule->pqid = newrule->qid; 1308 } 1309 #endif 1310 if (newrule->tagname[0]) 1311 if ((newrule->tag = 1312 pf_tagname2tag(newrule->tagname)) == 0) 1313 error = EBUSY; 1314 if (newrule->match_tagname[0]) 1315 if ((newrule->match_tag = pf_tagname2tag( 1316 newrule->match_tagname)) == 0) 1317 error = EBUSY; 1318 1319 if (newrule->rt && !newrule->direction) 1320 error = EINVAL; 1321 if (pfi_dynaddr_setup(&newrule->src.addr, newrule->af)) 1322 error = EINVAL; 1323 if (pfi_dynaddr_setup(&newrule->dst.addr, newrule->af)) 1324 error = EINVAL; 1325 if (pf_tbladdr_setup(ruleset, &newrule->src.addr)) 1326 error = EINVAL; 1327 if (pf_tbladdr_setup(ruleset, &newrule->dst.addr)) 1328 error = EINVAL; 1329 1330 pf_mv_pool(&pf_pabuf, &newrule->rpool.list); 1331 if (((((newrule->action == PF_NAT) || 1332 (newrule->action == PF_RDR) || 1333 (newrule->action == PF_BINAT) || 1334 (newrule->rt > PF_FASTROUTE)) && 1335 !newrule->anchorname[0])) && 1336 (TAILQ_FIRST(&newrule->rpool.list) == NULL)) 1337 error = EINVAL; 1338 1339 if (error) { 1340 pf_rm_rule(NULL, newrule); 1341 break; 1342 } 1343 newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list); 1344 newrule->evaluations = newrule->packets = 0; 1345 newrule->bytes = 0; 1346 } 1347 pf_empty_pool(&pf_pabuf); 1348 1349 crit_enter(); 1350 1351 if (pcr->action == PF_CHANGE_ADD_HEAD) 1352 oldrule = TAILQ_FIRST( 1353 ruleset->rules[rs_num].active.ptr); 1354 else if (pcr->action == PF_CHANGE_ADD_TAIL) 1355 oldrule = TAILQ_LAST( 1356 ruleset->rules[rs_num].active.ptr, pf_rulequeue); 1357 else { 1358 oldrule = TAILQ_FIRST( 1359 ruleset->rules[rs_num].active.ptr); 1360 while ((oldrule != NULL) && (oldrule->nr != pcr->nr)) 1361 oldrule = TAILQ_NEXT(oldrule, entries); 1362 if (oldrule == NULL) { 1363 pf_rm_rule(NULL, newrule); 1364 error = EINVAL; 1365 crit_exit(); 1366 break; 1367 } 1368 } 1369 1370 if (pcr->action == PF_CHANGE_REMOVE) 1371 pf_rm_rule(ruleset->rules[rs_num].active.ptr, oldrule); 1372 else { 1373 if (oldrule == NULL) 1374 TAILQ_INSERT_TAIL( 1375 ruleset->rules[rs_num].active.ptr, 1376 newrule, entries); 1377 else if (pcr->action == PF_CHANGE_ADD_HEAD || 1378 pcr->action == PF_CHANGE_ADD_BEFORE) 1379 TAILQ_INSERT_BEFORE(oldrule, newrule, entries); 1380 else 1381 TAILQ_INSERT_AFTER( 1382 ruleset->rules[rs_num].active.ptr, 1383 oldrule, newrule, entries); 1384 } 1385 1386 nr = 0; 1387 TAILQ_FOREACH(oldrule, 1388 ruleset->rules[rs_num].active.ptr, entries) 1389 oldrule->nr = nr++; 1390 1391 pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr); 1392 pf_remove_if_empty_ruleset(ruleset); 1393 pf_update_anchor_rules(); 1394 1395 ruleset->rules[rs_num].active.ticket++; 1396 crit_exit(); 1397 break; 1398 } 1399 1400 case DIOCCLRSTATES: { 1401 struct pf_state *state; 1402 struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr; 1403 int killed = 0; 1404 1405 crit_enter(); 1406 RB_FOREACH(state, pf_state_tree_id, &tree_id) { 1407 if (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname, 1408 state->u.s.kif->pfik_name)) { 1409 state->timeout = PFTM_PURGE; 1410 #if NPFSYNC 1411 /* don't send out individual delete messages */ 1412 state->sync_flags = PFSTATE_NOSYNC; 1413 #endif 1414 killed++; 1415 } 1416 } 1417 pf_purge_expired_states(); 1418 pf_status.states = 0; 1419 psk->psk_af = killed; 1420 #if NPFSYNC 1421 pfsync_clear_states(pf_status.hostid, psk->psk_ifname); 1422 #endif 1423 crit_exit(); 1424 break; 1425 } 1426 1427 case DIOCKILLSTATES: { 1428 struct pf_state *state; 1429 struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr; 1430 int killed = 0; 1431 1432 crit_enter(); 1433 RB_FOREACH(state, pf_state_tree_id, &tree_id) { 1434 if ((!psk->psk_af || state->af == psk->psk_af) 1435 && (!psk->psk_proto || psk->psk_proto == 1436 state->proto) && 1437 PF_MATCHA(psk->psk_src.not, 1438 &psk->psk_src.addr.v.a.addr, 1439 &psk->psk_src.addr.v.a.mask, 1440 &state->lan.addr, state->af) && 1441 PF_MATCHA(psk->psk_dst.not, 1442 &psk->psk_dst.addr.v.a.addr, 1443 &psk->psk_dst.addr.v.a.mask, 1444 &state->ext.addr, state->af) && 1445 (psk->psk_src.port_op == 0 || 1446 pf_match_port(psk->psk_src.port_op, 1447 psk->psk_src.port[0], psk->psk_src.port[1], 1448 state->lan.port)) && 1449 (psk->psk_dst.port_op == 0 || 1450 pf_match_port(psk->psk_dst.port_op, 1451 psk->psk_dst.port[0], psk->psk_dst.port[1], 1452 state->ext.port)) && 1453 (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname, 1454 state->u.s.kif->pfik_name))) { 1455 state->timeout = PFTM_PURGE; 1456 killed++; 1457 } 1458 } 1459 pf_purge_expired_states(); 1460 crit_exit(); 1461 psk->psk_af = killed; 1462 break; 1463 } 1464 1465 case DIOCADDSTATE: { 1466 struct pfioc_state *ps = (struct pfioc_state *)addr; 1467 struct pf_state *state; 1468 struct pfi_kif *kif; 1469 1470 if (ps->state.timeout >= PFTM_MAX && 1471 ps->state.timeout != PFTM_UNTIL_PACKET) { 1472 error = EINVAL; 1473 break; 1474 } 1475 state = pool_get(&pf_state_pl, PR_NOWAIT); 1476 if (state == NULL) { 1477 error = ENOMEM; 1478 break; 1479 } 1480 crit_enter(); 1481 kif = pfi_lookup_create(ps->state.u.ifname); 1482 if (kif == NULL) { 1483 pool_put(&pf_state_pl, state); 1484 error = ENOENT; 1485 crit_exit(); 1486 break; 1487 } 1488 bcopy(&ps->state, state, sizeof(struct pf_state)); 1489 bzero(&state->u, sizeof(state->u)); 1490 state->rule.ptr = &pf_default_rule; 1491 state->nat_rule.ptr = NULL; 1492 state->anchor.ptr = NULL; 1493 state->rt_kif = NULL; 1494 state->creation = time_second; 1495 state->pfsync_time = 0; 1496 state->packets[0] = state->packets[1] = 0; 1497 state->bytes[0] = state->bytes[1] = 0; 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 unregisteration 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