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