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