pfctl.c revision 127082
1126353Smlaier/* $OpenBSD: pfctl.c,v 1.188 2003/08/29 21:47:36 cedric Exp $ */ 2126353Smlaier 3126353Smlaier/* 4126353Smlaier * Copyright (c) 2001 Daniel Hartmeier 5126353Smlaier * All rights reserved. 6126353Smlaier * 7126353Smlaier * Redistribution and use in source and binary forms, with or without 8126353Smlaier * modification, are permitted provided that the following conditions 9126353Smlaier * are met: 10126353Smlaier * 11126353Smlaier * - Redistributions of source code must retain the above copyright 12126353Smlaier * notice, this list of conditions and the following disclaimer. 13126353Smlaier * - Redistributions in binary form must reproduce the above 14126353Smlaier * copyright notice, this list of conditions and the following 15126353Smlaier * disclaimer in the documentation and/or other materials provided 16126353Smlaier * with the distribution. 17126353Smlaier * 18126353Smlaier * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19126353Smlaier * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20126353Smlaier * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21126353Smlaier * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22126353Smlaier * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23126353Smlaier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24126353Smlaier * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25126353Smlaier * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26126353Smlaier * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27126353Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28126353Smlaier * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29126353Smlaier * POSSIBILITY OF SUCH DAMAGE. 30126353Smlaier * 31126353Smlaier */ 32126353Smlaier 33127082Sobrien#include <sys/cdefs.h> 34127082Sobrien__FBSDID("$FreeBSD: head/contrib/pf/pfctl/pfctl.c 127082 2004-03-16 17:24:06Z obrien $"); 35127082Sobrien 36126353Smlaier#include <sys/types.h> 37126353Smlaier#include <sys/ioctl.h> 38126353Smlaier#include <sys/socket.h> 39126353Smlaier 40126353Smlaier#include <net/if.h> 41126353Smlaier#include <netinet/in.h> 42126353Smlaier#include <net/pfvar.h> 43126353Smlaier#include <arpa/inet.h> 44126353Smlaier#include <altq/altq.h> 45126353Smlaier 46126353Smlaier#include <err.h> 47126353Smlaier#include <errno.h> 48126353Smlaier#include <fcntl.h> 49126353Smlaier#include <limits.h> 50126353Smlaier#include <netdb.h> 51126353Smlaier#include <stdio.h> 52126353Smlaier#include <stdlib.h> 53126353Smlaier#include <string.h> 54126353Smlaier#include <unistd.h> 55126353Smlaier 56126353Smlaier#include "pfctl_parser.h" 57126353Smlaier#include "pfctl.h" 58126353Smlaier 59126353Smlaiervoid usage(void); 60126353Smlaierint pfctl_enable(int, int); 61126353Smlaierint pfctl_disable(int, int); 62126353Smlaierint pfctl_clear_stats(int, int); 63126353Smlaierint pfctl_clear_rules(int, int, char *, char *); 64126353Smlaierint pfctl_clear_nat(int, int, char *, char *); 65126353Smlaierint pfctl_clear_altq(int, int); 66126353Smlaierint pfctl_clear_states(int, int); 67126353Smlaierint pfctl_kill_states(int, int); 68126353Smlaierint pfctl_get_pool(int, struct pf_pool *, u_int32_t, u_int32_t, int, 69126353Smlaier char *, char *); 70126353Smlaiervoid pfctl_print_rule_counters(struct pf_rule *, int); 71126353Smlaierint pfctl_show_rules(int, int, int, char *, char *); 72126353Smlaierint pfctl_show_nat(int, int, char *, char *); 73126353Smlaierint pfctl_show_states(int, u_int8_t, int); 74126353Smlaierint pfctl_show_status(int); 75126353Smlaierint pfctl_show_timeouts(int); 76126353Smlaierint pfctl_show_limits(int); 77126353Smlaierint pfctl_debug(int, u_int32_t, int); 78126353Smlaierint pfctl_clear_rule_counters(int, int); 79126353Smlaierint pfctl_test_altqsupport(int, int); 80126353Smlaierint pfctl_show_anchors(int, int, char *); 81126353Smlaierconst char *pfctl_lookup_option(char *, const char **); 82126353Smlaier 83126353Smlaierconst char *clearopt; 84126353Smlaierchar *rulesopt; 85126353Smlaierconst char *showopt; 86126353Smlaierconst char *debugopt; 87126353Smlaierchar *anchoropt; 88126353Smlaierchar *tableopt; 89126353Smlaierconst char *tblcmdopt; 90126353Smlaierint state_killers; 91126353Smlaierchar *state_kill[2]; 92126353Smlaierint loadopt; 93126353Smlaierint altqsupport; 94126353Smlaier 95126353Smlaierint dev = -1; 96126353Smlaier 97126353Smlaierconst char *infile; 98126353Smlaier 99126353Smlaierstatic const struct { 100126353Smlaier const char *name; 101126353Smlaier int index; 102126353Smlaier} pf_limits[] = { 103126353Smlaier { "states", PF_LIMIT_STATES }, 104126353Smlaier { "frags", PF_LIMIT_FRAGS }, 105126353Smlaier { NULL, 0 } 106126353Smlaier}; 107126353Smlaier 108126353Smlaierstruct pf_hint { 109126353Smlaier const char *name; 110126353Smlaier int timeout; 111126353Smlaier}; 112126353Smlaierstatic const struct pf_hint pf_hint_normal[] = { 113126353Smlaier { "tcp.first", 2 * 60 }, 114126353Smlaier { "tcp.opening", 30 }, 115126353Smlaier { "tcp.established", 24 * 60 * 60 }, 116126353Smlaier { "tcp.closing", 15 * 60 }, 117126353Smlaier { "tcp.finwait", 45 }, 118126353Smlaier { "tcp.closed", 90 }, 119126353Smlaier { NULL, 0 } 120126353Smlaier}; 121126353Smlaierstatic const struct pf_hint pf_hint_satellite[] = { 122126353Smlaier { "tcp.first", 3 * 60 }, 123126353Smlaier { "tcp.opening", 30 + 5 }, 124126353Smlaier { "tcp.established", 24 * 60 * 60 }, 125126353Smlaier { "tcp.closing", 15 * 60 + 5 }, 126126353Smlaier { "tcp.finwait", 45 + 5 }, 127126353Smlaier { "tcp.closed", 90 + 5 }, 128126353Smlaier { NULL, 0 } 129126353Smlaier}; 130126353Smlaierstatic const struct pf_hint pf_hint_conservative[] = { 131126353Smlaier { "tcp.first", 60 * 60 }, 132126353Smlaier { "tcp.opening", 15 * 60 }, 133126353Smlaier { "tcp.established", 5 * 24 * 60 * 60 }, 134126353Smlaier { "tcp.closing", 60 * 60 }, 135126353Smlaier { "tcp.finwait", 10 * 60 }, 136126353Smlaier { "tcp.closed", 3 * 60 }, 137126353Smlaier { NULL, 0 } 138126353Smlaier}; 139126353Smlaierstatic const struct pf_hint pf_hint_aggressive[] = { 140126353Smlaier { "tcp.first", 30 }, 141126353Smlaier { "tcp.opening", 5 }, 142126353Smlaier { "tcp.established", 5 * 60 * 60 }, 143126353Smlaier { "tcp.closing", 60 }, 144126353Smlaier { "tcp.finwait", 30 }, 145126353Smlaier { "tcp.closed", 30 }, 146126353Smlaier { NULL, 0 } 147126353Smlaier}; 148126353Smlaier 149126353Smlaierstatic const struct { 150126353Smlaier const char *name; 151126353Smlaier const struct pf_hint *hint; 152126353Smlaier} pf_hints[] = { 153126353Smlaier { "normal", pf_hint_normal }, 154126353Smlaier { "satellite", pf_hint_satellite }, 155126353Smlaier { "high-latency", pf_hint_satellite }, 156126353Smlaier { "conservative", pf_hint_conservative }, 157126353Smlaier { "aggressive", pf_hint_aggressive }, 158126353Smlaier { NULL, NULL } 159126353Smlaier}; 160126353Smlaier 161126353Smlaierstatic const char *clearopt_list[] = { 162126353Smlaier "nat", "queue", "rules", "state", "info", "Tables", "osfp", "all", NULL 163126353Smlaier}; 164126353Smlaier 165126353Smlaierstatic const char *showopt_list[] = { 166126353Smlaier "nat", "queue", "rules", "Anchors", "state", "info", "labels", 167126353Smlaier "timeouts", "memory", "Tables", "osfp", "all", NULL 168126353Smlaier}; 169126353Smlaier 170126353Smlaierstatic const char *tblcmdopt_list[] = { 171126353Smlaier "kill", "flush", "add", "delete", "load", "replace", "show", 172126353Smlaier "test", "zero", NULL 173126353Smlaier}; 174126353Smlaier 175126353Smlaierstatic const char *debugopt_list[] = { 176126353Smlaier "none", "urgent", "misc", "loud", NULL 177126353Smlaier}; 178126353Smlaier 179126353Smlaier 180126353Smlaiervoid 181126353Smlaierusage(void) 182126353Smlaier{ 183126353Smlaier extern char *__progname; 184126353Smlaier 185126353Smlaier fprintf(stderr, "usage: %s [-AdeghnNqrROvz] ", __progname); 186126353Smlaier fprintf(stderr, "[-a anchor[:ruleset]] [-D macro=value]\n"); 187126353Smlaier fprintf(stderr, " "); 188126353Smlaier fprintf(stderr, "[-f file] [-F modifier] [-k host] [-s modifier]\n"); 189126353Smlaier fprintf(stderr, " "); 190126353Smlaier fprintf(stderr, "[-t table] [-T command [address ...]] [-x level]\n"); 191126353Smlaier exit(1); 192126353Smlaier} 193126353Smlaier 194126353Smlaierint 195126353Smlaierpfctl_enable(int dev, int opts) 196126353Smlaier{ 197126353Smlaier if (ioctl(dev, DIOCSTART)) { 198126353Smlaier if (errno == EEXIST) 199126353Smlaier errx(1, "pf already enabled"); 200127024Smlaier#ifdef __FreeBSD__ 201126355Smlaier else if (errno == ESRCH) 202126355Smlaier errx(1, "pfil registeration failed"); 203126355Smlaier#endif 204126353Smlaier else 205126353Smlaier err(1, "DIOCSTART"); 206126353Smlaier } 207126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 208126353Smlaier fprintf(stderr, "pf enabled\n"); 209126353Smlaier 210126353Smlaier if (altqsupport && ioctl(dev, DIOCSTARTALTQ)) 211126353Smlaier if (errno != EEXIST) 212126353Smlaier err(1, "DIOCSTARTALTQ"); 213126353Smlaier 214126353Smlaier return (0); 215126353Smlaier} 216126353Smlaier 217126353Smlaierint 218126353Smlaierpfctl_disable(int dev, int opts) 219126353Smlaier{ 220126353Smlaier if (ioctl(dev, DIOCSTOP)) { 221126353Smlaier if (errno == ENOENT) 222126353Smlaier errx(1, "pf not enabled"); 223126353Smlaier else 224126353Smlaier err(1, "DIOCSTOP"); 225126353Smlaier } 226126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 227126353Smlaier fprintf(stderr, "pf disabled\n"); 228126353Smlaier 229126353Smlaier if (altqsupport && ioctl(dev, DIOCSTOPALTQ)) 230126353Smlaier if (errno != ENOENT) 231126353Smlaier err(1, "DIOCSTOPALTQ"); 232126353Smlaier 233126353Smlaier return (0); 234126353Smlaier} 235126353Smlaier 236126353Smlaierint 237126353Smlaierpfctl_clear_stats(int dev, int opts) 238126353Smlaier{ 239126353Smlaier if (ioctl(dev, DIOCCLRSTATUS)) 240126353Smlaier err(1, "DIOCCLRSTATUS"); 241126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 242126353Smlaier fprintf(stderr, "pf: statistics cleared\n"); 243126353Smlaier return (0); 244126353Smlaier} 245126353Smlaier 246126353Smlaierint 247126353Smlaierpfctl_clear_rules(int dev, int opts, char *anchorname, char *rulesetname) 248126353Smlaier{ 249126353Smlaier struct pfioc_rule pr; 250126353Smlaier 251126353Smlaier if (*anchorname && !*rulesetname) { 252126353Smlaier struct pfioc_ruleset pr; 253126353Smlaier int mnr, nr, r; 254126353Smlaier 255126353Smlaier memset(&pr, 0, sizeof(pr)); 256126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 257126353Smlaier if (ioctl(dev, DIOCGETRULESETS, &pr)) { 258126353Smlaier if (errno == EINVAL) 259126353Smlaier fprintf(stderr, "No rulesets in anchor '%s'.\n", 260126353Smlaier anchorname); 261126353Smlaier else 262126353Smlaier err(1, "DIOCGETRULESETS"); 263126353Smlaier return (-1); 264126353Smlaier } 265126353Smlaier mnr = pr.nr; 266126353Smlaier for (nr = mnr - 1; nr >= 0; --nr) { 267126353Smlaier pr.nr = nr; 268126353Smlaier if (ioctl(dev, DIOCGETRULESET, &pr)) 269126353Smlaier err(1, "DIOCGETRULESET"); 270126353Smlaier r = pfctl_clear_rules(dev, opts | PF_OPT_QUIET, 271126353Smlaier anchorname, pr.name); 272126353Smlaier if (r) 273126353Smlaier return (r); 274126353Smlaier } 275126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 276126353Smlaier fprintf(stderr, "rules cleared\n"); 277126353Smlaier return (0); 278126353Smlaier } 279126353Smlaier memset(&pr, 0, sizeof(pr)); 280126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 281126353Smlaier memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset)); 282126353Smlaier pr.rule.action = PF_SCRUB; 283126353Smlaier if (ioctl(dev, DIOCBEGINRULES, &pr)) 284126353Smlaier err(1, "DIOCBEGINRULES"); 285126353Smlaier else if (ioctl(dev, DIOCCOMMITRULES, &pr)) 286126353Smlaier err(1, "DIOCCOMMITRULES"); 287126353Smlaier pr.rule.action = PF_PASS; 288126353Smlaier if (ioctl(dev, DIOCBEGINRULES, &pr)) 289126353Smlaier err(1, "DIOCBEGINRULES"); 290126353Smlaier else if (ioctl(dev, DIOCCOMMITRULES, &pr)) 291126353Smlaier err(1, "DIOCCOMMITRULES"); 292126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 293126353Smlaier fprintf(stderr, "rules cleared\n"); 294126353Smlaier return (0); 295126353Smlaier} 296126353Smlaier 297126353Smlaierint 298126353Smlaierpfctl_clear_nat(int dev, int opts, char *anchorname, char *rulesetname) 299126353Smlaier{ 300126353Smlaier struct pfioc_rule pr; 301126353Smlaier 302126353Smlaier if (*anchorname && !*rulesetname) { 303126353Smlaier struct pfioc_ruleset pr; 304126353Smlaier int mnr, nr, r; 305126353Smlaier 306126353Smlaier memset(&pr, 0, sizeof(pr)); 307126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 308126353Smlaier if (ioctl(dev, DIOCGETRULESETS, &pr)) { 309126353Smlaier if (errno == EINVAL) 310126353Smlaier fprintf(stderr, "No rulesets in anchor '%s'.\n", 311126353Smlaier anchorname); 312126353Smlaier else 313126353Smlaier err(1, "DIOCGETRULESETS"); 314126353Smlaier return (-1); 315126353Smlaier } 316126353Smlaier mnr = pr.nr; 317126353Smlaier for (nr = mnr - 1; nr >= 0; --nr) { 318126353Smlaier pr.nr = nr; 319126353Smlaier if (ioctl(dev, DIOCGETRULESET, &pr)) 320126353Smlaier err(1, "DIOCGETRULESET"); 321126353Smlaier r = pfctl_clear_nat(dev, opts | PF_OPT_QUIET, 322126353Smlaier anchorname, pr.name); 323126353Smlaier if (r) 324126353Smlaier return (r); 325126353Smlaier } 326126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 327126353Smlaier fprintf(stderr, "nat cleared\n"); 328126353Smlaier return (0); 329126353Smlaier } 330126353Smlaier memset(&pr, 0, sizeof(pr)); 331126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 332126353Smlaier memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset)); 333126353Smlaier pr.rule.action = PF_NAT; 334126353Smlaier if (ioctl(dev, DIOCBEGINRULES, &pr)) 335126353Smlaier err(1, "DIOCBEGINRULES"); 336126353Smlaier else if (ioctl(dev, DIOCCOMMITRULES, &pr)) 337126353Smlaier err(1, "DIOCCOMMITRULES"); 338126353Smlaier pr.rule.action = PF_BINAT; 339126353Smlaier if (ioctl(dev, DIOCBEGINRULES, &pr)) 340126353Smlaier err(1, "DIOCBEGINRULES"); 341126353Smlaier else if (ioctl(dev, DIOCCOMMITRULES, &pr)) 342126353Smlaier err(1, "DIOCCOMMITRULES"); 343126353Smlaier pr.rule.action = PF_RDR; 344126353Smlaier if (ioctl(dev, DIOCBEGINRULES, &pr)) 345126353Smlaier err(1, "DIOCBEGINRULES"); 346126353Smlaier else if (ioctl(dev, DIOCCOMMITRULES, &pr)) 347126353Smlaier err(1, "DIOCCOMMITRULES"); 348126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 349126353Smlaier fprintf(stderr, "nat cleared\n"); 350126353Smlaier return (0); 351126353Smlaier} 352126353Smlaier 353126353Smlaierint 354126353Smlaierpfctl_clear_altq(int dev, int opts) 355126353Smlaier{ 356126353Smlaier struct pfioc_altq pa; 357126353Smlaier 358126353Smlaier if (!altqsupport) 359126353Smlaier return (-1); 360126353Smlaier memset(&pa, 0, sizeof(pa)); 361126353Smlaier if (ioctl(dev, DIOCBEGINALTQS, &pa.ticket)) 362126353Smlaier err(1, "DIOCBEGINALTQS"); 363126353Smlaier else if (ioctl(dev, DIOCCOMMITALTQS, &pa.ticket)) 364126353Smlaier err(1, "DIOCCOMMITALTQS"); 365126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 366126353Smlaier fprintf(stderr, "altq cleared\n"); 367126353Smlaier return (0); 368126353Smlaier} 369126353Smlaier 370126353Smlaierint 371126353Smlaierpfctl_clear_states(int dev, int opts) 372126353Smlaier{ 373126353Smlaier if (ioctl(dev, DIOCCLRSTATES)) 374126353Smlaier err(1, "DIOCCLRSTATES"); 375126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 376126353Smlaier fprintf(stderr, "states cleared\n"); 377126353Smlaier return (0); 378126353Smlaier} 379126353Smlaier 380126353Smlaierint 381126353Smlaierpfctl_kill_states(int dev, int opts) 382126353Smlaier{ 383126353Smlaier struct pfioc_state_kill psk; 384126353Smlaier struct addrinfo *res[2], *resp[2]; 385126353Smlaier struct sockaddr last_src, last_dst; 386126353Smlaier int killed, sources, dests; 387126353Smlaier int ret_ga; 388126353Smlaier 389126353Smlaier killed = sources = dests = 0; 390126353Smlaier 391126353Smlaier memset(&psk, 0, sizeof(psk)); 392126353Smlaier memset(&psk.psk_src.addr.v.a.mask, 0xff, 393126353Smlaier sizeof(psk.psk_src.addr.v.a.mask)); 394126353Smlaier memset(&last_src, 0xff, sizeof(last_src)); 395126353Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 396126353Smlaier 397126353Smlaier if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) { 398126353Smlaier errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 399126353Smlaier /* NOTREACHED */ 400126353Smlaier } 401126353Smlaier for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 402126353Smlaier if (resp[0]->ai_addr == NULL) 403126353Smlaier continue; 404126353Smlaier /* We get lots of duplicates. Catch the easy ones */ 405126353Smlaier if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 406126353Smlaier continue; 407126353Smlaier last_src = *(struct sockaddr *)resp[0]->ai_addr; 408126353Smlaier 409126353Smlaier psk.psk_af = resp[0]->ai_family; 410126353Smlaier sources++; 411126353Smlaier 412126353Smlaier if (psk.psk_af == AF_INET) 413126353Smlaier psk.psk_src.addr.v.a.addr.v4 = 414126353Smlaier ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 415126353Smlaier else if (psk.psk_af == AF_INET6) 416126353Smlaier psk.psk_src.addr.v.a.addr.v6 = 417126353Smlaier ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 418126353Smlaier sin6_addr; 419126353Smlaier else 420126353Smlaier errx(1, "Unknown address family %d", psk.psk_af); 421126353Smlaier 422126353Smlaier if (state_killers > 1) { 423126353Smlaier dests = 0; 424126353Smlaier memset(&psk.psk_dst.addr.v.a.mask, 0xff, 425126353Smlaier sizeof(psk.psk_dst.addr.v.a.mask)); 426126353Smlaier memset(&last_dst, 0xff, sizeof(last_dst)); 427126353Smlaier if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, 428126353Smlaier &res[1]))) { 429126353Smlaier errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 430126353Smlaier /* NOTREACHED */ 431126353Smlaier } 432126353Smlaier for (resp[1] = res[1]; resp[1]; 433126353Smlaier resp[1] = resp[1]->ai_next) { 434126353Smlaier if (resp[1]->ai_addr == NULL) 435126353Smlaier continue; 436126353Smlaier if (psk.psk_af != resp[1]->ai_family) 437126353Smlaier continue; 438126353Smlaier 439126353Smlaier if (memcmp(&last_dst, resp[1]->ai_addr, 440126353Smlaier sizeof(last_dst)) == 0) 441126353Smlaier continue; 442126353Smlaier last_dst = *(struct sockaddr *)resp[1]->ai_addr; 443126353Smlaier 444126353Smlaier dests++; 445126353Smlaier 446126353Smlaier if (psk.psk_af == AF_INET) 447126353Smlaier psk.psk_dst.addr.v.a.addr.v4 = 448126353Smlaier ((struct sockaddr_in *)resp[1]-> 449126353Smlaier ai_addr)->sin_addr; 450126353Smlaier else if (psk.psk_af == AF_INET6) 451126353Smlaier psk.psk_dst.addr.v.a.addr.v6 = 452126353Smlaier ((struct sockaddr_in6 *)resp[1]-> 453126353Smlaier ai_addr)->sin6_addr; 454126353Smlaier else 455126353Smlaier errx(1, "Unknown address family %d", 456126353Smlaier psk.psk_af); 457126353Smlaier 458126353Smlaier if (ioctl(dev, DIOCKILLSTATES, &psk)) 459126353Smlaier err(1, "DIOCKILLSTATES"); 460126353Smlaier killed += psk.psk_af; 461126353Smlaier /* fixup psk.psk_af */ 462126353Smlaier psk.psk_af = resp[1]->ai_family; 463126353Smlaier } 464126353Smlaier freeaddrinfo(res[1]); 465126353Smlaier } else { 466126353Smlaier if (ioctl(dev, DIOCKILLSTATES, &psk)) 467126353Smlaier err(1, "DIOCKILLSTATES"); 468126353Smlaier killed += psk.psk_af; 469126353Smlaier /* fixup psk.psk_af */ 470126353Smlaier psk.psk_af = res[0]->ai_family; 471126353Smlaier } 472126353Smlaier } 473126353Smlaier 474126353Smlaier freeaddrinfo(res[0]); 475126353Smlaier 476126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 477126353Smlaier fprintf(stderr, "killed %d states from %d sources and %d " 478126353Smlaier "destinations\n", killed, sources, dests); 479126353Smlaier return (0); 480126353Smlaier} 481126353Smlaier 482126353Smlaierint 483126353Smlaierpfctl_get_pool(int dev, struct pf_pool *pool, u_int32_t nr, 484126353Smlaier u_int32_t ticket, int r_action, char *anchorname, char *rulesetname) 485126353Smlaier{ 486126353Smlaier struct pfioc_pooladdr pp; 487126353Smlaier struct pf_pooladdr *pa; 488126353Smlaier u_int32_t pnr, mpnr; 489126353Smlaier 490126353Smlaier memset(&pp, 0, sizeof(pp)); 491126353Smlaier memcpy(pp.anchor, anchorname, sizeof(pp.anchor)); 492126353Smlaier memcpy(pp.ruleset, rulesetname, sizeof(pp.ruleset)); 493126353Smlaier pp.r_action = r_action; 494126353Smlaier pp.r_num = nr; 495126353Smlaier pp.ticket = ticket; 496126353Smlaier if (ioctl(dev, DIOCGETADDRS, &pp)) { 497126353Smlaier warn("DIOCGETADDRS"); 498126353Smlaier return (-1); 499126353Smlaier } 500126353Smlaier mpnr = pp.nr; 501126353Smlaier TAILQ_INIT(&pool->list); 502126353Smlaier for (pnr = 0; pnr < mpnr; ++pnr) { 503126353Smlaier pp.nr = pnr; 504126353Smlaier if (ioctl(dev, DIOCGETADDR, &pp)) { 505126353Smlaier warn("DIOCGETADDR"); 506126353Smlaier return (-1); 507126353Smlaier } 508126353Smlaier pa = calloc(1, sizeof(struct pf_pooladdr)); 509126353Smlaier if (pa == NULL) 510126353Smlaier err(1, "calloc"); 511126353Smlaier bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr)); 512126353Smlaier TAILQ_INSERT_TAIL(&pool->list, pa, entries); 513126353Smlaier } 514126353Smlaier 515126353Smlaier return (0); 516126353Smlaier} 517126353Smlaier 518126353Smlaiervoid 519126353Smlaierpfctl_clear_pool(struct pf_pool *pool) 520126353Smlaier{ 521126353Smlaier struct pf_pooladdr *pa; 522126353Smlaier 523126353Smlaier while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { 524126353Smlaier TAILQ_REMOVE(&pool->list, pa, entries); 525126353Smlaier free(pa); 526126353Smlaier } 527126353Smlaier} 528126353Smlaier 529126353Smlaiervoid 530126353Smlaierpfctl_print_rule_counters(struct pf_rule *rule, int opts) 531126353Smlaier{ 532126353Smlaier if (opts & PF_OPT_DEBUG) { 533126353Smlaier const char *t[PF_SKIP_COUNT] = { "i", "d", "f", 534126353Smlaier "p", "sa", "sp", "da", "dp" }; 535126353Smlaier int i; 536126353Smlaier 537126353Smlaier printf(" [ Skip steps: "); 538126353Smlaier for (i = 0; i < PF_SKIP_COUNT; ++i) { 539126353Smlaier if (rule->skip[i].nr == rule->nr + 1) 540126353Smlaier continue; 541126353Smlaier printf("%s=", t[i]); 542126353Smlaier if (rule->skip[i].nr == -1) 543126353Smlaier printf("end "); 544126353Smlaier else 545126353Smlaier printf("%u ", rule->skip[i].nr); 546126353Smlaier } 547126353Smlaier printf("]\n"); 548126353Smlaier 549126353Smlaier printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 550126353Smlaier rule->qname, rule->qid, rule->pqname, rule->pqid); 551126353Smlaier } 552126353Smlaier if (opts & PF_OPT_VERBOSE) 553127024Smlaier printf(" [ Evaluations: %-8llu Packets: %-8llu " 554127024Smlaier "Bytes: %-10llu States: %-6u]\n", 555127024Smlaier (unsigned long long)rule->evaluations, 556127024Smlaier (unsigned long long)rule->packets, 557127024Smlaier (unsigned long long)rule->bytes, rule->states); 558126353Smlaier} 559126353Smlaier 560126353Smlaierint 561126353Smlaierpfctl_show_rules(int dev, int opts, int format, char *anchorname, 562126353Smlaier char *rulesetname) 563126353Smlaier{ 564126353Smlaier struct pfioc_rule pr; 565126353Smlaier u_int32_t nr, mnr; 566126353Smlaier int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); 567126353Smlaier 568126353Smlaier if (*anchorname && !*rulesetname) { 569126353Smlaier struct pfioc_ruleset pr; 570126353Smlaier int r; 571126353Smlaier 572126353Smlaier memset(&pr, 0, sizeof(pr)); 573126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 574126353Smlaier if (ioctl(dev, DIOCGETRULESETS, &pr)) { 575126353Smlaier if (errno == EINVAL) 576126353Smlaier fprintf(stderr, "No rulesets in anchor '%s'.\n", 577126353Smlaier anchorname); 578126353Smlaier else 579126353Smlaier err(1, "DIOCGETRULESETS"); 580126353Smlaier return (-1); 581126353Smlaier } 582126353Smlaier mnr = pr.nr; 583126353Smlaier for (nr = 0; nr < mnr; ++nr) { 584126353Smlaier pr.nr = nr; 585126353Smlaier if (ioctl(dev, DIOCGETRULESET, &pr)) 586126353Smlaier err(1, "DIOCGETRULESET"); 587126353Smlaier r = pfctl_show_rules(dev, opts, format, anchorname, 588126353Smlaier pr.name); 589126353Smlaier if (r) 590126353Smlaier return (r); 591126353Smlaier } 592126353Smlaier return (0); 593126353Smlaier } 594126353Smlaier 595126353Smlaier memset(&pr, 0, sizeof(pr)); 596126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 597126353Smlaier memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset)); 598126353Smlaier pr.rule.action = PF_SCRUB; 599126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 600126353Smlaier warn("DIOCGETRULES"); 601126353Smlaier return (-1); 602126353Smlaier } 603126353Smlaier mnr = pr.nr; 604126353Smlaier for (nr = 0; nr < mnr; ++nr) { 605126353Smlaier pr.nr = nr; 606126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 607126353Smlaier warn("DIOCGETRULE"); 608126353Smlaier return (-1); 609126353Smlaier } 610126353Smlaier 611126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, 612126353Smlaier nr, pr.ticket, PF_SCRUB, anchorname, rulesetname) != 0) 613126353Smlaier return (-1); 614126353Smlaier 615126353Smlaier switch (format) { 616126353Smlaier case 1: 617126353Smlaier if (pr.rule.label[0]) { 618126353Smlaier printf("%s ", pr.rule.label); 619127024Smlaier printf("%llu %llu %llu\n", 620127024Smlaier (unsigned long long)pr.rule.evaluations, 621127024Smlaier (unsigned long long)pr.rule.packets, 622127024Smlaier (unsigned long long)pr.rule.bytes); 623126353Smlaier } 624126353Smlaier break; 625126353Smlaier default: 626126353Smlaier print_rule(&pr.rule, rule_numbers); 627126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 628126353Smlaier } 629126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 630126353Smlaier } 631126353Smlaier pr.rule.action = PF_PASS; 632126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 633126353Smlaier warn("DIOCGETRULES"); 634126353Smlaier return (-1); 635126353Smlaier } 636126353Smlaier mnr = pr.nr; 637126353Smlaier for (nr = 0; nr < mnr; ++nr) { 638126353Smlaier pr.nr = nr; 639126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 640126353Smlaier warn("DIOCGETRULE"); 641126353Smlaier return (-1); 642126353Smlaier } 643126353Smlaier 644126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, 645126353Smlaier nr, pr.ticket, PF_PASS, anchorname, rulesetname) != 0) 646126353Smlaier return (-1); 647126353Smlaier 648126353Smlaier switch (format) { 649126353Smlaier case 1: 650126353Smlaier if (pr.rule.label[0]) { 651126353Smlaier printf("%s ", pr.rule.label); 652127024Smlaier printf("%llu %llu %llu\n", 653127024Smlaier (unsigned long long)pr.rule.evaluations, 654127024Smlaier (unsigned long long)pr.rule.packets, 655127024Smlaier (unsigned long long)pr.rule.bytes); 656126353Smlaier } 657126353Smlaier break; 658126353Smlaier default: 659126353Smlaier print_rule(&pr.rule, rule_numbers); 660126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 661126353Smlaier } 662126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 663126353Smlaier } 664126353Smlaier return (0); 665126353Smlaier} 666126353Smlaier 667126353Smlaierint 668126353Smlaierpfctl_show_nat(int dev, int opts, char *anchorname, char *rulesetname) 669126353Smlaier{ 670126353Smlaier struct pfioc_rule pr; 671126353Smlaier u_int32_t mnr, nr; 672126353Smlaier static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; 673126353Smlaier int i; 674126353Smlaier 675126353Smlaier if (*anchorname && !*rulesetname) { 676126353Smlaier struct pfioc_ruleset pr; 677126353Smlaier int r; 678126353Smlaier 679126353Smlaier memset(&pr, 0, sizeof(pr)); 680126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 681126353Smlaier if (ioctl(dev, DIOCGETRULESETS, &pr)) { 682126353Smlaier if (errno == EINVAL) 683126353Smlaier fprintf(stderr, "No rulesets in anchor '%s'.\n", 684126353Smlaier anchorname); 685126353Smlaier else 686126353Smlaier err(1, "DIOCGETRULESETS"); 687126353Smlaier return (-1); 688126353Smlaier } 689126353Smlaier mnr = pr.nr; 690126353Smlaier for (nr = 0; nr < mnr; ++nr) { 691126353Smlaier pr.nr = nr; 692126353Smlaier if (ioctl(dev, DIOCGETRULESET, &pr)) 693126353Smlaier err(1, "DIOCGETRULESET"); 694126353Smlaier r = pfctl_show_nat(dev, opts, anchorname, pr.name); 695126353Smlaier if (r) 696126353Smlaier return (r); 697126353Smlaier } 698126353Smlaier return (0); 699126353Smlaier } 700126353Smlaier 701126353Smlaier memset(&pr, 0, sizeof(pr)); 702126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 703126353Smlaier memcpy(pr.ruleset, rulesetname, sizeof(pr.ruleset)); 704126353Smlaier for (i = 0; i < 3; i++) { 705126353Smlaier pr.rule.action = nattype[i]; 706126353Smlaier if (ioctl(dev, DIOCGETRULES, &pr)) { 707126353Smlaier warn("DIOCGETRULES"); 708126353Smlaier return (-1); 709126353Smlaier } 710126353Smlaier mnr = pr.nr; 711126353Smlaier for (nr = 0; nr < mnr; ++nr) { 712126353Smlaier pr.nr = nr; 713126353Smlaier if (ioctl(dev, DIOCGETRULE, &pr)) { 714126353Smlaier warn("DIOCGETRULE"); 715126353Smlaier return (-1); 716126353Smlaier } 717126353Smlaier if (pfctl_get_pool(dev, &pr.rule.rpool, nr, 718126353Smlaier pr.ticket, nattype[i], anchorname, 719126353Smlaier rulesetname) != 0) 720126353Smlaier return (-1); 721126353Smlaier print_rule(&pr.rule, opts & PF_OPT_VERBOSE2); 722126353Smlaier pfctl_print_rule_counters(&pr.rule, opts); 723126353Smlaier pfctl_clear_pool(&pr.rule.rpool); 724126353Smlaier } 725126353Smlaier } 726126353Smlaier return (0); 727126353Smlaier} 728126353Smlaier 729126353Smlaierint 730126353Smlaierpfctl_show_states(int dev, u_int8_t proto, int opts) 731126353Smlaier{ 732126353Smlaier struct pfioc_states ps; 733126353Smlaier struct pf_state *p; 734126353Smlaier char *inbuf = NULL; 735126353Smlaier unsigned len = 0; 736126353Smlaier int i; 737126353Smlaier 738126353Smlaier memset(&ps, 0, sizeof(ps)); 739126353Smlaier for (;;) { 740126353Smlaier ps.ps_len = len; 741126353Smlaier if (len) { 742126353Smlaier ps.ps_buf = inbuf = realloc(inbuf, len); 743126353Smlaier if (inbuf == NULL) 744126353Smlaier err(1, "realloc"); 745126353Smlaier } 746126353Smlaier if (ioctl(dev, DIOCGETSTATES, &ps) < 0) { 747126353Smlaier warn("DIOCGETSTATES"); 748126353Smlaier return (-1); 749126353Smlaier } 750126353Smlaier if (ps.ps_len + sizeof(struct pfioc_states) < len) 751126353Smlaier break; 752126353Smlaier if (len == 0 && ps.ps_len == 0) 753126353Smlaier return (0); 754126353Smlaier if (len == 0 && ps.ps_len != 0) 755126353Smlaier len = ps.ps_len; 756126353Smlaier if (ps.ps_len == 0) 757126353Smlaier return (0); /* no states */ 758126353Smlaier len *= 2; 759126353Smlaier } 760126353Smlaier p = ps.ps_states; 761126353Smlaier for (i = 0; i < ps.ps_len; i += sizeof(*p)) { 762126353Smlaier if (!proto || (p->proto == proto)) 763126353Smlaier print_state(p, opts); 764126353Smlaier p++; 765126353Smlaier } 766126353Smlaier return (0); 767126353Smlaier} 768126353Smlaier 769126353Smlaierint 770126353Smlaierpfctl_show_status(int dev) 771126353Smlaier{ 772126353Smlaier struct pf_status status; 773126353Smlaier 774126353Smlaier if (ioctl(dev, DIOCGETSTATUS, &status)) { 775126353Smlaier warn("DIOCGETSTATUS"); 776126353Smlaier return (-1); 777126353Smlaier } 778126353Smlaier print_status(&status); 779126353Smlaier return (0); 780126353Smlaier} 781126353Smlaier 782126353Smlaierint 783126353Smlaierpfctl_show_timeouts(int dev) 784126353Smlaier{ 785126353Smlaier struct pfioc_tm pt; 786126353Smlaier int i; 787126353Smlaier 788126353Smlaier memset(&pt, 0, sizeof(pt)); 789126353Smlaier for (i = 0; pf_timeouts[i].name; i++) { 790126353Smlaier pt.timeout = pf_timeouts[i].timeout; 791126353Smlaier if (ioctl(dev, DIOCGETTIMEOUT, &pt)) 792126353Smlaier err(1, "DIOCGETTIMEOUT"); 793126353Smlaier printf("%-20s %10d", pf_timeouts[i].name, pt.seconds); 794126353Smlaier if (i >= PFTM_ADAPTIVE_START && i <= PFTM_ADAPTIVE_END) 795126353Smlaier printf(" states"); 796126353Smlaier else 797126353Smlaier printf("s"); 798126353Smlaier printf("\n"); 799126353Smlaier } 800126353Smlaier return (0); 801126353Smlaier 802126353Smlaier} 803126353Smlaier 804126353Smlaierint 805126353Smlaierpfctl_show_limits(int dev) 806126353Smlaier{ 807126353Smlaier struct pfioc_limit pl; 808126353Smlaier int i; 809126353Smlaier 810126353Smlaier memset(&pl, 0, sizeof(pl)); 811126353Smlaier for (i = 0; pf_limits[i].name; i++) { 812126353Smlaier pl.index = i; 813126353Smlaier if (ioctl(dev, DIOCGETLIMIT, &pl)) 814126353Smlaier err(1, "DIOCGETLIMIT"); 815126353Smlaier printf("%-10s ", pf_limits[i].name); 816126353Smlaier if (pl.limit == UINT_MAX) 817126353Smlaier printf("unlimited\n"); 818126353Smlaier else 819126353Smlaier printf("hard limit %6u\n", pl.limit); 820126353Smlaier } 821126353Smlaier return (0); 822126353Smlaier} 823126353Smlaier 824126353Smlaier/* callbacks for rule/nat/rdr/addr */ 825126353Smlaierint 826126353Smlaierpfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af) 827126353Smlaier{ 828126353Smlaier struct pf_pooladdr *pa; 829126353Smlaier 830126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 831126353Smlaier if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) 832126353Smlaier err(1, "DIOCBEGINADDRS"); 833126353Smlaier } 834126353Smlaier 835126353Smlaier pf->paddr.af = af; 836126353Smlaier TAILQ_FOREACH(pa, &p->list, entries) { 837126353Smlaier memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); 838126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 839126353Smlaier if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) 840126353Smlaier err(1, "DIOCADDADDR"); 841126353Smlaier } 842126353Smlaier } 843126353Smlaier return (0); 844126353Smlaier} 845126353Smlaier 846126353Smlaierint 847126353Smlaierpfctl_add_rule(struct pfctl *pf, struct pf_rule *r) 848126353Smlaier{ 849126353Smlaier u_int8_t rs_num; 850126353Smlaier 851126353Smlaier switch (r->action) { 852126353Smlaier case PF_SCRUB: 853126353Smlaier if ((loadopt & PFCTL_FLAG_FILTER) == 0) 854126353Smlaier return (0); 855126353Smlaier rs_num = PF_RULESET_SCRUB; 856126353Smlaier break; 857126353Smlaier case PF_DROP: 858126353Smlaier case PF_PASS: 859126353Smlaier if ((loadopt & PFCTL_FLAG_FILTER) == 0) 860126353Smlaier return (0); 861126353Smlaier rs_num = PF_RULESET_FILTER; 862126353Smlaier break; 863126353Smlaier case PF_NAT: 864126353Smlaier case PF_NONAT: 865126353Smlaier if ((loadopt & PFCTL_FLAG_NAT) == 0) 866126353Smlaier return (0); 867126353Smlaier rs_num = PF_RULESET_NAT; 868126353Smlaier break; 869126353Smlaier case PF_RDR: 870126353Smlaier case PF_NORDR: 871126353Smlaier if ((loadopt & PFCTL_FLAG_NAT) == 0) 872126353Smlaier return (0); 873126353Smlaier rs_num = PF_RULESET_RDR; 874126353Smlaier break; 875126353Smlaier case PF_BINAT: 876126353Smlaier case PF_NOBINAT: 877126353Smlaier if ((loadopt & PFCTL_FLAG_NAT) == 0) 878126353Smlaier return (0); 879126353Smlaier rs_num = PF_RULESET_BINAT; 880126353Smlaier break; 881126353Smlaier default: 882126353Smlaier errx(1, "Invalid rule type"); 883126353Smlaier break; 884126353Smlaier } 885126353Smlaier 886126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 887126353Smlaier if (pfctl_add_pool(pf, &r->rpool, r->af)) 888126353Smlaier return (1); 889126353Smlaier memcpy(&pf->prule[rs_num]->rule, r, 890126353Smlaier sizeof(pf->prule[rs_num]->rule)); 891126353Smlaier pf->prule[rs_num]->pool_ticket = pf->paddr.ticket; 892126353Smlaier if (ioctl(pf->dev, DIOCADDRULE, pf->prule[rs_num])) 893126353Smlaier err(1, "DIOCADDRULE"); 894126353Smlaier } 895126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 896126353Smlaier print_rule(r, pf->opts & PF_OPT_VERBOSE2); 897126353Smlaier pfctl_clear_pool(&r->rpool); 898126353Smlaier return (0); 899126353Smlaier} 900126353Smlaier 901126353Smlaierint 902126353Smlaierpfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 903126353Smlaier{ 904126353Smlaier if (altqsupport && 905126353Smlaier (loadopt & PFCTL_FLAG_ALTQ) != 0) { 906126353Smlaier memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq)); 907126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 908126353Smlaier if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) { 909126353Smlaier if (errno == ENXIO) 910126353Smlaier errx(1, "qtype not configured"); 911126353Smlaier else if (errno == ENODEV) 912126353Smlaier errx(1, "%s: driver does not support " 913126353Smlaier "altq", a->ifname); 914126353Smlaier else 915126353Smlaier err(1, "DIOCADDALTQ"); 916126353Smlaier } 917126353Smlaier } 918126353Smlaier pfaltq_store(&pf->paltq->altq); 919126353Smlaier } 920126353Smlaier return (0); 921126353Smlaier} 922126353Smlaier 923126353Smlaierint 924126353Smlaierpfctl_rules(int dev, char *filename, int opts, char *anchorname, 925126353Smlaier char *rulesetname) 926126353Smlaier{ 927126353Smlaier#define ERR(x) do { warn(x); goto _error; } while(0) 928126353Smlaier#define ERRX(x) do { warnx(x); goto _error; } while(0) 929126353Smlaier 930126353Smlaier FILE *fin; 931126353Smlaier struct pfioc_rule pr[PF_RULESET_MAX]; 932126353Smlaier struct pfioc_altq pa; 933126353Smlaier struct pfctl pf; 934126353Smlaier struct pfr_table trs; 935126353Smlaier int i; 936126353Smlaier 937126353Smlaier memset(&pa, 0, sizeof(pa)); 938126353Smlaier memset(&pf, 0, sizeof(pf)); 939126353Smlaier memset(&trs, 0, sizeof(trs)); 940126353Smlaier for (i = 0; i < PF_RULESET_MAX; i++) { 941126353Smlaier memset(&pr[i], 0, sizeof(pr[i])); 942126353Smlaier memcpy(pr[i].anchor, anchorname, sizeof(pr[i].anchor)); 943126353Smlaier memcpy(pr[i].ruleset, rulesetname, sizeof(pr[i].ruleset)); 944126353Smlaier } 945126353Smlaier if (strlcpy(trs.pfrt_anchor, anchorname, 946126353Smlaier sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor) || 947126353Smlaier strlcpy(trs.pfrt_ruleset, rulesetname, 948126353Smlaier sizeof(trs.pfrt_ruleset)) >= sizeof(trs.pfrt_ruleset)) 949126353Smlaier ERRX("pfctl_rules: strlcpy"); 950126353Smlaier if (strcmp(filename, "-") == 0) { 951126353Smlaier fin = stdin; 952126353Smlaier infile = "stdin"; 953126353Smlaier } else { 954126353Smlaier if ((fin = fopen(filename, "r")) == NULL) { 955126353Smlaier warn("%s", filename); 956126353Smlaier return (1); 957126353Smlaier } 958126353Smlaier infile = filename; 959126353Smlaier } 960126353Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 961126353Smlaier if ((loadopt & PFCTL_FLAG_NAT) != 0) { 962126353Smlaier pr[PF_RULESET_NAT].rule.action = PF_NAT; 963126353Smlaier if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_NAT])) 964126353Smlaier ERR("DIOCBEGINRULES"); 965126353Smlaier pr[PF_RULESET_RDR].rule.action = PF_RDR; 966126353Smlaier if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_RDR])) 967126353Smlaier ERR("DIOCBEGINRULES"); 968126353Smlaier pr[PF_RULESET_BINAT].rule.action = PF_BINAT; 969126353Smlaier if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_BINAT])) 970126353Smlaier ERR("DIOCBEGINRULES"); 971126353Smlaier } 972126353Smlaier if (((altqsupport && (loadopt & PFCTL_FLAG_ALTQ) != 0)) && 973126353Smlaier ioctl(dev, DIOCBEGINALTQS, &pa.ticket)) { 974126353Smlaier ERR("DIOCBEGINALTQS"); 975126353Smlaier } 976126353Smlaier if ((loadopt & PFCTL_FLAG_FILTER) != 0) { 977126353Smlaier pr[PF_RULESET_SCRUB].rule.action = PF_SCRUB; 978126353Smlaier if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_SCRUB])) 979126353Smlaier ERR("DIOCBEGINRULES"); 980126353Smlaier pr[PF_RULESET_FILTER].rule.action = PF_PASS; 981126353Smlaier if (ioctl(dev, DIOCBEGINRULES, &pr[PF_RULESET_FILTER])) 982126353Smlaier ERR("DIOCBEGINRULES"); 983126353Smlaier } 984126353Smlaier if (loadopt & PFCTL_FLAG_TABLE) { 985126353Smlaier if (pfr_ina_begin(&trs, &pf.tticket, NULL, 0) != 0) 986126353Smlaier ERR("begin table"); 987126353Smlaier } 988126353Smlaier } 989126353Smlaier /* fill in callback data */ 990126353Smlaier pf.dev = dev; 991126353Smlaier pf.opts = opts; 992126353Smlaier pf.loadopt = loadopt; 993126353Smlaier pf.paltq = &pa; 994126353Smlaier for (i = 0; i < PF_RULESET_MAX; i++) { 995126353Smlaier pf.prule[i] = &pr[i]; 996126353Smlaier } 997126353Smlaier pf.rule_nr = 0; 998126353Smlaier pf.anchor = anchorname; 999126353Smlaier pf.ruleset = rulesetname; 1000126353Smlaier if (parse_rules(fin, &pf) < 0) { 1001126353Smlaier if ((opts & PF_OPT_NOACTION) == 0) 1002126353Smlaier ERRX("Syntax error in config file: " 1003126353Smlaier "pf rules not loaded"); 1004126353Smlaier else 1005126353Smlaier goto _error; 1006126353Smlaier } 1007126353Smlaier if ((altqsupport && (loadopt & PFCTL_FLAG_ALTQ) != 0)) 1008126353Smlaier if (check_commit_altq(dev, opts) != 0) 1009126353Smlaier ERRX("errors in altq config"); 1010126353Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 1011126353Smlaier if ((loadopt & PFCTL_FLAG_NAT) != 0) { 1012126353Smlaier pr[PF_RULESET_NAT].rule.action = PF_NAT; 1013126353Smlaier if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_NAT]) && 1014126353Smlaier (errno != EINVAL || pf.rule_nr)) 1015126353Smlaier ERR("DIOCCOMMITRULES NAT"); 1016126353Smlaier pr[PF_RULESET_RDR].rule.action = PF_RDR; 1017126353Smlaier if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_RDR]) && 1018126353Smlaier (errno != EINVAL || pf.rule_nr)) 1019126353Smlaier ERR("DIOCCOMMITRULES RDR"); 1020126353Smlaier pr[PF_RULESET_BINAT].rule.action = PF_BINAT; 1021126353Smlaier if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_BINAT]) && 1022126353Smlaier (errno != EINVAL || pf.rule_nr)) 1023126353Smlaier ERR("DIOCCOMMITRULES BINAT"); 1024126353Smlaier } 1025126353Smlaier if (((altqsupport && (loadopt & PFCTL_FLAG_ALTQ) != 0)) && 1026126353Smlaier ioctl(dev, DIOCCOMMITALTQS, &pa.ticket)) 1027126353Smlaier ERR("DIOCCOMMITALTQS"); 1028126353Smlaier if ((loadopt & PFCTL_FLAG_FILTER) != 0) { 1029126353Smlaier pr[PF_RULESET_SCRUB].rule.action = PF_SCRUB; 1030126353Smlaier if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_SCRUB]) && 1031126353Smlaier (errno != EINVAL || pf.rule_nr)) 1032126353Smlaier ERR("DIOCCOMMITRULES SCRUB"); 1033126353Smlaier pr[PF_RULESET_FILTER].rule.action = PF_PASS; 1034126353Smlaier if (ioctl(dev, DIOCCOMMITRULES, &pr[PF_RULESET_FILTER]) && 1035126353Smlaier (errno != EINVAL || pf.rule_nr)) 1036126353Smlaier ERR("DIOCCOMMITRULES FILTER"); 1037126353Smlaier } 1038126353Smlaier if (loadopt & PFCTL_FLAG_TABLE) { 1039126353Smlaier if (pfr_ina_commit(&trs, pf.tticket, NULL, NULL, 0)) 1040126353Smlaier ERR("commit table"); 1041126353Smlaier pf.tdirty = 0; 1042126353Smlaier } 1043126353Smlaier } 1044126353Smlaier if (fin != stdin) 1045126353Smlaier fclose(fin); 1046126353Smlaier 1047126353Smlaier /* process "load anchor" directives */ 1048126353Smlaier if (!anchorname[0] && !rulesetname[0]) 1049126353Smlaier if (pfctl_load_anchors(dev, opts) == -1) 1050126353Smlaier ERRX("load anchors"); 1051126353Smlaier 1052126353Smlaier return (0); 1053126353Smlaier 1054126353Smlaier_error: 1055126353Smlaier if (pf.tdirty) /* cleanup kernel leftover */ 1056126353Smlaier pfr_ina_begin(&trs, NULL, NULL, 0); 1057126353Smlaier exit(1); 1058126353Smlaier 1059126353Smlaier#undef ERR 1060126353Smlaier#undef ERRX 1061126353Smlaier} 1062126353Smlaier 1063126353Smlaierint 1064126353Smlaierpfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 1065126353Smlaier{ 1066126353Smlaier struct pfioc_limit pl; 1067126353Smlaier int i; 1068126353Smlaier 1069126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1070126353Smlaier return (0); 1071126353Smlaier 1072126353Smlaier memset(&pl, 0, sizeof(pl)); 1073126353Smlaier for (i = 0; pf_limits[i].name; i++) { 1074126353Smlaier if (strcasecmp(opt, pf_limits[i].name) == 0) { 1075126353Smlaier pl.index = i; 1076126353Smlaier pl.limit = limit; 1077126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1078126353Smlaier if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) { 1079126353Smlaier if (errno == EBUSY) { 1080126353Smlaier warnx("Current pool " 1081126353Smlaier "size exceeds requested " 1082126353Smlaier "hard limit"); 1083126353Smlaier return (1); 1084126353Smlaier } else 1085126353Smlaier err(1, "DIOCSETLIMIT"); 1086126353Smlaier } 1087126353Smlaier } 1088126353Smlaier break; 1089126353Smlaier } 1090126353Smlaier } 1091126353Smlaier if (pf_limits[i].name == NULL) { 1092126353Smlaier warnx("Bad pool name."); 1093126353Smlaier return (1); 1094126353Smlaier } 1095126353Smlaier 1096126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1097126353Smlaier printf("set limit %s %d\n", opt, limit); 1098126353Smlaier 1099126353Smlaier return (0); 1100126353Smlaier} 1101126353Smlaier 1102126353Smlaierint 1103126353Smlaierpfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 1104126353Smlaier{ 1105126353Smlaier struct pfioc_tm pt; 1106126353Smlaier int i; 1107126353Smlaier 1108126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1109126353Smlaier return (0); 1110126353Smlaier 1111126353Smlaier memset(&pt, 0, sizeof(pt)); 1112126353Smlaier for (i = 0; pf_timeouts[i].name; i++) { 1113126353Smlaier if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 1114126353Smlaier pt.timeout = pf_timeouts[i].timeout; 1115126353Smlaier break; 1116126353Smlaier } 1117126353Smlaier } 1118126353Smlaier 1119126353Smlaier if (pf_timeouts[i].name == NULL) { 1120126353Smlaier warnx("Bad timeout name."); 1121126353Smlaier return (1); 1122126353Smlaier } 1123126353Smlaier 1124126353Smlaier pt.seconds = seconds; 1125126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1126126353Smlaier if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) 1127126353Smlaier err(1, "DIOCSETTIMEOUT"); 1128126353Smlaier } 1129126353Smlaier 1130126353Smlaier if (pf->opts & PF_OPT_VERBOSE && ! quiet) 1131126353Smlaier printf("set timeout %s %d\n", opt, seconds); 1132126353Smlaier 1133126353Smlaier return (0); 1134126353Smlaier} 1135126353Smlaier 1136126353Smlaierint 1137126353Smlaierpfctl_set_optimization(struct pfctl *pf, const char *opt) 1138126353Smlaier{ 1139126353Smlaier const struct pf_hint *hint; 1140126353Smlaier int i, r; 1141126353Smlaier 1142126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1143126353Smlaier return (0); 1144126353Smlaier 1145126353Smlaier for (i = 0; pf_hints[i].name; i++) 1146126353Smlaier if (strcasecmp(opt, pf_hints[i].name) == 0) 1147126353Smlaier break; 1148126353Smlaier 1149126353Smlaier hint = pf_hints[i].hint; 1150126353Smlaier if (hint == NULL) { 1151126353Smlaier warnx("Bad hint name."); 1152126353Smlaier return (1); 1153126353Smlaier } 1154126353Smlaier 1155126353Smlaier for (i = 0; hint[i].name; i++) 1156126353Smlaier if ((r = pfctl_set_timeout(pf, hint[i].name, 1157126353Smlaier hint[i].timeout, 1))) 1158126353Smlaier return (r); 1159126353Smlaier 1160126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1161126353Smlaier printf("set optimization %s\n", opt); 1162126353Smlaier 1163126353Smlaier return (0); 1164126353Smlaier} 1165126353Smlaier 1166126353Smlaierint 1167126353Smlaierpfctl_set_logif(struct pfctl *pf, char *ifname) 1168126353Smlaier{ 1169126353Smlaier struct pfioc_if pi; 1170126353Smlaier 1171126353Smlaier if ((loadopt & PFCTL_FLAG_OPTION) == 0) 1172126353Smlaier return (0); 1173126353Smlaier 1174126353Smlaier memset(&pi, 0, sizeof(pi)); 1175126353Smlaier if ((pf->opts & PF_OPT_NOACTION) == 0) { 1176126353Smlaier if (!strcmp(ifname, "none")) 1177126353Smlaier bzero(pi.ifname, sizeof(pi.ifname)); 1178126353Smlaier else { 1179126353Smlaier if (strlcpy(pi.ifname, ifname, 1180126353Smlaier sizeof(pi.ifname)) >= sizeof(pi.ifname)) 1181126353Smlaier errx(1, "pfctl_set_logif: strlcpy"); 1182126353Smlaier } 1183126353Smlaier if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) 1184126353Smlaier err(1, "DIOCSETSTATUSIF"); 1185126353Smlaier } 1186126353Smlaier 1187126353Smlaier if (pf->opts & PF_OPT_VERBOSE) 1188126353Smlaier printf("set loginterface %s\n", ifname); 1189126353Smlaier 1190126353Smlaier return (0); 1191126353Smlaier} 1192126353Smlaier 1193126353Smlaierint 1194126353Smlaierpfctl_debug(int dev, u_int32_t level, int opts) 1195126353Smlaier{ 1196126353Smlaier if (ioctl(dev, DIOCSETDEBUG, &level)) 1197126353Smlaier err(1, "DIOCSETDEBUG"); 1198126353Smlaier if ((opts & PF_OPT_QUIET) == 0) { 1199126353Smlaier fprintf(stderr, "debug level set to '"); 1200126353Smlaier switch (level) { 1201126353Smlaier case PF_DEBUG_NONE: 1202126353Smlaier fprintf(stderr, "none"); 1203126353Smlaier break; 1204126353Smlaier case PF_DEBUG_URGENT: 1205126353Smlaier fprintf(stderr, "urgent"); 1206126353Smlaier break; 1207126353Smlaier case PF_DEBUG_MISC: 1208126353Smlaier fprintf(stderr, "misc"); 1209126353Smlaier break; 1210126353Smlaier case PF_DEBUG_NOISY: 1211126353Smlaier fprintf(stderr, "loud"); 1212126353Smlaier break; 1213126353Smlaier default: 1214126353Smlaier fprintf(stderr, "<invalid>"); 1215126353Smlaier break; 1216126353Smlaier } 1217126353Smlaier fprintf(stderr, "'\n"); 1218126353Smlaier } 1219126353Smlaier return (0); 1220126353Smlaier} 1221126353Smlaier 1222126353Smlaierint 1223126353Smlaierpfctl_clear_rule_counters(int dev, int opts) 1224126353Smlaier{ 1225126353Smlaier if (ioctl(dev, DIOCCLRRULECTRS)) 1226126353Smlaier err(1, "DIOCCLRRULECTRS"); 1227126353Smlaier if ((opts & PF_OPT_QUIET) == 0) 1228126353Smlaier fprintf(stderr, "pf: rule counters cleared\n"); 1229126353Smlaier return (0); 1230126353Smlaier} 1231126353Smlaier 1232126353Smlaierint 1233126353Smlaierpfctl_test_altqsupport(int dev, int opts) 1234126353Smlaier{ 1235126355Smlaier#if defined(__FreeBSD__) && !defined(ENABLE_ALTQ) 1236126355Smlaier return (0); 1237126355Smlaier#else 1238126353Smlaier struct pfioc_altq pa; 1239126353Smlaier 1240126353Smlaier if (ioctl(dev, DIOCGETALTQS, &pa)) { 1241126353Smlaier if (errno == ENODEV) { 1242126353Smlaier if (!(opts & PF_OPT_QUIET)) 1243126353Smlaier fprintf(stderr, "No ALTQ support in kernel\n" 1244126353Smlaier "ALTQ related functions disabled\n"); 1245126353Smlaier return (0); 1246126353Smlaier } else 1247126353Smlaier err(1, "DIOCGETALTQS"); 1248126353Smlaier } 1249126353Smlaier return (1); 1250126355Smlaier#endif 1251126353Smlaier} 1252126353Smlaier 1253126353Smlaierint 1254126353Smlaierpfctl_show_anchors(int dev, int opts, char *anchorname) 1255126353Smlaier{ 1256126353Smlaier u_int32_t nr, mnr; 1257126353Smlaier 1258126353Smlaier if (!*anchorname) { 1259126353Smlaier struct pfioc_anchor pa; 1260126353Smlaier 1261126353Smlaier memset(&pa, 0, sizeof(pa)); 1262126353Smlaier if (ioctl(dev, DIOCGETANCHORS, &pa)) { 1263126353Smlaier warn("DIOCGETANCHORS"); 1264126353Smlaier return (-1); 1265126353Smlaier } 1266126353Smlaier mnr = pa.nr; 1267126353Smlaier if (!(opts & PF_OPT_QUIET)) 1268126353Smlaier printf("%u anchors:\n", mnr); 1269126353Smlaier for (nr = 0; nr < mnr; ++nr) { 1270126353Smlaier pa.nr = nr; 1271126353Smlaier if (ioctl(dev, DIOCGETANCHOR, &pa)) { 1272126353Smlaier warn("DIOCGETANCHOR"); 1273126353Smlaier return (-1); 1274126353Smlaier } 1275126353Smlaier printf(" %s\n", pa.name); 1276126353Smlaier } 1277126353Smlaier } else { 1278126353Smlaier struct pfioc_ruleset pr; 1279126353Smlaier 1280126353Smlaier memset(&pr, 0, sizeof(pr)); 1281126353Smlaier memcpy(pr.anchor, anchorname, sizeof(pr.anchor)); 1282126353Smlaier if (ioctl(dev, DIOCGETRULESETS, &pr)) { 1283126353Smlaier if (errno == EINVAL) 1284126353Smlaier fprintf(stderr, "No rulesets in anchor '%s'.\n", 1285126353Smlaier anchorname); 1286126353Smlaier else 1287126353Smlaier err(1, "DIOCGETRULESETS"); 1288126353Smlaier return (-1); 1289126353Smlaier } 1290126353Smlaier mnr = pr.nr; 1291126353Smlaier if (!(opts & PF_OPT_QUIET)) 1292126353Smlaier printf("%u rulesets in anchor %s:\n", mnr, anchorname); 1293126353Smlaier for (nr = 0; nr < mnr; ++nr) { 1294126353Smlaier pr.nr = nr; 1295126353Smlaier if (ioctl(dev, DIOCGETRULESET, &pr)) 1296126353Smlaier err(1, "DIOCGETRULESET"); 1297126353Smlaier printf(" %s:%s\n", pr.anchor, pr.name); 1298126353Smlaier } 1299126353Smlaier } 1300126353Smlaier return (0); 1301126353Smlaier} 1302126353Smlaier 1303126353Smlaierconst char * 1304126353Smlaierpfctl_lookup_option(char *cmd, const char **list) 1305126353Smlaier{ 1306126353Smlaier if (cmd != NULL && *cmd) 1307126353Smlaier for (; *list; list++) 1308126353Smlaier if (!strncmp(cmd, *list, strlen(cmd))) 1309126353Smlaier return (*list); 1310126353Smlaier return (NULL); 1311126353Smlaier} 1312126353Smlaier 1313126353Smlaierint 1314126353Smlaiermain(int argc, char *argv[]) 1315126353Smlaier{ 1316126353Smlaier int error = 0; 1317126353Smlaier int ch; 1318126353Smlaier int mode = O_RDONLY; 1319126353Smlaier int opts = 0; 1320126353Smlaier char anchorname[PF_ANCHOR_NAME_SIZE]; 1321126353Smlaier char rulesetname[PF_RULESET_NAME_SIZE]; 1322126353Smlaier 1323126353Smlaier if (argc < 2) 1324126353Smlaier usage(); 1325126353Smlaier 1326126353Smlaier while ((ch = getopt(argc, argv, "a:AdD:eqf:F:ghk:nNOrRs:t:T:vx:z")) != 1327126353Smlaier -1) { 1328126353Smlaier switch (ch) { 1329126353Smlaier case 'a': 1330126353Smlaier anchoropt = optarg; 1331126353Smlaier break; 1332126353Smlaier case 'd': 1333126353Smlaier opts |= PF_OPT_DISABLE; 1334126353Smlaier mode = O_RDWR; 1335126353Smlaier break; 1336126353Smlaier case 'D': 1337126353Smlaier if (pfctl_cmdline_symset(optarg) < 0) 1338126353Smlaier warnx("could not parse macro definition %s", 1339126353Smlaier optarg); 1340126353Smlaier break; 1341126353Smlaier case 'e': 1342126353Smlaier opts |= PF_OPT_ENABLE; 1343126353Smlaier mode = O_RDWR; 1344126353Smlaier break; 1345126353Smlaier case 'q': 1346126353Smlaier opts |= PF_OPT_QUIET; 1347126353Smlaier break; 1348126353Smlaier case 'F': 1349126353Smlaier clearopt = pfctl_lookup_option(optarg, clearopt_list); 1350126353Smlaier if (clearopt == NULL) { 1351126353Smlaier warnx("Unknown flush modifier '%s'", optarg); 1352126353Smlaier usage(); 1353126353Smlaier } 1354126353Smlaier mode = O_RDWR; 1355126353Smlaier break; 1356126353Smlaier case 'k': 1357126353Smlaier if (state_killers >= 2) { 1358126353Smlaier warnx("can only specify -k twice"); 1359126353Smlaier usage(); 1360126353Smlaier /* NOTREACHED */ 1361126353Smlaier } 1362126353Smlaier state_kill[state_killers++] = optarg; 1363126353Smlaier mode = O_RDWR; 1364126353Smlaier break; 1365126353Smlaier case 'n': 1366126353Smlaier opts |= PF_OPT_NOACTION; 1367126353Smlaier break; 1368126353Smlaier case 'N': 1369126353Smlaier loadopt |= PFCTL_FLAG_NAT; 1370126353Smlaier break; 1371126353Smlaier case 'r': 1372126353Smlaier opts |= PF_OPT_USEDNS; 1373126353Smlaier break; 1374126353Smlaier case 'f': 1375126353Smlaier rulesopt = optarg; 1376126353Smlaier mode = O_RDWR; 1377126353Smlaier break; 1378126353Smlaier case 'g': 1379126353Smlaier opts |= PF_OPT_DEBUG; 1380126353Smlaier break; 1381126353Smlaier case 'A': 1382126353Smlaier loadopt |= PFCTL_FLAG_ALTQ; 1383126353Smlaier break; 1384126353Smlaier case 'R': 1385126353Smlaier loadopt |= PFCTL_FLAG_FILTER; 1386126353Smlaier break; 1387126353Smlaier case 'O': 1388126353Smlaier loadopt |= PFCTL_FLAG_OPTION; 1389126353Smlaier break; 1390126353Smlaier case 's': 1391126353Smlaier showopt = pfctl_lookup_option(optarg, showopt_list); 1392126353Smlaier if (showopt == NULL) { 1393126353Smlaier warnx("Unknown show modifier '%s'", optarg); 1394126353Smlaier usage(); 1395126353Smlaier } 1396126353Smlaier break; 1397126353Smlaier case 't': 1398126353Smlaier tableopt = optarg; 1399126353Smlaier break; 1400126353Smlaier case 'T': 1401126353Smlaier tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 1402126353Smlaier if (tblcmdopt == NULL) { 1403126353Smlaier warnx("Unknown table command '%s'", optarg); 1404126353Smlaier usage(); 1405126353Smlaier } 1406126353Smlaier break; 1407126353Smlaier case 'v': 1408126353Smlaier if (opts & PF_OPT_VERBOSE) 1409126353Smlaier opts |= PF_OPT_VERBOSE2; 1410126353Smlaier opts |= PF_OPT_VERBOSE; 1411126353Smlaier break; 1412126353Smlaier case 'x': 1413126353Smlaier debugopt = pfctl_lookup_option(optarg, debugopt_list); 1414126353Smlaier if (debugopt == NULL) { 1415126353Smlaier warnx("Unknown debug level '%s'", optarg); 1416126353Smlaier usage(); 1417126353Smlaier } 1418126353Smlaier mode = O_RDWR; 1419126353Smlaier break; 1420126353Smlaier case 'z': 1421126353Smlaier opts |= PF_OPT_CLRRULECTRS; 1422126353Smlaier mode = O_RDWR; 1423126353Smlaier break; 1424126353Smlaier case 'h': 1425126353Smlaier /* FALLTHROUGH */ 1426126353Smlaier default: 1427126353Smlaier usage(); 1428126353Smlaier /* NOTREACHED */ 1429126353Smlaier } 1430126353Smlaier } 1431126353Smlaier 1432126353Smlaier if (tblcmdopt != NULL) { 1433126353Smlaier argc -= optind; 1434126353Smlaier argv += optind; 1435126353Smlaier ch = *tblcmdopt; 1436126353Smlaier if (ch == 'l') { 1437126353Smlaier loadopt |= PFCTL_FLAG_TABLE; 1438126353Smlaier tblcmdopt = NULL; 1439126353Smlaier } else { 1440126353Smlaier mode = strchr("acdfkrz", ch) ? O_RDWR : O_RDONLY; 1441126353Smlaier if (opts & PF_OPT_NOACTION) { 1442126353Smlaier dev = open("/dev/pf", mode); 1443126353Smlaier if (dev >= 0) 1444126353Smlaier opts |= PF_OPT_DUMMYACTION; 1445126353Smlaier } 1446126353Smlaier } 1447126353Smlaier } else if (argc != optind) { 1448126353Smlaier warnx("unknown command line argument: %s ...", argv[optind]); 1449126353Smlaier usage(); 1450126353Smlaier /* NOTREACHED */ 1451126353Smlaier } 1452126353Smlaier if (loadopt == 0) 1453126353Smlaier loadopt = ~0; 1454126353Smlaier 1455126353Smlaier memset(anchorname, 0, sizeof(anchorname)); 1456126353Smlaier memset(rulesetname, 0, sizeof(rulesetname)); 1457126353Smlaier if (anchoropt != NULL) { 1458126353Smlaier char *t; 1459126353Smlaier 1460126353Smlaier if ((t = strchr(anchoropt, ':')) == NULL) { 1461126353Smlaier if (strlcpy(anchorname, anchoropt, 1462126353Smlaier sizeof(anchorname)) >= sizeof(anchorname)) 1463126353Smlaier errx(1, "anchor name '%s' too long", 1464126353Smlaier anchoropt); 1465126353Smlaier } else { 1466126353Smlaier char *p; 1467126353Smlaier 1468126353Smlaier if ((p = strdup(anchoropt)) == NULL) 1469126353Smlaier err(1, "anchoropt: strdup"); 1470126353Smlaier t = strsep(&p, ":"); 1471126353Smlaier if (*t == '\0' || *p == '\0') 1472126353Smlaier errx(1, "anchor '%s' invalid", anchoropt); 1473126353Smlaier if (strlcpy(anchorname, t, sizeof(anchorname)) >= 1474126353Smlaier sizeof(anchorname)) 1475126353Smlaier errx(1, "anchor name '%s' too long", t); 1476126353Smlaier if (strlcpy(rulesetname, p, sizeof(rulesetname)) >= 1477126353Smlaier sizeof(rulesetname)) 1478126353Smlaier errx(1, "ruleset name '%s' too long", p); 1479126353Smlaier free(t); /* not p */ 1480126353Smlaier } 1481126353Smlaier loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE; 1482126353Smlaier } 1483126353Smlaier 1484126353Smlaier if ((opts & PF_OPT_NOACTION) == 0) { 1485126353Smlaier dev = open("/dev/pf", mode); 1486126353Smlaier if (dev == -1) 1487126353Smlaier err(1, "/dev/pf"); 1488126353Smlaier altqsupport = pfctl_test_altqsupport(dev, opts); 1489126353Smlaier } else { 1490126353Smlaier /* turn off options */ 1491126353Smlaier opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 1492126353Smlaier clearopt = showopt = debugopt = NULL; 1493126355Smlaier#if defined(__FreeBSD__) && !defined(ENABLE_ALTQ) 1494126355Smlaier altqsupport = 0; 1495126355Smlaier#else 1496126353Smlaier altqsupport = 1; 1497126355Smlaier#endif 1498126353Smlaier } 1499126353Smlaier 1500126353Smlaier if (opts & PF_OPT_DISABLE) 1501126353Smlaier if (pfctl_disable(dev, opts)) 1502126353Smlaier error = 1; 1503126353Smlaier 1504126353Smlaier if (showopt != NULL) { 1505126353Smlaier switch (*showopt) { 1506126353Smlaier case 'A': 1507126353Smlaier pfctl_show_anchors(dev, opts, anchorname); 1508126353Smlaier break; 1509126353Smlaier case 'r': 1510126353Smlaier pfctl_load_fingerprints(dev, opts); 1511126353Smlaier pfctl_show_rules(dev, opts, 0, anchorname, 1512126353Smlaier rulesetname); 1513126353Smlaier break; 1514126353Smlaier case 'l': 1515126353Smlaier pfctl_load_fingerprints(dev, opts); 1516126353Smlaier pfctl_show_rules(dev, opts, 1, anchorname, 1517126353Smlaier rulesetname); 1518126353Smlaier break; 1519126353Smlaier case 'n': 1520126353Smlaier pfctl_load_fingerprints(dev, opts); 1521126353Smlaier pfctl_show_nat(dev, opts, anchorname, rulesetname); 1522126353Smlaier break; 1523126353Smlaier case 'q': 1524126353Smlaier pfctl_show_altq(dev, opts, opts & PF_OPT_VERBOSE2); 1525126353Smlaier break; 1526126353Smlaier case 's': 1527126353Smlaier pfctl_show_states(dev, 0, opts); 1528126353Smlaier break; 1529126353Smlaier case 'i': 1530126353Smlaier pfctl_show_status(dev); 1531126353Smlaier break; 1532126353Smlaier case 't': 1533126353Smlaier pfctl_show_timeouts(dev); 1534126353Smlaier break; 1535126353Smlaier case 'm': 1536126353Smlaier pfctl_show_limits(dev); 1537126353Smlaier break; 1538126353Smlaier case 'a': 1539126353Smlaier pfctl_load_fingerprints(dev, opts); 1540126353Smlaier 1541126353Smlaier pfctl_show_rules(dev, opts, 0, anchorname, 1542126353Smlaier rulesetname); 1543126353Smlaier pfctl_show_nat(dev, opts, anchorname, rulesetname); 1544126353Smlaier pfctl_show_altq(dev, opts, 0); 1545126353Smlaier pfctl_show_states(dev, 0, opts); 1546126353Smlaier pfctl_show_status(dev); 1547126353Smlaier pfctl_show_rules(dev, opts, 1, anchorname, rulesetname); 1548126353Smlaier pfctl_show_timeouts(dev); 1549126353Smlaier pfctl_show_limits(dev); 1550126353Smlaier pfctl_show_tables(anchorname, rulesetname, opts); 1551126353Smlaier pfctl_show_fingerprints(opts); 1552126353Smlaier break; 1553126353Smlaier case 'T': 1554126353Smlaier pfctl_show_tables(anchorname, rulesetname, opts); 1555126353Smlaier break; 1556126353Smlaier case 'o': 1557126353Smlaier pfctl_load_fingerprints(dev, opts); 1558126353Smlaier pfctl_show_fingerprints(opts); 1559126353Smlaier break; 1560126353Smlaier } 1561126353Smlaier } 1562126353Smlaier 1563126353Smlaier if (clearopt != NULL) { 1564126353Smlaier switch (*clearopt) { 1565126353Smlaier case 'r': 1566126353Smlaier pfctl_clear_rules(dev, opts, anchorname, rulesetname); 1567126353Smlaier break; 1568126353Smlaier case 'n': 1569126353Smlaier pfctl_clear_nat(dev, opts, anchorname, rulesetname); 1570126353Smlaier break; 1571126353Smlaier case 'q': 1572126353Smlaier pfctl_clear_altq(dev, opts); 1573126353Smlaier break; 1574126353Smlaier case 's': 1575126353Smlaier pfctl_clear_states(dev, opts); 1576126353Smlaier break; 1577126353Smlaier case 'i': 1578126353Smlaier pfctl_clear_stats(dev, opts); 1579126353Smlaier break; 1580126353Smlaier case 'a': 1581126353Smlaier pfctl_clear_rules(dev, opts, anchorname, rulesetname); 1582126353Smlaier pfctl_clear_nat(dev, opts, anchorname, rulesetname); 1583126353Smlaier pfctl_clear_altq(dev, opts); 1584126353Smlaier pfctl_clear_states(dev, opts); 1585126353Smlaier pfctl_clear_stats(dev, opts); 1586126353Smlaier pfctl_clear_tables(anchorname, rulesetname, opts); 1587126353Smlaier pfctl_clear_fingerprints(dev, opts); 1588126353Smlaier break; 1589126353Smlaier case 'o': 1590126353Smlaier pfctl_clear_fingerprints(dev, opts); 1591126353Smlaier break; 1592126353Smlaier case 'T': 1593126353Smlaier pfctl_clear_tables(anchorname, rulesetname, opts); 1594126353Smlaier break; 1595126353Smlaier } 1596126353Smlaier } 1597126353Smlaier if (state_killers) 1598126353Smlaier pfctl_kill_states(dev, opts); 1599126353Smlaier 1600126353Smlaier if (tblcmdopt != NULL) { 1601126353Smlaier error = pfctl_command_tables(argc, argv, tableopt, 1602126353Smlaier tblcmdopt, rulesopt, anchorname, rulesetname, opts); 1603126353Smlaier rulesopt = NULL; 1604126353Smlaier } 1605126353Smlaier 1606126353Smlaier if (rulesopt != NULL) 1607126353Smlaier if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 1608126353Smlaier error = 1; 1609126353Smlaier 1610126353Smlaier if (rulesopt != NULL) { 1611126353Smlaier if (pfctl_rules(dev, rulesopt, opts, anchorname, rulesetname)) 1612126353Smlaier error = 1; 1613126353Smlaier else if (!(opts & PF_OPT_NOACTION) && 1614126353Smlaier (loadopt & PFCTL_FLAG_TABLE)) 1615126353Smlaier warn_namespace_collision(NULL); 1616126353Smlaier } 1617126353Smlaier 1618126353Smlaier if (opts & PF_OPT_ENABLE) 1619126353Smlaier if (pfctl_enable(dev, opts)) 1620126353Smlaier error = 1; 1621126353Smlaier 1622126353Smlaier if (debugopt != NULL) { 1623126353Smlaier switch (*debugopt) { 1624126353Smlaier case 'n': 1625126353Smlaier pfctl_debug(dev, PF_DEBUG_NONE, opts); 1626126353Smlaier break; 1627126353Smlaier case 'u': 1628126353Smlaier pfctl_debug(dev, PF_DEBUG_URGENT, opts); 1629126353Smlaier break; 1630126353Smlaier case 'm': 1631126353Smlaier pfctl_debug(dev, PF_DEBUG_MISC, opts); 1632126353Smlaier break; 1633126353Smlaier case 'l': 1634126353Smlaier pfctl_debug(dev, PF_DEBUG_NOISY, opts); 1635126353Smlaier break; 1636126353Smlaier } 1637126353Smlaier } 1638126353Smlaier 1639126353Smlaier if (opts & PF_OPT_CLRRULECTRS) { 1640126353Smlaier if (pfctl_clear_rule_counters(dev, opts)) 1641126353Smlaier error = 1; 1642126353Smlaier } 1643126353Smlaier exit(error); 1644126353Smlaier} 1645