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