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