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