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