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