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