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