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