1 /* $OpenBSD: pfctl.c,v 1.337 2016/09/03 21:30:49 jca Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Daniel Hartmeier 5 * Copyright (c) 2002 - 2013 Henning Brauer <henning@openbsd.org> 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 */ 33 34 #include <sys/types.h> 35 #include <sys/ioctl.h> 36 #include <sys/socket.h> 37 #include <sys/stat.h> 38 39 #include <net/if.h> 40 #include <netinet/in.h> 41 #include <net/pfvar.h> 42 #include <arpa/inet.h> 43 #include <net/hfsc.h> 44 #include <sys/sysctl.h> 45 46 #include <err.h> 47 #include <errno.h> 48 #include <fcntl.h> 49 #include <limits.h> 50 #include <netdb.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <unistd.h> 55 56 #include <syslog.h> 57 58 #include "pfctl_parser.h" 59 #include "pfctl.h" 60 61 void usage(void); 62 int pfctl_enable(int, int); 63 int pfctl_disable(int, int); 64 void pfctl_clear_queues(struct pf_qihead *); 65 int pfctl_clear_stats(int, const char *, int); 66 int pfctl_clear_interface_flags(int, int); 67 int pfctl_clear_rules(int, int, char *); 68 int pfctl_clear_src_nodes(int, int); 69 int pfctl_clear_states(int, const char *, int); 70 void pfctl_addrprefix(char *, struct pf_addr *); 71 int pfctl_kill_src_nodes(int, const char *, int); 72 int pfctl_net_kill_states(int, const char *, int); 73 int pfctl_label_kill_states(int, const char *, int); 74 int pfctl_id_kill_states(int, const char *, int); 75 void pfctl_init_options(struct pfctl *); 76 int pfctl_load_options(struct pfctl *); 77 int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); 78 int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); 79 int pfctl_load_debug(struct pfctl *, unsigned int); 80 int pfctl_load_logif(struct pfctl *, char *); 81 int pfctl_load_hostid(struct pfctl *, unsigned int); 82 int pfctl_load_reassembly(struct pfctl *, u_int32_t); 83 void pfctl_print_rule_counters(struct pf_rule *, int); 84 int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int, 85 long); 86 int pfctl_show_src_nodes(int, int); 87 int pfctl_show_states(int, const char *, int, long); 88 int pfctl_show_status(int, int); 89 int pfctl_show_timeouts(int, int); 90 int pfctl_show_limits(int, int); 91 void pfctl_debug(int, u_int32_t, int); 92 int pfctl_show_anchors(int, int, char *); 93 int pfctl_ruleset_trans(struct pfctl *, char *, struct pf_anchor *); 94 u_int pfctl_find_childqs(struct pfctl_qsitem *); 95 void pfctl_load_queue(struct pfctl *, u_int32_t, struct pfctl_qsitem *); 96 int pfctl_load_queues(struct pfctl *); 97 u_int pfctl_leafqueue_check(char *); 98 u_int pfctl_check_qassignments(struct pf_ruleset *); 99 int pfctl_load_ruleset(struct pfctl *, char *, struct pf_ruleset *, int); 100 int pfctl_load_rule(struct pfctl *, char *, struct pf_rule *, int); 101 const char *pfctl_lookup_option(char *, const char **); 102 void pfctl_state_store(int, const char *); 103 void pfctl_state_load(int, const char *); 104 105 struct pf_anchor_global pf_anchors; 106 struct pf_anchor pf_main_anchor; 107 108 const char *clearopt; 109 char *rulesopt; 110 const char *showopt; 111 const char *debugopt; 112 char *anchoropt; 113 const char *optiopt = NULL; 114 char *pf_device = "/dev/pf"; 115 char *ifaceopt; 116 char *tableopt; 117 const char *tblcmdopt; 118 int src_node_killers; 119 char *src_node_kill[2]; 120 int state_killers; 121 char *state_kill[2]; 122 123 int dev = -1; 124 int first_title = 1; 125 int labels = 0; 126 127 #define INDENT(d, o) do { \ 128 if (o) { \ 129 int i; \ 130 for (i=0; i < d; i++) \ 131 printf(" "); \ 132 } \ 133 } while (0) \ 134 135 136 static const struct { 137 const char *name; 138 int index; 139 } pf_limits[] = { 140 { "states", PF_LIMIT_STATES }, 141 { "src-nodes", PF_LIMIT_SRC_NODES }, 142 { "frags", PF_LIMIT_FRAGS }, 143 { "tables", PF_LIMIT_TABLES }, 144 { "table-entries", PF_LIMIT_TABLE_ENTRIES }, 145 { NULL, 0 } 146 }; 147 148 struct pf_hint { 149 const char *name; 150 int timeout; 151 }; 152 static const struct pf_hint pf_hint_normal[] = { 153 { "tcp.first", 2 * 60 }, 154 { "tcp.opening", 30 }, 155 { "tcp.established", 24 * 60 * 60 }, 156 { "tcp.closing", 15 * 60 }, 157 { "tcp.finwait", 45 }, 158 { "tcp.closed", 90 }, 159 { "tcp.tsdiff", 30 }, 160 { NULL, 0 } 161 }; 162 static const struct pf_hint pf_hint_satellite[] = { 163 { "tcp.first", 3 * 60 }, 164 { "tcp.opening", 30 + 5 }, 165 { "tcp.established", 24 * 60 * 60 }, 166 { "tcp.closing", 15 * 60 + 5 }, 167 { "tcp.finwait", 45 + 5 }, 168 { "tcp.closed", 90 + 5 }, 169 { "tcp.tsdiff", 60 }, 170 { NULL, 0 } 171 }; 172 static const struct pf_hint pf_hint_conservative[] = { 173 { "tcp.first", 60 * 60 }, 174 { "tcp.opening", 15 * 60 }, 175 { "tcp.established", 5 * 24 * 60 * 60 }, 176 { "tcp.closing", 60 * 60 }, 177 { "tcp.finwait", 10 * 60 }, 178 { "tcp.closed", 3 * 60 }, 179 { "tcp.tsdiff", 60 }, 180 { NULL, 0 } 181 }; 182 static const struct pf_hint pf_hint_aggressive[] = { 183 { "tcp.first", 30 }, 184 { "tcp.opening", 5 }, 185 { "tcp.established", 5 * 60 * 60 }, 186 { "tcp.closing", 60 }, 187 { "tcp.finwait", 30 }, 188 { "tcp.closed", 30 }, 189 { "tcp.tsdiff", 10 }, 190 { NULL, 0 } 191 }; 192 193 static const struct { 194 const char *name; 195 const struct pf_hint *hint; 196 } pf_hints[] = { 197 { "normal", pf_hint_normal }, 198 { "satellite", pf_hint_satellite }, 199 { "high-latency", pf_hint_satellite }, 200 { "conservative", pf_hint_conservative }, 201 { "aggressive", pf_hint_aggressive }, 202 { NULL, NULL } 203 }; 204 205 static const char *clearopt_list[] = { 206 "rules", "Sources", "states", "info", "Tables", "osfp", "all", NULL 207 }; 208 209 static const char *showopt_list[] = { 210 "queue", "rules", "Anchors", "Sources", "states", "info", 211 "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp", 212 "all", NULL 213 }; 214 215 static const char *tblcmdopt_list[] = { 216 "kill", "flush", "add", "delete", "replace", "show", 217 "test", "zero", "expire", NULL 218 }; 219 220 static const char *debugopt_list[] = { 221 "debug", "info", "notice", "warning", 222 "error", "crit", "alert", "emerg", 223 NULL 224 }; 225 226 static const char *optiopt_list[] = { 227 "none", "basic", "profile", NULL 228 }; 229 230 struct pf_qihead qspecs = TAILQ_HEAD_INITIALIZER(qspecs); 231 struct pf_qihead rootqs = TAILQ_HEAD_INITIALIZER(rootqs); 232 233 234 void 235 usage(void) 236 { 237 extern char *__progname; 238 239 fprintf(stderr, "usage: %s [-deghnPqrvz] ", __progname); 240 fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n"); 241 fprintf(stderr, "\t[-f file] [-i interface] [-K host | network]\n"); 242 fprintf(stderr, "\t[-k host | network | label | id] "); 243 fprintf(stderr, "[-L statefile] [-o level] [-p device]\n"); 244 fprintf(stderr, "\t[-S statefile] [-s modifier [-R id]] "); 245 fprintf(stderr, "[-t table -T command [address ...]]\n"); 246 fprintf(stderr, "\t[-x level]\n"); 247 exit(1); 248 } 249 250 int 251 pfctl_enable(int dev, int opts) 252 { 253 if (ioctl(dev, DIOCSTART)) { 254 if (errno == EEXIST) 255 errx(1, "pf already enabled"); 256 else 257 err(1, "DIOCSTART"); 258 } 259 if ((opts & PF_OPT_QUIET) == 0) 260 fprintf(stderr, "pf enabled\n"); 261 262 return (0); 263 } 264 265 int 266 pfctl_disable(int dev, int opts) 267 { 268 if (ioctl(dev, DIOCSTOP)) { 269 if (errno == ENOENT) 270 errx(1, "pf not enabled"); 271 else 272 err(1, "DIOCSTOP"); 273 } 274 if ((opts & PF_OPT_QUIET) == 0) 275 fprintf(stderr, "pf disabled\n"); 276 277 return (0); 278 } 279 280 int 281 pfctl_clear_stats(int dev, const char *iface, int opts) 282 { 283 struct pfioc_iface pi; 284 285 memset(&pi, 0, sizeof(pi)); 286 if (iface != NULL && strlcpy(pi.pfiio_name, iface, 287 sizeof(pi.pfiio_name)) >= sizeof(pi.pfiio_name)) 288 errx(1, "invalid interface: %s", iface); 289 290 if (ioctl(dev, DIOCCLRSTATUS, &pi)) 291 err(1, "DIOCCLRSTATUS"); 292 if ((opts & PF_OPT_QUIET) == 0) { 293 fprintf(stderr, "pf: statistics cleared"); 294 if (iface != NULL) 295 fprintf(stderr, " for interface %s", iface); 296 fprintf(stderr, "\n"); 297 } 298 return (0); 299 } 300 301 int 302 pfctl_clear_interface_flags(int dev, int opts) 303 { 304 struct pfioc_iface pi; 305 306 if ((opts & PF_OPT_NOACTION) == 0) { 307 bzero(&pi, sizeof(pi)); 308 pi.pfiio_flags = PFI_IFLAG_SKIP; 309 310 if (ioctl(dev, DIOCCLRIFFLAG, &pi)) 311 err(1, "DIOCCLRIFFLAG"); 312 if ((opts & PF_OPT_QUIET) == 0) 313 fprintf(stderr, "pf: interface flags reset\n"); 314 } 315 return (0); 316 } 317 318 int 319 pfctl_clear_rules(int dev, int opts, char *anchorname) 320 { 321 struct pfr_buffer t; 322 323 memset(&t, 0, sizeof(t)); 324 t.pfrb_type = PFRB_TRANS; 325 if (pfctl_add_trans(&t, PF_TRANS_RULESET, anchorname) || 326 pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 327 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 328 err(1, "pfctl_clear_rules"); 329 if ((opts & PF_OPT_QUIET) == 0) 330 fprintf(stderr, "rules cleared\n"); 331 return (0); 332 } 333 334 int 335 pfctl_clear_src_nodes(int dev, int opts) 336 { 337 if (ioctl(dev, DIOCCLRSRCNODES)) 338 err(1, "DIOCCLRSRCNODES"); 339 if ((opts & PF_OPT_QUIET) == 0) 340 fprintf(stderr, "source tracking entries cleared\n"); 341 return (0); 342 } 343 344 int 345 pfctl_clear_states(int dev, const char *iface, int opts) 346 { 347 struct pfioc_state_kill psk; 348 349 memset(&psk, 0, sizeof(psk)); 350 if (iface != NULL && strlcpy(psk.psk_ifname, iface, 351 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 352 errx(1, "invalid interface: %s", iface); 353 354 if (ioctl(dev, DIOCCLRSTATES, &psk)) 355 err(1, "DIOCCLRSTATES"); 356 if ((opts & PF_OPT_QUIET) == 0) 357 fprintf(stderr, "%d states cleared\n", psk.psk_killed); 358 return (0); 359 } 360 361 void 362 pfctl_addrprefix(char *addr, struct pf_addr *mask) 363 { 364 char *p; 365 const char *errstr; 366 int prefix, ret_ga, q, r; 367 struct addrinfo hints, *res; 368 369 if ((p = strchr(addr, '/')) == NULL) 370 return; 371 372 *p++ = '\0'; 373 prefix = strtonum(p, 0, 128, &errstr); 374 if (errstr) 375 errx(1, "prefix is %s: %s", errstr, p); 376 377 bzero(&hints, sizeof(hints)); 378 /* prefix only with numeric addresses */ 379 hints.ai_flags |= AI_NUMERICHOST; 380 381 if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) { 382 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 383 /* NOTREACHED */ 384 } 385 386 if (res->ai_family == AF_INET && prefix > 32) 387 errx(1, "prefix too long for AF_INET"); 388 else if (res->ai_family == AF_INET6 && prefix > 128) 389 errx(1, "prefix too long for AF_INET6"); 390 391 q = prefix >> 3; 392 r = prefix & 7; 393 switch (res->ai_family) { 394 case AF_INET: 395 bzero(&mask->v4, sizeof(mask->v4)); 396 mask->v4.s_addr = htonl((u_int32_t) 397 (0xffffffffffULL << (32 - prefix))); 398 break; 399 case AF_INET6: 400 bzero(&mask->v6, sizeof(mask->v6)); 401 if (q > 0) 402 memset((void *)&mask->v6, 0xff, q); 403 if (r > 0) 404 *((u_char *)&mask->v6 + q) = 405 (0xff00 >> r) & 0xff; 406 break; 407 } 408 freeaddrinfo(res); 409 } 410 411 int 412 pfctl_kill_src_nodes(int dev, const char *iface, int opts) 413 { 414 struct pfioc_src_node_kill psnk; 415 struct addrinfo *res[2], *resp[2]; 416 struct sockaddr last_src, last_dst; 417 int killed, sources, dests; 418 int ret_ga; 419 420 killed = sources = dests = 0; 421 422 memset(&psnk, 0, sizeof(psnk)); 423 memset(&psnk.psnk_src.addr.v.a.mask, 0xff, 424 sizeof(psnk.psnk_src.addr.v.a.mask)); 425 memset(&last_src, 0xff, sizeof(last_src)); 426 memset(&last_dst, 0xff, sizeof(last_dst)); 427 428 pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask); 429 430 if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) { 431 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 432 /* NOTREACHED */ 433 } 434 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 435 if (resp[0]->ai_addr == NULL) 436 continue; 437 /* We get lots of duplicates. Catch the easy ones */ 438 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 439 continue; 440 last_src = *(struct sockaddr *)resp[0]->ai_addr; 441 442 psnk.psnk_af = resp[0]->ai_family; 443 sources++; 444 445 if (psnk.psnk_af == AF_INET) 446 psnk.psnk_src.addr.v.a.addr.v4 = 447 ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 448 else if (psnk.psnk_af == AF_INET6) 449 psnk.psnk_src.addr.v.a.addr.v6 = 450 ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 451 sin6_addr; 452 else 453 errx(1, "Unknown address family %d", psnk.psnk_af); 454 455 if (src_node_killers > 1) { 456 dests = 0; 457 memset(&psnk.psnk_dst.addr.v.a.mask, 0xff, 458 sizeof(psnk.psnk_dst.addr.v.a.mask)); 459 memset(&last_dst, 0xff, sizeof(last_dst)); 460 pfctl_addrprefix(src_node_kill[1], 461 &psnk.psnk_dst.addr.v.a.mask); 462 if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL, 463 &res[1]))) { 464 errx(1, "getaddrinfo: %s", 465 gai_strerror(ret_ga)); 466 /* NOTREACHED */ 467 } 468 for (resp[1] = res[1]; resp[1]; 469 resp[1] = resp[1]->ai_next) { 470 if (resp[1]->ai_addr == NULL) 471 continue; 472 if (psnk.psnk_af != resp[1]->ai_family) 473 continue; 474 475 if (memcmp(&last_dst, resp[1]->ai_addr, 476 sizeof(last_dst)) == 0) 477 continue; 478 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 479 480 dests++; 481 482 if (psnk.psnk_af == AF_INET) 483 psnk.psnk_dst.addr.v.a.addr.v4 = 484 ((struct sockaddr_in *)resp[1]-> 485 ai_addr)->sin_addr; 486 else if (psnk.psnk_af == AF_INET6) 487 psnk.psnk_dst.addr.v.a.addr.v6 = 488 ((struct sockaddr_in6 *)resp[1]-> 489 ai_addr)->sin6_addr; 490 else 491 errx(1, "Unknown address family %d", 492 psnk.psnk_af); 493 494 if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 495 err(1, "DIOCKILLSRCNODES"); 496 killed += psnk.psnk_killed; 497 } 498 freeaddrinfo(res[1]); 499 } else { 500 if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 501 err(1, "DIOCKILLSRCNODES"); 502 killed += psnk.psnk_killed; 503 } 504 } 505 506 freeaddrinfo(res[0]); 507 508 if ((opts & PF_OPT_QUIET) == 0) 509 fprintf(stderr, "killed %d src nodes from %d sources and %d " 510 "destinations\n", killed, sources, dests); 511 return (0); 512 } 513 514 int 515 pfctl_net_kill_states(int dev, const char *iface, int opts) 516 { 517 struct pfioc_state_kill psk; 518 struct addrinfo *res[2], *resp[2]; 519 struct sockaddr last_src, last_dst; 520 int killed, sources, dests; 521 int ret_ga; 522 523 killed = sources = dests = 0; 524 525 memset(&psk, 0, sizeof(psk)); 526 memset(&psk.psk_src.addr.v.a.mask, 0xff, 527 sizeof(psk.psk_src.addr.v.a.mask)); 528 memset(&last_src, 0xff, sizeof(last_src)); 529 memset(&last_dst, 0xff, sizeof(last_dst)); 530 if (iface != NULL && strlcpy(psk.psk_ifname, iface, 531 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 532 errx(1, "invalid interface: %s", iface); 533 534 pfctl_addrprefix(state_kill[0], &psk.psk_src.addr.v.a.mask); 535 536 if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) { 537 errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 538 /* NOTREACHED */ 539 } 540 for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 541 if (resp[0]->ai_addr == NULL) 542 continue; 543 /* We get lots of duplicates. Catch the easy ones */ 544 if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 545 continue; 546 last_src = *(struct sockaddr *)resp[0]->ai_addr; 547 548 psk.psk_af = resp[0]->ai_family; 549 sources++; 550 551 if (psk.psk_af == AF_INET) 552 psk.psk_src.addr.v.a.addr.v4 = 553 ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 554 else if (psk.psk_af == AF_INET6) 555 psk.psk_src.addr.v.a.addr.v6 = 556 ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 557 sin6_addr; 558 else 559 errx(1, "Unknown address family %d", psk.psk_af); 560 561 if (state_killers > 1) { 562 dests = 0; 563 memset(&psk.psk_dst.addr.v.a.mask, 0xff, 564 sizeof(psk.psk_dst.addr.v.a.mask)); 565 memset(&last_dst, 0xff, sizeof(last_dst)); 566 pfctl_addrprefix(state_kill[1], 567 &psk.psk_dst.addr.v.a.mask); 568 if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, 569 &res[1]))) { 570 errx(1, "getaddrinfo: %s", 571 gai_strerror(ret_ga)); 572 /* NOTREACHED */ 573 } 574 for (resp[1] = res[1]; resp[1]; 575 resp[1] = resp[1]->ai_next) { 576 if (resp[1]->ai_addr == NULL) 577 continue; 578 if (psk.psk_af != resp[1]->ai_family) 579 continue; 580 581 if (memcmp(&last_dst, resp[1]->ai_addr, 582 sizeof(last_dst)) == 0) 583 continue; 584 last_dst = *(struct sockaddr *)resp[1]->ai_addr; 585 586 dests++; 587 588 if (psk.psk_af == AF_INET) 589 psk.psk_dst.addr.v.a.addr.v4 = 590 ((struct sockaddr_in *)resp[1]-> 591 ai_addr)->sin_addr; 592 else if (psk.psk_af == AF_INET6) 593 psk.psk_dst.addr.v.a.addr.v6 = 594 ((struct sockaddr_in6 *)resp[1]-> 595 ai_addr)->sin6_addr; 596 else 597 errx(1, "Unknown address family %d", 598 psk.psk_af); 599 600 if (ioctl(dev, DIOCKILLSTATES, &psk)) 601 err(1, "DIOCKILLSTATES"); 602 killed += psk.psk_killed; 603 } 604 freeaddrinfo(res[1]); 605 } else { 606 if (ioctl(dev, DIOCKILLSTATES, &psk)) 607 err(1, "DIOCKILLSTATES"); 608 killed += psk.psk_killed; 609 } 610 } 611 612 freeaddrinfo(res[0]); 613 614 if ((opts & PF_OPT_QUIET) == 0) 615 fprintf(stderr, "killed %d states from %d sources and %d " 616 "destinations\n", killed, sources, dests); 617 return (0); 618 } 619 620 int 621 pfctl_label_kill_states(int dev, const char *iface, int opts) 622 { 623 struct pfioc_state_kill psk; 624 625 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 626 warnx("no label specified"); 627 usage(); 628 } 629 memset(&psk, 0, sizeof(psk)); 630 if (iface != NULL && strlcpy(psk.psk_ifname, iface, 631 sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) 632 errx(1, "invalid interface: %s", iface); 633 634 if (strlcpy(psk.psk_label, state_kill[1], sizeof(psk.psk_label)) >= 635 sizeof(psk.psk_label)) 636 errx(1, "label too long: %s", state_kill[1]); 637 638 if (ioctl(dev, DIOCKILLSTATES, &psk)) 639 err(1, "DIOCKILLSTATES"); 640 641 if ((opts & PF_OPT_QUIET) == 0) 642 fprintf(stderr, "killed %d states\n", psk.psk_killed); 643 644 return (0); 645 } 646 647 int 648 pfctl_id_kill_states(int dev, const char *iface, int opts) 649 { 650 struct pfioc_state_kill psk; 651 652 if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 653 warnx("no id specified"); 654 usage(); 655 } 656 657 memset(&psk, 0, sizeof(psk)); 658 if ((sscanf(state_kill[1], "%llx/%x", 659 &psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2) 660 HTONL(psk.psk_pfcmp.creatorid); 661 else if ((sscanf(state_kill[1], "%llx", &psk.psk_pfcmp.id)) == 1) { 662 psk.psk_pfcmp.creatorid = 0; 663 } else { 664 warnx("wrong id format specified"); 665 usage(); 666 } 667 if (psk.psk_pfcmp.id == 0) { 668 warnx("cannot kill id 0"); 669 usage(); 670 } 671 672 psk.psk_pfcmp.id = htobe64(psk.psk_pfcmp.id); 673 if (ioctl(dev, DIOCKILLSTATES, &psk)) 674 err(1, "DIOCKILLSTATES"); 675 676 if ((opts & PF_OPT_QUIET) == 0) 677 fprintf(stderr, "killed %d states\n", psk.psk_killed); 678 679 return (0); 680 } 681 682 void 683 pfctl_print_rule_counters(struct pf_rule *rule, int opts) 684 { 685 if (opts & PF_OPT_DEBUG) { 686 const char *t[PF_SKIP_COUNT] = { "i", "d", "r", "f", 687 "p", "sa", "da", "sp", "dp" }; 688 int i; 689 690 printf(" [ Skip steps: "); 691 for (i = 0; i < PF_SKIP_COUNT; ++i) { 692 if (rule->skip[i].nr == rule->nr + 1) 693 continue; 694 printf("%s=", t[i]); 695 if (rule->skip[i].nr == -1) 696 printf("end "); 697 else 698 printf("%u ", rule->skip[i].nr); 699 } 700 printf("]\n"); 701 702 printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 703 rule->qname, rule->qid, rule->pqname, rule->pqid); 704 } 705 if (opts & PF_OPT_VERBOSE) { 706 printf(" [ Evaluations: %-8llu Packets: %-8llu " 707 "Bytes: %-10llu States: %-6u]\n", 708 (unsigned long long)rule->evaluations, 709 (unsigned long long)(rule->packets[0] + 710 rule->packets[1]), 711 (unsigned long long)(rule->bytes[0] + 712 rule->bytes[1]), rule->states_cur); 713 if (!(opts & PF_OPT_DEBUG)) 714 printf(" [ Inserted: uid %lu pid %lu " 715 "State Creations: %-6u]\n", 716 (unsigned long)rule->cuid, (unsigned long)rule->cpid, 717 rule->states_tot); 718 } 719 } 720 721 void 722 pfctl_print_title(char *title) 723 { 724 if (!first_title) 725 printf("\n"); 726 first_title = 0; 727 printf("%s\n", title); 728 } 729 730 int 731 pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, 732 char *anchorname, int depth, int wildcard, long shownr) 733 { 734 struct pfioc_rule pr; 735 u_int32_t nr, mnr, header = 0; 736 int len = strlen(path), ret = 0; 737 char *npath, *p; 738 739 /* 740 * Truncate a trailing / and * on an anchorname before searching for 741 * the ruleset, this is syntactic sugar that doesn't actually make it 742 * to the kernel. 743 */ 744 if ((p = strrchr(anchorname, '/')) != NULL && 745 p[1] == '*' && p[2] == '\0') { 746 p[0] = '\0'; 747 } 748 749 memset(&pr, 0, sizeof(pr)); 750 if (anchorname[0] == '/') { 751 if ((npath = calloc(1, PATH_MAX)) == NULL) 752 errx(1, "pfctl_rules: calloc"); 753 strlcpy(npath, anchorname, PATH_MAX); 754 } else { 755 if (path[0]) 756 snprintf(&path[len], PATH_MAX - len, "/%s", anchorname); 757 else 758 snprintf(&path[len], PATH_MAX - len, "%s", anchorname); 759 npath = path; 760 } 761 762 memcpy(pr.anchor, npath, sizeof(pr.anchor)); 763 if (opts & PF_OPT_SHOWALL) { 764 pr.rule.action = PF_PASS; 765 if (ioctl(dev, DIOCGETRULES, &pr)) { 766 warn("DIOCGETRULES"); 767 ret = -1; 768 goto error; 769 } 770 header++; 771 if (format == PFCTL_SHOW_RULES && (pr.nr > 0 || header)) 772 pfctl_print_title("FILTER RULES:"); 773 else if (format == PFCTL_SHOW_LABELS && labels) 774 pfctl_print_title("LABEL COUNTERS:"); 775 } 776 if (opts & PF_OPT_CLRRULECTRS) 777 pr.action = PF_GET_CLR_CNTR; 778 779 pr.rule.action = PF_PASS; 780 if (ioctl(dev, DIOCGETRULES, &pr)) { 781 warn("DIOCGETRULES"); 782 ret = -1; 783 goto error; 784 } 785 786 if (shownr < 0) { 787 mnr = pr.nr; 788 nr = 0; 789 } else if (shownr < pr.nr) { 790 nr = shownr; 791 mnr = shownr + 1; 792 } else { 793 warnx("rule %ld not found", shownr); 794 ret = -1; 795 goto error; 796 } 797 for (; nr < mnr; ++nr) { 798 pr.nr = nr; 799 if (ioctl(dev, DIOCGETRULE, &pr)) { 800 warn("DIOCGETRULE"); 801 ret = -1; 802 goto error; 803 } 804 805 /* anchor is the same for all rules in it */ 806 if (pr.rule.anchor_wildcard == 0) 807 wildcard = 0; 808 809 switch (format) { 810 case PFCTL_SHOW_LABELS: 811 if (pr.rule.label[0]) { 812 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 813 printf("%s %llu %llu %llu %llu" 814 " %llu %llu %llu %llu\n", 815 pr.rule.label, 816 (unsigned long long)pr.rule.evaluations, 817 (unsigned long long)(pr.rule.packets[0] + 818 pr.rule.packets[1]), 819 (unsigned long long)(pr.rule.bytes[0] + 820 pr.rule.bytes[1]), 821 (unsigned long long)pr.rule.packets[0], 822 (unsigned long long)pr.rule.bytes[0], 823 (unsigned long long)pr.rule.packets[1], 824 (unsigned long long)pr.rule.bytes[1], 825 (unsigned long long)pr.rule.states_tot); 826 } 827 break; 828 case PFCTL_SHOW_RULES: 829 if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) 830 labels = 1; 831 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 832 print_rule(&pr.rule, pr.anchor_call, opts); 833 834 /* 835 * If this is an 'unnamed' brace notation anchor OR 836 * the user has explicitly requested recursion, 837 * print it recursively. 838 */ 839 if (pr.anchor_call[0] && 840 (((p = strrchr(pr.anchor_call, '/')) ? 841 p[1] == '_' : pr.anchor_call[0] == '_') || 842 opts & PF_OPT_RECURSE)) { 843 printf(" {\n"); 844 pfctl_print_rule_counters(&pr.rule, opts); 845 pfctl_show_rules(dev, npath, opts, format, 846 pr.anchor_call, depth + 1, 847 pr.rule.anchor_wildcard, -1); 848 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 849 printf("}\n"); 850 } else { 851 printf("\n"); 852 pfctl_print_rule_counters(&pr.rule, opts); 853 } 854 break; 855 case PFCTL_SHOW_NOTHING: 856 break; 857 } 858 } 859 860 /* 861 * If this anchor was called with a wildcard path, go through 862 * the rulesets in the anchor rather than the rules. 863 */ 864 if (wildcard && (opts & PF_OPT_RECURSE)) { 865 struct pfioc_ruleset prs; 866 u_int32_t mnr, nr; 867 868 memset(&prs, 0, sizeof(prs)); 869 memcpy(prs.path, npath, sizeof(prs.path)); 870 if (ioctl(dev, DIOCGETRULESETS, &prs)) { 871 if (errno == EINVAL) 872 fprintf(stderr, "Anchor '%s' " 873 "not found.\n", anchorname); 874 else 875 err(1, "DIOCGETRULESETS"); 876 } 877 mnr = prs.nr; 878 879 for (nr = 0; nr < mnr; ++nr) { 880 prs.nr = nr; 881 if (ioctl(dev, DIOCGETRULESET, &prs)) 882 err(1, "DIOCGETRULESET"); 883 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 884 printf("anchor \"%s\" all {\n", prs.name); 885 pfctl_show_rules(dev, npath, opts, 886 format, prs.name, depth + 1, 0, shownr); 887 INDENT(depth, !(opts & PF_OPT_VERBOSE)); 888 printf("}\n"); 889 } 890 path[len] = '\0'; 891 return (0); 892 } 893 894 error: 895 if (path != npath) 896 free(npath); 897 path[len] = '\0'; 898 return (ret); 899 } 900 901 int 902 pfctl_show_src_nodes(int dev, int opts) 903 { 904 struct pfioc_src_nodes psn; 905 struct pf_src_node *p; 906 char *inbuf = NULL, *newinbuf = NULL; 907 unsigned int len = 0; 908 int i; 909 910 memset(&psn, 0, sizeof(psn)); 911 for (;;) { 912 psn.psn_len = len; 913 if (len) { 914 newinbuf = realloc(inbuf, len); 915 if (newinbuf == NULL) 916 err(1, "realloc"); 917 psn.psn_buf = inbuf = newinbuf; 918 } 919 if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) { 920 warn("DIOCGETSRCNODES"); 921 free(inbuf); 922 return (-1); 923 } 924 if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len) 925 break; 926 if (len == 0 && psn.psn_len == 0) 927 goto done; 928 if (len == 0 && psn.psn_len != 0) 929 len = psn.psn_len; 930 if (psn.psn_len == 0) 931 goto done; /* no src_nodes */ 932 len *= 2; 933 } 934 p = psn.psn_src_nodes; 935 if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL)) 936 pfctl_print_title("SOURCE TRACKING NODES:"); 937 for (i = 0; i < psn.psn_len; i += sizeof(*p)) { 938 print_src_node(p, opts); 939 p++; 940 } 941 done: 942 free(inbuf); 943 return (0); 944 } 945 946 int 947 pfctl_show_states(int dev, const char *iface, int opts, long shownr) 948 { 949 struct pfioc_states ps; 950 struct pfsync_state *p; 951 char *inbuf = NULL, *newinbuf = NULL; 952 unsigned int len = 0; 953 int i, dotitle = (opts & PF_OPT_SHOWALL); 954 955 memset(&ps, 0, sizeof(ps)); 956 for (;;) { 957 ps.ps_len = len; 958 if (len) { 959 newinbuf = realloc(inbuf, len); 960 if (newinbuf == NULL) 961 err(1, "realloc"); 962 ps.ps_buf = inbuf = newinbuf; 963 } 964 if (ioctl(dev, DIOCGETSTATES, &ps) < 0) { 965 warn("DIOCGETSTATES"); 966 free(inbuf); 967 return (-1); 968 } 969 if (ps.ps_len + sizeof(struct pfioc_states) < len) 970 break; 971 if (len == 0 && ps.ps_len == 0) 972 goto done; 973 if (len == 0 && ps.ps_len != 0) 974 len = ps.ps_len; 975 if (ps.ps_len == 0) 976 goto done; /* no states */ 977 len *= 2; 978 } 979 p = ps.ps_states; 980 for (i = 0; i < ps.ps_len; i += sizeof(*p), p++) { 981 if (iface != NULL && strcmp(p->ifname, iface)) 982 continue; 983 if (dotitle) { 984 pfctl_print_title("STATES:"); 985 dotitle = 0; 986 } 987 if (shownr < 0 || ntohl(p->rule) == shownr) 988 print_state(p, opts); 989 } 990 done: 991 free(inbuf); 992 return (0); 993 } 994 995 int 996 pfctl_show_status(int dev, int opts) 997 { 998 struct pf_status status; 999 1000 if (ioctl(dev, DIOCGETSTATUS, &status)) { 1001 warn("DIOCGETSTATUS"); 1002 return (-1); 1003 } 1004 if (opts & PF_OPT_SHOWALL) 1005 pfctl_print_title("INFO:"); 1006 print_status(&status, opts); 1007 return (0); 1008 } 1009 1010 int 1011 pfctl_show_timeouts(int dev, int opts) 1012 { 1013 struct pfioc_tm pt; 1014 int i; 1015 1016 if (opts & PF_OPT_SHOWALL) 1017 pfctl_print_title("TIMEOUTS:"); 1018 memset(&pt, 0, sizeof(pt)); 1019 for (i = 0; pf_timeouts[i].name; i++) { 1020 pt.timeout = pf_timeouts[i].timeout; 1021 if (ioctl(dev, DIOCGETTIMEOUT, &pt)) 1022 err(1, "DIOCGETTIMEOUT"); 1023 printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); 1024 if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 1025 pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 1026 printf(" states"); 1027 else 1028 printf("s"); 1029 printf("\n"); 1030 } 1031 return (0); 1032 1033 } 1034 1035 int 1036 pfctl_show_limits(int dev, int opts) 1037 { 1038 struct pfioc_limit pl; 1039 int i; 1040 1041 if (opts & PF_OPT_SHOWALL) 1042 pfctl_print_title("LIMITS:"); 1043 memset(&pl, 0, sizeof(pl)); 1044 for (i = 0; pf_limits[i].name; i++) { 1045 pl.index = pf_limits[i].index; 1046 if (ioctl(dev, DIOCGETLIMIT, &pl)) 1047 err(1, "DIOCGETLIMIT"); 1048 printf("%-13s ", pf_limits[i].name); 1049 if (pl.limit == UINT_MAX) 1050 printf("unlimited\n"); 1051 else 1052 printf("hard limit %8u\n", pl.limit); 1053 } 1054 return (0); 1055 } 1056 1057 /* callbacks for rule/nat/rdr/addr */ 1058 int 1059 pfctl_add_rule(struct pfctl *pf, struct pf_rule *r, const char *anchor_call) 1060 { 1061 struct pf_rule *rule; 1062 struct pf_ruleset *rs; 1063 char *p; 1064 1065 rs = &pf->anchor->ruleset; 1066 if (anchor_call[0] && r->anchor == NULL) { 1067 /* 1068 * Don't make non-brace anchors part of the main anchor pool. 1069 */ 1070 if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 1071 err(1, "pfctl_add_rule: calloc"); 1072 1073 pf_init_ruleset(&r->anchor->ruleset); 1074 r->anchor->ruleset.anchor = r->anchor; 1075 if (strlcpy(r->anchor->path, anchor_call, 1076 sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 1077 errx(1, "pfctl_add_rule: strlcpy"); 1078 if ((p = strrchr(anchor_call, '/')) != NULL) { 1079 if (strlen(p) == 1) 1080 errx(1, "pfctl_add_rule: bad anchor name %s", 1081 anchor_call); 1082 } else 1083 p = (char *)anchor_call; 1084 if (strlcpy(r->anchor->name, p, 1085 sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 1086 errx(1, "pfctl_add_rule: strlcpy"); 1087 } 1088 1089 if ((rule = calloc(1, sizeof(*rule))) == NULL) 1090 err(1, "calloc"); 1091 bcopy(r, rule, sizeof(*rule)); 1092 1093 TAILQ_INSERT_TAIL(rs->rules.active.ptr, rule, entries); 1094 return (0); 1095 } 1096 1097 int 1098 pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pf_anchor *a) 1099 { 1100 int osize = pf->trans->pfrb_size; 1101 1102 if (pfctl_add_trans(pf->trans, PF_TRANS_RULESET, path)) 1103 return (3); 1104 if (pfctl_add_trans(pf->trans, PF_TRANS_TABLE, path)) 1105 return (4); 1106 if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1107 return (5); 1108 1109 return (0); 1110 } 1111 1112 int 1113 pfctl_add_queue(struct pfctl *pf, struct pf_queuespec *q) 1114 { 1115 struct pfctl_qsitem *qi; 1116 1117 if (pf->anchor->name[0]) { 1118 printf("must not have queue definitions in an anchor\n"); 1119 return (1); 1120 } 1121 1122 if (q->parent[0] == '\0') { 1123 TAILQ_FOREACH(qi, &rootqs, entries) { 1124 if (strcmp(q->ifname, qi->qs.ifname)) 1125 continue; 1126 printf("A root queue is already defined on %s\n", 1127 qi->qs.ifname); 1128 return (1); 1129 } 1130 } 1131 1132 if ((qi = calloc(1, sizeof(*qi))) == NULL) 1133 err(1, "calloc"); 1134 bcopy(q, &qi->qs, sizeof(qi->qs)); 1135 TAILQ_INIT(&qi->children); 1136 1137 if (qi->qs.parent[0]) 1138 TAILQ_INSERT_TAIL(&qspecs, qi, entries); 1139 else 1140 TAILQ_INSERT_TAIL(&rootqs, qi, entries); 1141 1142 return (0); 1143 } 1144 1145 struct pfctl_qsitem * 1146 pfctl_find_queue(char *what, struct pf_qihead *where) 1147 { 1148 struct pfctl_qsitem *q; 1149 1150 TAILQ_FOREACH(q, where, entries) 1151 if (strcmp(q->qs.qname, what) == 0) 1152 return (q); 1153 1154 return (NULL); 1155 } 1156 1157 u_int 1158 pfctl_find_childqs(struct pfctl_qsitem *qi) 1159 { 1160 struct pfctl_qsitem *n, *p, *q; 1161 u_int flags = qi->qs.flags; 1162 1163 TAILQ_FOREACH(p, &qspecs, entries) { 1164 if (strcmp(p->qs.parent, qi->qs.qname)) 1165 continue; 1166 if (p->qs.ifname[0] && strcmp(p->qs.ifname, qi->qs.ifname)) 1167 continue; 1168 if (++p->matches > 10000) 1169 errx(1, "pfctl_find_childqs: excessive matches, loop?"); 1170 1171 if ((q = pfctl_find_queue(p->qs.qname, &qi->children)) == NULL) { 1172 /* insert */ 1173 if ((n = calloc(1, sizeof(*n))) == NULL) 1174 err(1, "calloc"); 1175 TAILQ_INIT(&n->children); 1176 bcopy(&p->qs, &n->qs, sizeof(n->qs)); 1177 TAILQ_INSERT_TAIL(&qi->children, n, entries); 1178 } else { 1179 if ((q->qs.ifname[0] && p->qs.ifname[0])) 1180 errx(1, "queue %s on %s respecified", 1181 q->qs.qname, q->qs.ifname); 1182 if (!q->qs.ifname[0] && !p->qs.ifname[0]) 1183 errx(1, "queue %s respecified", 1184 q->qs.qname); 1185 /* ifbound beats floating */ 1186 if (!q->qs.ifname[0]) 1187 bcopy(&p->qs, &q->qs, sizeof(q->qs)); 1188 } 1189 } 1190 1191 TAILQ_FOREACH(p, &qi->children, entries) 1192 flags |= pfctl_find_childqs(p); 1193 1194 if (qi->qs.flags & HFSC_DEFAULTCLASS && !TAILQ_EMPTY(&qi->children)) 1195 errx(1, "default queue %s is not a leaf queue", qi->qs.qname); 1196 1197 return (flags); 1198 } 1199 1200 void 1201 pfctl_load_queue(struct pfctl *pf, u_int32_t ticket, struct pfctl_qsitem *qi) 1202 { 1203 struct pfioc_queue q; 1204 struct pfctl_qsitem *p; 1205 1206 q.ticket = ticket; 1207 bcopy(&qi->qs, &q.queue, sizeof(q.queue)); 1208 if ((pf->opts & PF_OPT_NOACTION) == 0) 1209 if (ioctl(pf->dev, DIOCADDQUEUE, &q)) 1210 err(1, "DIOCADDQUEUE"); 1211 if (pf->opts & PF_OPT_VERBOSE) 1212 print_queuespec(&qi->qs); 1213 1214 TAILQ_FOREACH(p, &qi->children, entries) { 1215 strlcpy(p->qs.ifname, qi->qs.ifname, IFNAMSIZ); 1216 pfctl_load_queue(pf, ticket, p); 1217 } 1218 } 1219 1220 int 1221 pfctl_load_queues(struct pfctl *pf) 1222 { 1223 struct pfctl_qsitem *qi, *tempqi, rqi; 1224 u_int32_t ticket; 1225 1226 TAILQ_FOREACH(qi, &qspecs, entries) { 1227 if (qi->matches == 0) 1228 errx(1, "queue %s: parent %s not found\n", qi->qs.qname, 1229 qi->qs.parent); 1230 if (qi->qs.realtime.m1.percent || qi->qs.realtime.m2.percent || 1231 qi->qs.linkshare.m1.percent || 1232 qi->qs.linkshare.m2.percent || 1233 qi->qs.upperlimit.m1.percent || 1234 qi->qs.upperlimit.m2.percent) 1235 errx(1, "only absolute bandwidth specs for now"); 1236 } 1237 1238 if ((pf->opts & PF_OPT_NOACTION) == 0) 1239 ticket = pfctl_get_ticket(pf->trans, PF_TRANS_RULESET, ""); 1240 1241 TAILQ_FOREACH_SAFE(qi, &rootqs, entries, tempqi) { 1242 TAILQ_REMOVE(&rootqs, qi, entries); 1243 1244 /* 1245 * We must have a hidden root queue below the user- 1246 * specified/visible root queue, due to the way the 1247 * dequeueing works far down there... don't ask. 1248 * the _ namespace is reserved for these. 1249 */ 1250 bzero(&rqi, sizeof(rqi)); 1251 TAILQ_INIT(&rqi.children); 1252 TAILQ_INSERT_TAIL(&rqi.children, qi, entries); 1253 snprintf(rqi.qs.qname, PF_QNAME_SIZE, "_root_%s", 1254 qi->qs.ifname); 1255 strlcpy(rqi.qs.ifname, qi->qs.ifname, sizeof(rqi.qs.ifname)); 1256 strlcpy(qi->qs.parent, rqi.qs.qname, sizeof(qi->qs.parent)); 1257 1258 pfctl_load_queue(pf, ticket, &rqi); 1259 1260 TAILQ_INSERT_HEAD(&rootqs, qi, entries); 1261 } 1262 1263 return (0); 1264 } 1265 1266 void 1267 pfctl_clear_queues(struct pf_qihead *head) 1268 { 1269 struct pfctl_qsitem *qi; 1270 1271 while ((qi = TAILQ_FIRST(head)) != NULL) { 1272 TAILQ_REMOVE(head, qi, entries); 1273 pfctl_clear_queues(&qi->children); 1274 free(qi); 1275 } 1276 } 1277 1278 u_int 1279 pfctl_leafqueue_check(char *qname) 1280 { 1281 struct pfctl_qsitem *qi; 1282 if (qname == NULL || qname[0] == 0) 1283 return (0); 1284 1285 TAILQ_FOREACH(qi, &rootqs, entries) { 1286 if (strcmp(qname, qi->qs.qname)) 1287 continue; 1288 if (!TAILQ_EMPTY(&qi->children)) { 1289 printf("queue %s: packets must be assigned to leaf " 1290 "queues only\n", qname); 1291 return (1); 1292 } 1293 } 1294 TAILQ_FOREACH(qi, &qspecs, entries) { 1295 if (strcmp(qname, qi->qs.qname)) 1296 continue; 1297 if (!TAILQ_EMPTY(&qi->children)) { 1298 printf("queue %s: packets must be assigned to leaf " 1299 "queues only\n", qname); 1300 return (1); 1301 } 1302 } 1303 return (0); 1304 } 1305 1306 u_int 1307 pfctl_check_qassignments(struct pf_ruleset *rs) 1308 { 1309 struct pf_rule *r; 1310 struct pfctl_qsitem *qi; 1311 u_int flags, errs = 0; 1312 1313 /* main ruleset: need find_childqs to populate qi->children */ 1314 if (rs->anchor->path[0] == 0) { 1315 TAILQ_FOREACH(qi, &rootqs, entries) { 1316 flags = pfctl_find_childqs(qi); 1317 if (!(flags & HFSC_DEFAULTCLASS)) 1318 errx(1, "no default queue specified"); 1319 } 1320 } 1321 1322 TAILQ_FOREACH(r, rs->rules.active.ptr, entries) { 1323 if (r->anchor) 1324 errs += pfctl_check_qassignments(&r->anchor->ruleset); 1325 if (pfctl_leafqueue_check(r->qname) || 1326 pfctl_leafqueue_check(r->pqname)) 1327 errs++; 1328 } 1329 return (errs); 1330 } 1331 1332 int 1333 pfctl_load_ruleset(struct pfctl *pf, char *path, struct pf_ruleset *rs, 1334 int depth) 1335 { 1336 struct pf_rule *r; 1337 int error, len = strlen(path); 1338 int brace = 0; 1339 1340 pf->anchor = rs->anchor; 1341 1342 if (path[0]) 1343 snprintf(&path[len], PATH_MAX - len, "/%s", pf->anchor->name); 1344 else 1345 snprintf(&path[len], PATH_MAX - len, "%s", pf->anchor->path); 1346 1347 if (depth) { 1348 if (TAILQ_FIRST(rs->rules.active.ptr) != NULL) { 1349 brace++; 1350 if (pf->opts & PF_OPT_VERBOSE) 1351 printf(" {\n"); 1352 if ((pf->opts & PF_OPT_NOACTION) == 0 && 1353 (error = pfctl_ruleset_trans(pf, 1354 path, rs->anchor))) { 1355 printf("pfctl_load_rulesets: " 1356 "pfctl_ruleset_trans %d\n", error); 1357 goto error; 1358 } 1359 } else if (pf->opts & PF_OPT_VERBOSE) 1360 printf("\n"); 1361 1362 } 1363 1364 if (pf->optimize) 1365 pfctl_optimize_ruleset(pf, rs); 1366 1367 while ((r = TAILQ_FIRST(rs->rules.active.ptr)) != NULL) { 1368 TAILQ_REMOVE(rs->rules.active.ptr, r, entries); 1369 if ((error = pfctl_load_rule(pf, path, r, depth))) 1370 goto error; 1371 if (r->anchor) { 1372 if ((error = pfctl_load_ruleset(pf, path, 1373 &r->anchor->ruleset, depth + 1))) 1374 goto error; 1375 } else if (pf->opts & PF_OPT_VERBOSE) 1376 printf("\n"); 1377 free(r); 1378 } 1379 if (brace && pf->opts & PF_OPT_VERBOSE) { 1380 INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1381 printf("}\n"); 1382 } 1383 path[len] = '\0'; 1384 return (0); 1385 1386 error: 1387 path[len] = '\0'; 1388 return (error); 1389 1390 } 1391 1392 int 1393 pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) 1394 { 1395 char *name; 1396 struct pfioc_rule pr; 1397 int len = strlen(path); 1398 1399 bzero(&pr, sizeof(pr)); 1400 /* set up anchor before adding to path for anchor_call */ 1401 if ((pf->opts & PF_OPT_NOACTION) == 0) 1402 pr.ticket = pfctl_get_ticket(pf->trans, PF_TRANS_RULESET, path); 1403 if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor)) 1404 errx(1, "pfctl_load_rule: strlcpy"); 1405 1406 if (r->anchor) { 1407 if (r->anchor->match) { 1408 if (path[0]) 1409 snprintf(&path[len], PATH_MAX - len, 1410 "/%s", r->anchor->name); 1411 else 1412 snprintf(&path[len], PATH_MAX - len, 1413 "%s", r->anchor->name); 1414 name = r->anchor->name; 1415 } else 1416 name = r->anchor->path; 1417 } else 1418 name = ""; 1419 1420 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1421 memcpy(&pr.rule, r, sizeof(pr.rule)); 1422 if (r->anchor && strlcpy(pr.anchor_call, name, 1423 sizeof(pr.anchor_call)) >= sizeof(pr.anchor_call)) 1424 errx(1, "pfctl_load_rule: strlcpy"); 1425 if (ioctl(pf->dev, DIOCADDRULE, &pr)) 1426 err(1, "DIOCADDRULE"); 1427 } 1428 1429 if (pf->opts & PF_OPT_VERBOSE) { 1430 INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 1431 print_rule(r, name, pf->opts); 1432 } 1433 path[len] = '\0'; 1434 return (0); 1435 } 1436 1437 int 1438 pfctl_rules(int dev, char *filename, int opts, int optimize, 1439 char *anchorname, struct pfr_buffer *trans) 1440 { 1441 #define ERR(x) do { warn(x); goto _error; } while(0) 1442 #define ERRX(x) do { warnx(x); goto _error; } while(0) 1443 1444 struct pfr_buffer *t, buf; 1445 struct pfctl pf; 1446 struct pf_ruleset *rs; 1447 struct pfr_table trs; 1448 char *path = NULL; 1449 int osize; 1450 char *p; 1451 1452 bzero(&pf, sizeof(pf)); 1453 RB_INIT(&pf_anchors); 1454 memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 1455 pf_init_ruleset(&pf_main_anchor.ruleset); 1456 pf_main_anchor.ruleset.anchor = &pf_main_anchor; 1457 if (trans == NULL) { 1458 bzero(&buf, sizeof(buf)); 1459 buf.pfrb_type = PFRB_TRANS; 1460 t = &buf; 1461 osize = 0; 1462 } else { 1463 t = trans; 1464 osize = t->pfrb_size; 1465 } 1466 1467 memset(&pf, 0, sizeof(pf)); 1468 memset(&trs, 0, sizeof(trs)); 1469 if ((path = calloc(1, PATH_MAX)) == NULL) 1470 ERRX("pfctl_rules: calloc"); 1471 if (strlcpy(trs.pfrt_anchor, anchorname, 1472 sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 1473 ERRX("pfctl_rules: strlcpy"); 1474 pf.dev = dev; 1475 pf.opts = opts; 1476 pf.optimize = optimize; 1477 1478 /* non-brace anchor, create without resolving the path */ 1479 if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 1480 ERRX("pfctl_rules: calloc"); 1481 rs = &pf.anchor->ruleset; 1482 pf_init_ruleset(rs); 1483 rs->anchor = pf.anchor; 1484 if (strlcpy(pf.anchor->path, anchorname, 1485 sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 1486 errx(1, "pfctl_add_rule: strlcpy"); 1487 1488 if ((p = strrchr(anchorname, '/')) != NULL) { 1489 if (strlen(p) == 1) 1490 errx(1, "pfctl_add_rule: bad anchor name %s", 1491 anchorname); 1492 } else 1493 p = anchorname; 1494 1495 if (strlcpy(pf.anchor->name, p, 1496 sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 1497 errx(1, "pfctl_add_rule: strlcpy"); 1498 1499 1500 pf.astack[0] = pf.anchor; 1501 pf.asd = 0; 1502 pf.trans = t; 1503 pfctl_init_options(&pf); 1504 1505 if ((opts & PF_OPT_NOACTION) == 0) { 1506 /* 1507 * XXX For the time being we need to open transactions for 1508 * the main ruleset before parsing, because tables are still 1509 * loaded at parse time. 1510 */ 1511 if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor)) 1512 ERRX("pfctl_rules"); 1513 pf.astack[0]->ruleset.tticket = 1514 pfctl_get_ticket(t, PF_TRANS_TABLE, anchorname); 1515 } 1516 1517 if (parse_config(filename, &pf) < 0) { 1518 if ((opts & PF_OPT_NOACTION) == 0) 1519 ERRX("Syntax error in config file: " 1520 "pf rules not loaded"); 1521 else 1522 goto _error; 1523 } 1524 1525 if (!anchorname[0] && (pfctl_check_qassignments(&pf.anchor->ruleset) || 1526 pfctl_load_queues(&pf))) { 1527 if ((opts & PF_OPT_NOACTION) == 0) 1528 ERRX("Unable to load queues into kernel"); 1529 else 1530 goto _error; 1531 } 1532 1533 if (pfctl_load_ruleset(&pf, path, rs, 0)) { 1534 if ((opts & PF_OPT_NOACTION) == 0) 1535 ERRX("Unable to load rules into kernel"); 1536 else 1537 goto _error; 1538 } 1539 1540 free(path); 1541 path = NULL; 1542 1543 /* process "load anchor" directives that might have used queues */ 1544 if (!anchorname[0]) { 1545 if (pfctl_load_anchors(dev, &pf, t) == -1) 1546 ERRX("load anchors"); 1547 pfctl_clear_queues(&qspecs); 1548 pfctl_clear_queues(&rootqs); 1549 } 1550 1551 if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) { 1552 if (!anchorname[0]) 1553 if (pfctl_load_options(&pf)) 1554 goto _error; 1555 if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 1556 ERR("DIOCXCOMMIT"); 1557 } 1558 return (0); 1559 1560 _error: 1561 if (trans == NULL) { /* main ruleset */ 1562 if ((opts & PF_OPT_NOACTION) == 0) 1563 if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 1564 err(1, "DIOCXROLLBACK"); 1565 exit(1); 1566 } else { /* sub ruleset */ 1567 free(path); 1568 return (-1); 1569 } 1570 1571 #undef ERR 1572 #undef ERRX 1573 } 1574 1575 FILE * 1576 pfctl_fopen(const char *name, const char *mode) 1577 { 1578 struct stat st; 1579 FILE *fp; 1580 1581 fp = fopen(name, mode); 1582 if (fp == NULL) 1583 return (NULL); 1584 if (fstat(fileno(fp), &st)) { 1585 fclose(fp); 1586 return (NULL); 1587 } 1588 if (S_ISDIR(st.st_mode)) { 1589 fclose(fp); 1590 errno = EISDIR; 1591 return (NULL); 1592 } 1593 return (fp); 1594 } 1595 1596 void 1597 pfctl_init_options(struct pfctl *pf) 1598 { 1599 int64_t mem; 1600 int mib[2], mcl; 1601 size_t size; 1602 1603 pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 1604 pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 1605 pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 1606 pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 1607 pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 1608 pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 1609 pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 1610 pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 1611 pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 1612 pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 1613 pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 1614 pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 1615 pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 1616 pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 1617 pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 1618 pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 1619 pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 1620 pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 1621 pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 1622 pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 1623 1624 pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 1625 1626 mib[0] = CTL_KERN; 1627 mib[1] = KERN_MAXCLUSTERS; 1628 size = sizeof(mcl); 1629 if (sysctl(mib, 2, &mcl, &size, NULL, 0) == -1) 1630 err(1, "sysctl"); 1631 pf->limit[PF_LIMIT_FRAGS] = mcl / 4; 1632 1633 pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; 1634 pf->limit[PF_LIMIT_TABLES] = PFR_KTABLE_HIWAT; 1635 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; 1636 1637 mib[0] = CTL_HW; 1638 mib[1] = HW_PHYSMEM64; 1639 size = sizeof(mem); 1640 if (sysctl(mib, 2, &mem, &size, NULL, 0) == -1) 1641 err(1, "sysctl"); 1642 if (mem <= 100*1024*1024) 1643 pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT_SMALL; 1644 1645 pf->debug = LOG_ERR; 1646 pf->debug_set = 0; 1647 pf->reassemble = PF_REASS_ENABLED; 1648 } 1649 1650 int 1651 pfctl_load_options(struct pfctl *pf) 1652 { 1653 int i, error = 0; 1654 1655 /* load limits */ 1656 for (i = 0; i < PF_LIMIT_MAX; i++) 1657 if (pfctl_load_limit(pf, i, pf->limit[i])) 1658 error = 1; 1659 1660 /* 1661 * If we've set the limit, but haven't explicitly set adaptive 1662 * timeouts, do it now with a start of 60% and end of 120%. 1663 */ 1664 if (pf->limit_set[PF_LIMIT_STATES] && 1665 !pf->timeout_set[PFTM_ADAPTIVE_START] && 1666 !pf->timeout_set[PFTM_ADAPTIVE_END]) { 1667 pf->timeout[PFTM_ADAPTIVE_START] = 1668 (pf->limit[PF_LIMIT_STATES] / 10) * 6; 1669 pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 1670 pf->timeout[PFTM_ADAPTIVE_END] = 1671 (pf->limit[PF_LIMIT_STATES] / 10) * 12; 1672 pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 1673 } 1674 1675 /* load timeouts */ 1676 for (i = 0; i < PFTM_MAX; i++) 1677 if (pfctl_load_timeout(pf, i, pf->timeout[i])) 1678 error = 1; 1679 1680 /* load debug */ 1681 if (pf->debug_set && pfctl_load_debug(pf, pf->debug)) 1682 error = 1; 1683 1684 /* load logif */ 1685 if (pf->ifname_set && pfctl_load_logif(pf, pf->ifname)) 1686 error = 1; 1687 1688 /* load hostid */ 1689 if (pf->hostid_set && pfctl_load_hostid(pf, pf->hostid)) 1690 error = 1; 1691 1692 /* load reassembly settings */ 1693 if (pf->reass_set && pfctl_load_reassembly(pf, pf->reassemble)) 1694 error = 1; 1695 1696 return (error); 1697 } 1698 1699 int 1700 pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 1701 { 1702 int i; 1703 1704 1705 for (i = 0; pf_limits[i].name; i++) { 1706 if (strcasecmp(opt, pf_limits[i].name) == 0) { 1707 pf->limit[pf_limits[i].index] = limit; 1708 pf->limit_set[pf_limits[i].index] = 1; 1709 break; 1710 } 1711 } 1712 if (pf_limits[i].name == NULL) { 1713 warnx("Bad pool name."); 1714 return (1); 1715 } 1716 1717 if (pf->opts & PF_OPT_VERBOSE) 1718 printf("set limit %s %d\n", opt, limit); 1719 1720 return (0); 1721 } 1722 1723 int 1724 pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 1725 { 1726 struct pfioc_limit pl; 1727 1728 memset(&pl, 0, sizeof(pl)); 1729 pl.index = index; 1730 pl.limit = limit; 1731 if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { 1732 if (errno == EBUSY) 1733 warnx("Current pool size exceeds requested %s limit %u", 1734 pf_limits[index].name, limit); 1735 else 1736 warnx("Cannot set %s limit to %u", 1737 pf_limits[index].name, limit); 1738 return (1); 1739 } 1740 return (0); 1741 } 1742 1743 int 1744 pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 1745 { 1746 int i; 1747 1748 for (i = 0; pf_timeouts[i].name; i++) { 1749 if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 1750 pf->timeout[pf_timeouts[i].timeout] = seconds; 1751 pf->timeout_set[pf_timeouts[i].timeout] = 1; 1752 break; 1753 } 1754 } 1755 1756 if (pf_timeouts[i].name == NULL) { 1757 warnx("Bad timeout name."); 1758 return (1); 1759 } 1760 1761 1762 if (pf->opts & PF_OPT_VERBOSE && ! quiet) 1763 printf("set timeout %s %d\n", opt, seconds); 1764 1765 return (0); 1766 } 1767 1768 int 1769 pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 1770 { 1771 struct pfioc_tm pt; 1772 1773 memset(&pt, 0, sizeof(pt)); 1774 pt.timeout = timeout; 1775 pt.seconds = seconds; 1776 if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) { 1777 warnx("DIOCSETTIMEOUT"); 1778 return (1); 1779 } 1780 return (0); 1781 } 1782 1783 int 1784 pfctl_set_reassembly(struct pfctl *pf, int on, int nodf) 1785 { 1786 pf->reass_set = 1; 1787 if (on) { 1788 pf->reassemble = PF_REASS_ENABLED; 1789 if (nodf) 1790 pf->reassemble |= PF_REASS_NODF; 1791 } else { 1792 pf->reassemble = 0; 1793 } 1794 1795 if (pf->opts & PF_OPT_VERBOSE) 1796 printf("set reassemble %s %s\n", on ? "yes" : "no", 1797 nodf ? "no-df" : ""); 1798 1799 return (0); 1800 } 1801 1802 int 1803 pfctl_set_optimization(struct pfctl *pf, const char *opt) 1804 { 1805 const struct pf_hint *hint; 1806 int i, r; 1807 1808 for (i = 0; pf_hints[i].name; i++) 1809 if (strcasecmp(opt, pf_hints[i].name) == 0) 1810 break; 1811 1812 hint = pf_hints[i].hint; 1813 if (hint == NULL) { 1814 warnx("invalid state timeouts optimization"); 1815 return (1); 1816 } 1817 1818 for (i = 0; hint[i].name; i++) 1819 if ((r = pfctl_set_timeout(pf, hint[i].name, 1820 hint[i].timeout, 1))) 1821 return (r); 1822 1823 if (pf->opts & PF_OPT_VERBOSE) 1824 printf("set optimization %s\n", opt); 1825 1826 return (0); 1827 } 1828 1829 int 1830 pfctl_set_logif(struct pfctl *pf, char *ifname) 1831 { 1832 if (!strcmp(ifname, "none")) { 1833 free(pf->ifname); 1834 pf->ifname = NULL; 1835 } else { 1836 pf->ifname = strdup(ifname); 1837 if (!pf->ifname) 1838 errx(1, "pfctl_set_logif: strdup"); 1839 } 1840 pf->ifname_set = 1; 1841 1842 if (pf->opts & PF_OPT_VERBOSE) 1843 printf("set loginterface %s\n", ifname); 1844 1845 return (0); 1846 } 1847 1848 int 1849 pfctl_load_logif(struct pfctl *pf, char *ifname) 1850 { 1851 struct pfioc_iface pi; 1852 1853 memset(&pi, 0, sizeof(pi)); 1854 if (ifname && strlcpy(pi.pfiio_name, ifname, 1855 sizeof(pi.pfiio_name)) >= sizeof(pi.pfiio_name)) { 1856 warnx("pfctl_load_logif: strlcpy"); 1857 return (1); 1858 } 1859 if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) { 1860 warnx("DIOCSETSTATUSIF"); 1861 return (1); 1862 } 1863 return (0); 1864 } 1865 1866 void 1867 pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 1868 { 1869 HTONL(hostid); 1870 1871 pf->hostid = hostid; 1872 pf->hostid_set = 1; 1873 1874 if (pf->opts & PF_OPT_VERBOSE) 1875 printf("set hostid 0x%08x\n", ntohl(hostid)); 1876 } 1877 1878 int 1879 pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 1880 { 1881 if (ioctl(dev, DIOCSETHOSTID, &hostid)) { 1882 warnx("DIOCSETHOSTID"); 1883 return (1); 1884 } 1885 return (0); 1886 } 1887 1888 int 1889 pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly) 1890 { 1891 if (ioctl(dev, DIOCSETREASS, &reassembly)) { 1892 warnx("DIOCSETREASS"); 1893 return (1); 1894 } 1895 return (0); 1896 } 1897 1898 int 1899 pfctl_set_debug(struct pfctl *pf, char *d) 1900 { 1901 u_int32_t level; 1902 int loglevel; 1903 1904 if ((loglevel = string_to_loglevel(d)) >= 0) 1905 level = loglevel; 1906 else { 1907 warnx("unknown debug level \"%s\"", d); 1908 return (-1); 1909 } 1910 pf->debug = level; 1911 pf->debug_set = 1; 1912 1913 if ((pf->opts & PF_OPT_NOACTION) == 0) 1914 if (ioctl(dev, DIOCSETDEBUG, &level)) 1915 err(1, "DIOCSETDEBUG"); 1916 1917 if (pf->opts & PF_OPT_VERBOSE) 1918 printf("set debug %s\n", d); 1919 1920 return (0); 1921 } 1922 1923 int 1924 pfctl_load_debug(struct pfctl *pf, unsigned int level) 1925 { 1926 if (ioctl(pf->dev, DIOCSETDEBUG, &level)) { 1927 warnx("DIOCSETDEBUG"); 1928 return (1); 1929 } 1930 return (0); 1931 } 1932 1933 int 1934 pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 1935 { 1936 struct pfioc_iface pi; 1937 1938 bzero(&pi, sizeof(pi)); 1939 1940 pi.pfiio_flags = flags; 1941 1942 if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 1943 sizeof(pi.pfiio_name)) 1944 errx(1, "pfctl_set_interface_flags: strlcpy"); 1945 1946 if ((pf->opts & PF_OPT_NOACTION) == 0) { 1947 if (how == 0) { 1948 if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi)) 1949 err(1, "DIOCCLRIFFLAG"); 1950 } else { 1951 if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) 1952 err(1, "DIOCSETIFFLAG"); 1953 } 1954 } 1955 return (0); 1956 } 1957 1958 void 1959 pfctl_debug(int dev, u_int32_t level, int opts) 1960 { 1961 struct pfr_buffer t; 1962 1963 memset(&t, 0, sizeof(t)); 1964 t.pfrb_type = PFRB_TRANS; 1965 if (pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 1966 ioctl(dev, DIOCSETDEBUG, &level) || 1967 pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 1968 err(1, "pfctl_debug ioctl"); 1969 1970 if ((opts & PF_OPT_QUIET) == 0) 1971 fprintf(stderr, "debug level set to '%s'\n", 1972 loglevel_to_string(level)); 1973 } 1974 1975 int 1976 pfctl_show_anchors(int dev, int opts, char *anchorname) 1977 { 1978 struct pfioc_ruleset pr; 1979 u_int32_t mnr, nr; 1980 1981 memset(&pr, 0, sizeof(pr)); 1982 memcpy(pr.path, anchorname, sizeof(pr.path)); 1983 if (ioctl(dev, DIOCGETRULESETS, &pr)) { 1984 if (errno == EINVAL) 1985 fprintf(stderr, "Anchor '%s' not found.\n", 1986 anchorname); 1987 else 1988 err(1, "DIOCGETRULESETS"); 1989 return (-1); 1990 } 1991 mnr = pr.nr; 1992 for (nr = 0; nr < mnr; ++nr) { 1993 char sub[PATH_MAX]; 1994 1995 pr.nr = nr; 1996 if (ioctl(dev, DIOCGETRULESET, &pr)) 1997 err(1, "DIOCGETRULESET"); 1998 if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 1999 continue; 2000 sub[0] = 0; 2001 if (pr.path[0]) { 2002 strlcat(sub, pr.path, sizeof(sub)); 2003 strlcat(sub, "/", sizeof(sub)); 2004 } 2005 strlcat(sub, pr.name, sizeof(sub)); 2006 if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 2007 printf(" %s\n", sub); 2008 if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub)) 2009 return (-1); 2010 } 2011 return (0); 2012 } 2013 2014 const char * 2015 pfctl_lookup_option(char *cmd, const char **list) 2016 { 2017 const char *item = NULL; 2018 if (cmd != NULL && *cmd) 2019 for (; *list; list++) 2020 if (!strncmp(cmd, *list, strlen(cmd))) { 2021 if (item == NULL) 2022 item = *list; 2023 else 2024 errx(1, "%s is ambigious", cmd); 2025 } 2026 2027 return (item); 2028 } 2029 2030 2031 void 2032 pfctl_state_store(int dev, const char *file) 2033 { 2034 FILE *f; 2035 struct pfioc_states ps; 2036 char *inbuf = NULL, *newinbuf = NULL; 2037 unsigned int len = 0; 2038 size_t n; 2039 2040 f = fopen(file, "w"); 2041 if (f == NULL) 2042 err(1, "open: %s", file); 2043 2044 memset(&ps, 0, sizeof(ps)); 2045 for (;;) { 2046 ps.ps_len = len; 2047 if (len) { 2048 newinbuf = realloc(inbuf, len); 2049 if (newinbuf == NULL) 2050 err(1, "realloc"); 2051 ps.ps_buf = inbuf = newinbuf; 2052 } 2053 if (ioctl(dev, DIOCGETSTATES, &ps) < 0) 2054 err(1, "DIOCGETSTATES"); 2055 2056 if (ps.ps_len + sizeof(struct pfioc_states) < len) 2057 break; 2058 if (len == 0 && ps.ps_len == 0) 2059 goto done; 2060 if (len == 0 && ps.ps_len != 0) 2061 len = ps.ps_len; 2062 if (ps.ps_len == 0) 2063 goto done; /* no states */ 2064 len *= 2; 2065 } 2066 2067 n = ps.ps_len / sizeof(struct pfsync_state); 2068 if (fwrite(inbuf, sizeof(struct pfsync_state), n, f) < n) 2069 err(1, "fwrite"); 2070 2071 done: 2072 free(inbuf); 2073 fclose(f); 2074 } 2075 2076 void 2077 pfctl_state_load(int dev, const char *file) 2078 { 2079 FILE *f; 2080 struct pfioc_state ps; 2081 2082 f = fopen(file, "r"); 2083 if (f == NULL) 2084 err(1, "open: %s", file); 2085 2086 while (fread(&ps.state, sizeof(ps.state), 1, f) == 1) { 2087 if (ioctl(dev, DIOCADDSTATE, &ps) < 0) { 2088 switch (errno) { 2089 case EEXIST: 2090 case EINVAL: 2091 break; 2092 default: 2093 err(1, "DIOCADDSTATE"); 2094 } 2095 } 2096 } 2097 2098 fclose(f); 2099 } 2100 2101 int 2102 main(int argc, char *argv[]) 2103 { 2104 int error = 0; 2105 int ch; 2106 int mode = O_RDONLY; 2107 int opts = 0; 2108 int optimize = PF_OPTIMIZE_BASIC; 2109 int level; 2110 char anchorname[PATH_MAX]; 2111 int anchor_wildcard = 0; 2112 char *path; 2113 char *lfile = NULL, *sfile = NULL; 2114 const char *errstr; 2115 long shownr = -1; 2116 2117 if (argc < 2) 2118 usage(); 2119 2120 while ((ch = getopt(argc, argv, 2121 "a:dD:eqf:F:ghi:k:K:L:no:Pp:R:rS:s:t:T:vx:z")) != -1) { 2122 switch (ch) { 2123 case 'a': 2124 anchoropt = optarg; 2125 break; 2126 case 'd': 2127 opts |= PF_OPT_DISABLE; 2128 mode = O_RDWR; 2129 break; 2130 case 'D': 2131 if (pfctl_cmdline_symset(optarg) < 0) 2132 warnx("could not parse macro definition %s", 2133 optarg); 2134 break; 2135 case 'e': 2136 opts |= PF_OPT_ENABLE; 2137 mode = O_RDWR; 2138 break; 2139 case 'q': 2140 opts |= PF_OPT_QUIET; 2141 break; 2142 case 'F': 2143 clearopt = pfctl_lookup_option(optarg, clearopt_list); 2144 if (clearopt == NULL) { 2145 warnx("Unknown flush modifier '%s'", optarg); 2146 usage(); 2147 } 2148 mode = O_RDWR; 2149 break; 2150 case 'i': 2151 ifaceopt = optarg; 2152 break; 2153 case 'k': 2154 if (state_killers >= 2) { 2155 warnx("can only specify -k twice"); 2156 usage(); 2157 /* NOTREACHED */ 2158 } 2159 state_kill[state_killers++] = optarg; 2160 mode = O_RDWR; 2161 break; 2162 case 'K': 2163 if (src_node_killers >= 2) { 2164 warnx("can only specify -K twice"); 2165 usage(); 2166 /* NOTREACHED */ 2167 } 2168 src_node_kill[src_node_killers++] = optarg; 2169 mode = O_RDWR; 2170 break; 2171 case 'n': 2172 opts |= PF_OPT_NOACTION; 2173 break; 2174 case 'r': 2175 opts |= PF_OPT_USEDNS; 2176 break; 2177 case 'R': 2178 shownr = strtonum(optarg, -1, LONG_MAX, &errstr); 2179 if (errstr) { 2180 warnx("invalid rule id: %s", errstr); 2181 usage(); 2182 } 2183 break; 2184 case 'f': 2185 rulesopt = optarg; 2186 mode = O_RDWR; 2187 break; 2188 case 'g': 2189 opts |= PF_OPT_DEBUG; 2190 break; 2191 case 'o': 2192 optiopt = pfctl_lookup_option(optarg, optiopt_list); 2193 if (optiopt == NULL) { 2194 warnx("Unknown optimization '%s'", optarg); 2195 usage(); 2196 } 2197 opts |= PF_OPT_OPTIMIZE; 2198 break; 2199 case 'P': 2200 opts |= PF_OPT_PORTNAMES; 2201 break; 2202 case 'p': 2203 pf_device = optarg; 2204 break; 2205 case 's': 2206 showopt = pfctl_lookup_option(optarg, showopt_list); 2207 if (showopt == NULL) { 2208 warnx("Unknown show modifier '%s'", optarg); 2209 usage(); 2210 } 2211 break; 2212 case 't': 2213 tableopt = optarg; 2214 break; 2215 case 'T': 2216 tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 2217 if (tblcmdopt == NULL) { 2218 warnx("Unknown table command '%s'", optarg); 2219 usage(); 2220 } 2221 break; 2222 case 'v': 2223 if (opts & PF_OPT_VERBOSE) 2224 opts |= PF_OPT_VERBOSE2; 2225 opts |= PF_OPT_VERBOSE; 2226 break; 2227 case 'x': 2228 debugopt = pfctl_lookup_option(optarg, debugopt_list); 2229 if (debugopt == NULL) { 2230 warnx("Unknown debug level '%s'", optarg); 2231 usage(); 2232 } 2233 mode = O_RDWR; 2234 break; 2235 case 'z': 2236 opts |= PF_OPT_CLRRULECTRS; 2237 mode = O_RDWR; 2238 break; 2239 case 'S': 2240 sfile = optarg; 2241 break; 2242 case 'L': 2243 mode = O_RDWR; 2244 lfile = optarg; 2245 break; 2246 case 'h': 2247 /* FALLTHROUGH */ 2248 default: 2249 usage(); 2250 /* NOTREACHED */ 2251 } 2252 } 2253 2254 if (tblcmdopt != NULL) { 2255 argc -= optind; 2256 argv += optind; 2257 ch = *tblcmdopt; 2258 mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY; 2259 } else if (argc != optind) { 2260 warnx("unknown command line argument: %s ...", argv[optind]); 2261 usage(); 2262 /* NOTREACHED */ 2263 } 2264 2265 if ((path = calloc(1, PATH_MAX)) == NULL) 2266 errx(1, "pfctl: calloc"); 2267 memset(anchorname, 0, sizeof(anchorname)); 2268 if (anchoropt != NULL) { 2269 int len = strlen(anchoropt); 2270 2271 if (anchoropt[len - 1] == '*') { 2272 if (len >= 2 && anchoropt[len - 2] == '/') { 2273 anchoropt[len - 2] = '\0'; 2274 anchor_wildcard = 1; 2275 } else 2276 anchoropt[len - 1] = '\0'; 2277 opts |= PF_OPT_RECURSE; 2278 } 2279 if (strlcpy(anchorname, anchoropt, 2280 sizeof(anchorname)) >= sizeof(anchorname)) 2281 errx(1, "anchor name '%s' too long", 2282 anchoropt); 2283 } 2284 2285 if ((opts & PF_OPT_NOACTION) == 0) { 2286 dev = open(pf_device, mode); 2287 if (dev == -1) 2288 err(1, "%s", pf_device); 2289 } else { 2290 dev = open(pf_device, O_RDONLY); 2291 if (dev >= 0) 2292 opts |= PF_OPT_DUMMYACTION; 2293 /* turn off options */ 2294 opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 2295 clearopt = showopt = debugopt = NULL; 2296 } 2297 2298 if (opts & PF_OPT_DISABLE) 2299 if (pfctl_disable(dev, opts)) 2300 error = 1; 2301 2302 if (showopt != NULL) { 2303 switch (*showopt) { 2304 case 'A': 2305 pfctl_show_anchors(dev, opts, anchorname); 2306 break; 2307 case 'r': 2308 pfctl_load_fingerprints(dev, opts); 2309 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 2310 anchorname, 0, anchor_wildcard, shownr); 2311 break; 2312 case 'l': 2313 pfctl_load_fingerprints(dev, opts); 2314 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 2315 anchorname, 0, anchor_wildcard, shownr); 2316 break; 2317 case 'q': 2318 pfctl_show_queues(dev, ifaceopt, opts, 2319 opts & PF_OPT_VERBOSE2); 2320 break; 2321 case 's': 2322 pfctl_show_states(dev, ifaceopt, opts, shownr); 2323 break; 2324 case 'S': 2325 pfctl_show_src_nodes(dev, opts); 2326 break; 2327 case 'i': 2328 pfctl_show_status(dev, opts); 2329 break; 2330 case 't': 2331 pfctl_show_timeouts(dev, opts); 2332 break; 2333 case 'm': 2334 pfctl_show_limits(dev, opts); 2335 break; 2336 case 'a': 2337 opts |= PF_OPT_SHOWALL; 2338 pfctl_load_fingerprints(dev, opts); 2339 2340 pfctl_show_rules(dev, path, opts, 0, anchorname, 2341 0, 0, -1); 2342 pfctl_show_queues(dev, ifaceopt, opts, 2343 opts & PF_OPT_VERBOSE2); 2344 pfctl_show_states(dev, ifaceopt, opts, -1); 2345 pfctl_show_src_nodes(dev, opts); 2346 pfctl_show_status(dev, opts); 2347 pfctl_show_rules(dev, path, opts, 1, anchorname, 2348 0, 0, -1); 2349 pfctl_show_timeouts(dev, opts); 2350 pfctl_show_limits(dev, opts); 2351 pfctl_show_tables(anchorname, opts); 2352 pfctl_show_fingerprints(opts); 2353 break; 2354 case 'T': 2355 pfctl_show_tables(anchorname, opts); 2356 break; 2357 case 'o': 2358 pfctl_load_fingerprints(dev, opts); 2359 pfctl_show_fingerprints(opts); 2360 break; 2361 case 'I': 2362 pfctl_show_ifaces(ifaceopt, opts); 2363 break; 2364 } 2365 } 2366 2367 if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) 2368 pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 2369 anchorname, 0, 0, -1); 2370 2371 if (clearopt != NULL) { 2372 if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2373 errx(1, "anchor names beginning with '_' cannot " 2374 "be modified from the command line"); 2375 2376 switch (*clearopt) { 2377 case 'r': 2378 pfctl_clear_rules(dev, opts, anchorname); 2379 break; 2380 case 's': 2381 pfctl_clear_states(dev, ifaceopt, opts); 2382 break; 2383 case 'S': 2384 pfctl_clear_src_nodes(dev, opts); 2385 break; 2386 case 'i': 2387 pfctl_clear_stats(dev, ifaceopt, opts); 2388 break; 2389 case 'a': 2390 pfctl_clear_rules(dev, opts, anchorname); 2391 pfctl_clear_tables(anchorname, opts); 2392 if (ifaceopt && *ifaceopt) { 2393 warnx("don't specify an interface with -Fall"); 2394 usage(); 2395 /* NOTREACHED */ 2396 } 2397 if (!*anchorname) { 2398 pfctl_clear_states(dev, ifaceopt, opts); 2399 pfctl_clear_src_nodes(dev, opts); 2400 pfctl_clear_stats(dev, ifaceopt, opts); 2401 pfctl_clear_fingerprints(dev, opts); 2402 pfctl_clear_interface_flags(dev, opts); 2403 } 2404 break; 2405 case 'o': 2406 pfctl_clear_fingerprints(dev, opts); 2407 break; 2408 case 'T': 2409 pfctl_clear_tables(anchorname, opts); 2410 break; 2411 } 2412 } 2413 if (state_killers) { 2414 if (!strcmp(state_kill[0], "label")) 2415 pfctl_label_kill_states(dev, ifaceopt, opts); 2416 else if (!strcmp(state_kill[0], "id")) 2417 pfctl_id_kill_states(dev, ifaceopt, opts); 2418 else 2419 pfctl_net_kill_states(dev, ifaceopt, opts); 2420 } 2421 2422 if (src_node_killers) 2423 pfctl_kill_src_nodes(dev, ifaceopt, opts); 2424 2425 if (tblcmdopt != NULL) { 2426 error = pfctl_command_tables(argc, argv, tableopt, 2427 tblcmdopt, rulesopt, anchorname, opts); 2428 rulesopt = NULL; 2429 } 2430 if (optiopt != NULL) { 2431 switch (*optiopt) { 2432 case 'n': 2433 optimize = 0; 2434 break; 2435 case 'b': 2436 optimize |= PF_OPTIMIZE_BASIC; 2437 break; 2438 case 'o': 2439 case 'p': 2440 optimize |= PF_OPTIMIZE_PROFILE; 2441 break; 2442 } 2443 } 2444 2445 if ((rulesopt != NULL) && !anchorname[0]) 2446 if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET)) 2447 error = 1; 2448 2449 if (rulesopt != NULL && !anchorname[0]) 2450 if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 2451 error = 1; 2452 2453 if (rulesopt != NULL) { 2454 if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 2455 errx(1, "anchor names beginning with '_' cannot " 2456 "be modified from the command line"); 2457 if (pfctl_rules(dev, rulesopt, opts, optimize, 2458 anchorname, NULL)) 2459 error = 1; 2460 else if (!(opts & PF_OPT_NOACTION)) 2461 warn_namespace_collision(NULL); 2462 } 2463 2464 if (opts & PF_OPT_ENABLE) 2465 if (pfctl_enable(dev, opts)) 2466 error = 1; 2467 2468 if (debugopt != NULL) { 2469 if ((level = string_to_loglevel((char *)debugopt)) < 0) { 2470 switch (*debugopt) { 2471 case 'n': 2472 level = LOG_CRIT; 2473 break; 2474 case 'u': 2475 level = LOG_ERR; 2476 break; 2477 case 'm': 2478 level = LOG_NOTICE; 2479 break; 2480 case 'l': 2481 level = LOG_DEBUG; 2482 break; 2483 } 2484 } 2485 if (level >= 0) 2486 pfctl_debug(dev, level, opts); 2487 } 2488 2489 if (sfile != NULL) 2490 pfctl_state_store(dev, sfile); 2491 if (lfile != NULL) 2492 pfctl_state_load(dev, lfile); 2493 2494 exit(error); 2495 } 2496