13b3a8eb9SGleb Smirnoff /* $OpenBSD: pfctl.c,v 1.278 2008/08/31 20:18:17 jmc Exp $ */ 23b3a8eb9SGleb Smirnoff 31de7b4b8SPedro F. Giffuni /*- 41de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause 51de7b4b8SPedro F. Giffuni * 63b3a8eb9SGleb Smirnoff * Copyright (c) 2001 Daniel Hartmeier 73b3a8eb9SGleb Smirnoff * Copyright (c) 2002,2003 Henning Brauer 83b3a8eb9SGleb Smirnoff * All rights reserved. 93b3a8eb9SGleb Smirnoff * 103b3a8eb9SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 113b3a8eb9SGleb Smirnoff * modification, are permitted provided that the following conditions 123b3a8eb9SGleb Smirnoff * are met: 133b3a8eb9SGleb Smirnoff * 143b3a8eb9SGleb Smirnoff * - Redistributions of source code must retain the above copyright 153b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 163b3a8eb9SGleb Smirnoff * - Redistributions in binary form must reproduce the above 173b3a8eb9SGleb Smirnoff * copyright notice, this list of conditions and the following 183b3a8eb9SGleb Smirnoff * disclaimer in the documentation and/or other materials provided 193b3a8eb9SGleb Smirnoff * with the distribution. 203b3a8eb9SGleb Smirnoff * 213b3a8eb9SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 223b3a8eb9SGleb Smirnoff * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 233b3a8eb9SGleb Smirnoff * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 243b3a8eb9SGleb Smirnoff * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 253b3a8eb9SGleb Smirnoff * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 263b3a8eb9SGleb Smirnoff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 273b3a8eb9SGleb Smirnoff * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 283b3a8eb9SGleb Smirnoff * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 293b3a8eb9SGleb Smirnoff * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 303b3a8eb9SGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 313b3a8eb9SGleb Smirnoff * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 323b3a8eb9SGleb Smirnoff * POSSIBILITY OF SUCH DAMAGE. 333b3a8eb9SGleb Smirnoff * 343b3a8eb9SGleb Smirnoff */ 353b3a8eb9SGleb Smirnoff 363b3a8eb9SGleb Smirnoff #include <sys/cdefs.h> 37249cc75fSPatrick Kelsey #define PFIOC_USE_LATEST 38249cc75fSPatrick Kelsey 393b3a8eb9SGleb Smirnoff #include <sys/types.h> 403b3a8eb9SGleb Smirnoff #include <sys/ioctl.h> 413b3a8eb9SGleb Smirnoff #include <sys/socket.h> 423b3a8eb9SGleb Smirnoff #include <sys/stat.h> 433b3a8eb9SGleb Smirnoff #include <sys/endian.h> 443b3a8eb9SGleb Smirnoff 453b3a8eb9SGleb Smirnoff #include <net/if.h> 463b3a8eb9SGleb Smirnoff #include <netinet/in.h> 473b3a8eb9SGleb Smirnoff #include <net/pfvar.h> 483b3a8eb9SGleb Smirnoff #include <arpa/inet.h> 49772e66a6SGleb Smirnoff #include <net/altq/altq.h> 503b3a8eb9SGleb Smirnoff 513b3a8eb9SGleb Smirnoff #include <err.h> 523b3a8eb9SGleb Smirnoff #include <errno.h> 533b3a8eb9SGleb Smirnoff #include <fcntl.h> 540d71f9f3SKristof Provost #include <libpfctl.h> 553b3a8eb9SGleb Smirnoff #include <limits.h> 563b3a8eb9SGleb Smirnoff #include <netdb.h> 575a9ab487SGleb Smirnoff #include <stdint.h> 583b3a8eb9SGleb Smirnoff #include <stdio.h> 593b3a8eb9SGleb Smirnoff #include <stdlib.h> 603b3a8eb9SGleb Smirnoff #include <string.h> 613b3a8eb9SGleb Smirnoff #include <unistd.h> 623b3a8eb9SGleb Smirnoff 633b3a8eb9SGleb Smirnoff #include "pfctl_parser.h" 643b3a8eb9SGleb Smirnoff #include "pfctl.h" 653b3a8eb9SGleb Smirnoff 663b3a8eb9SGleb Smirnoff void usage(void); 673b3a8eb9SGleb Smirnoff int pfctl_enable(int, int); 683b3a8eb9SGleb Smirnoff int pfctl_disable(int, int); 699dbbe68bSKristof Provost int pfctl_clear_stats(struct pfctl_handle *, int); 70c5e10565SKristof Provost int pfctl_get_skip_ifaces(void); 71c5e10565SKristof Provost int pfctl_check_skip_ifaces(char *); 727a831fecSKristof Provost int pfctl_adjust_skip_ifaces(struct pfctl *); 733b3a8eb9SGleb Smirnoff int pfctl_clear_interface_flags(int, int); 74f0c334e4SKristof Provost int pfctl_flush_eth_rules(int, int, char *); 75f0c334e4SKristof Provost int pfctl_flush_rules(int, int, char *); 76f0c334e4SKristof Provost int pfctl_flush_nat(int, int, char *); 773b3a8eb9SGleb Smirnoff int pfctl_clear_altq(int, int); 783b3a8eb9SGleb Smirnoff int pfctl_clear_src_nodes(int, int); 7953714a58SKristof Provost int pfctl_clear_iface_states(int, const char *, int); 803b3a8eb9SGleb Smirnoff void pfctl_addrprefix(char *, struct pf_addr *); 813b3a8eb9SGleb Smirnoff int pfctl_kill_src_nodes(int, const char *, int); 823b3a8eb9SGleb Smirnoff int pfctl_net_kill_states(int, const char *, int); 83abbcba9cSKristof Provost int pfctl_gateway_kill_states(int, const char *, int); 843b3a8eb9SGleb Smirnoff int pfctl_label_kill_states(int, const char *, int); 853b3a8eb9SGleb Smirnoff int pfctl_id_kill_states(int, const char *, int); 863b3a8eb9SGleb Smirnoff void pfctl_init_options(struct pfctl *); 873b3a8eb9SGleb Smirnoff int pfctl_load_options(struct pfctl *); 883b3a8eb9SGleb Smirnoff int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int); 893b3a8eb9SGleb Smirnoff int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int); 903b3a8eb9SGleb Smirnoff int pfctl_load_debug(struct pfctl *, unsigned int); 913b3a8eb9SGleb Smirnoff int pfctl_load_logif(struct pfctl *, char *); 929a5e33beSKristof Provost int pfctl_load_hostid(struct pfctl *, u_int32_t); 9339282ef3SKajetan Staszkiewicz int pfctl_load_reassembly(struct pfctl *, u_int32_t); 94c69121c4SKristof Provost int pfctl_load_syncookies(struct pfctl *, u_int8_t); 95600bd6ceSKurosawa Takahiro int pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int, 96aa69fdf1SKristof Provost char *, int); 972b29ceb8SKristof Provost void pfctl_print_eth_rule_counters(struct pfctl_eth_rule *, int); 98e9eb0941SKristof Provost void pfctl_print_rule_counters(struct pfctl_rule *, int); 99cfa1a130SKristof Provost int pfctl_show_eth_rules(int, char *, int, enum pfctl_show, char *, int, int); 100585a5ed0SKristof Provost int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int); 1018ddd0359SKristof Provost int pfctl_show_nat(int, char *, int, char *, int, int); 1023b3a8eb9SGleb Smirnoff int pfctl_show_src_nodes(int, int); 1033b3a8eb9SGleb Smirnoff int pfctl_show_states(int, const char *, int); 1043b3a8eb9SGleb Smirnoff int pfctl_show_status(int, int); 105fa1d4439SKristof Provost int pfctl_show_running(int); 1063b3a8eb9SGleb Smirnoff int pfctl_show_timeouts(int, int); 1073b3a8eb9SGleb Smirnoff int pfctl_show_limits(int, int); 1083b3a8eb9SGleb Smirnoff void pfctl_debug(int, u_int32_t, int); 1093b3a8eb9SGleb Smirnoff int pfctl_test_altqsupport(int, int); 1103b3a8eb9SGleb Smirnoff int pfctl_show_anchors(int, int, char *); 1119bb06778SKristof Provost int pfctl_show_eth_anchors(int, int, char *); 112c5131afeSKristof Provost int pfctl_ruleset_trans(struct pfctl *, char *, struct pfctl_anchor *, bool); 113c5131afeSKristof Provost int pfctl_eth_ruleset_trans(struct pfctl *, char *, 114c5131afeSKristof Provost struct pfctl_eth_anchor *); 115c5131afeSKristof Provost int pfctl_load_eth_ruleset(struct pfctl *, char *, 116c5131afeSKristof Provost struct pfctl_eth_ruleset *, int); 117c5131afeSKristof Provost int pfctl_load_eth_rule(struct pfctl *, char *, struct pfctl_eth_rule *, 118c5131afeSKristof Provost int); 1193b3a8eb9SGleb Smirnoff int pfctl_load_ruleset(struct pfctl *, char *, 120e9eb0941SKristof Provost struct pfctl_ruleset *, int, int); 121e9eb0941SKristof Provost int pfctl_load_rule(struct pfctl *, char *, struct pfctl_rule *, int); 12272a3cf0fSKristof Provost const char *pfctl_lookup_option(char *, const char * const *); 1233b3a8eb9SGleb Smirnoff 124e9eb0941SKristof Provost static struct pfctl_anchor_global pf_anchors; 125c5131afeSKristof Provost struct pfctl_anchor pf_main_anchor; 126c5131afeSKristof Provost struct pfctl_eth_anchor pf_eth_main_anchor; 127c5e10565SKristof Provost static struct pfr_buffer skip_b; 1283b3a8eb9SGleb Smirnoff 12913cfafabSKristof Provost static const char *clearopt; 13013cfafabSKristof Provost static char *rulesopt; 13113cfafabSKristof Provost static const char *showopt; 13213cfafabSKristof Provost static const char *debugopt; 13313cfafabSKristof Provost static char *anchoropt; 13413cfafabSKristof Provost static const char *optiopt = NULL; 13566cacc14SKristof Provost static const char *pf_device = PF_DEVICE; 13613cfafabSKristof Provost static char *ifaceopt; 13713cfafabSKristof Provost static char *tableopt; 13813cfafabSKristof Provost static const char *tblcmdopt; 13913cfafabSKristof Provost static int src_node_killers; 14013cfafabSKristof Provost static char *src_node_kill[2]; 14113cfafabSKristof Provost static int state_killers; 14213cfafabSKristof Provost static char *state_kill[2]; 1433b3a8eb9SGleb Smirnoff int loadopt; 1443b3a8eb9SGleb Smirnoff int altqsupport; 1453b3a8eb9SGleb Smirnoff 1463b3a8eb9SGleb Smirnoff int dev = -1; 14766cacc14SKristof Provost struct pfctl_handle *pfh = NULL; 14813cfafabSKristof Provost static int first_title = 1; 14913cfafabSKristof Provost static int labels = 0; 1503b3a8eb9SGleb Smirnoff 1513b3a8eb9SGleb Smirnoff #define INDENT(d, o) do { \ 1523b3a8eb9SGleb Smirnoff if (o) { \ 1533b3a8eb9SGleb Smirnoff int i; \ 1543b3a8eb9SGleb Smirnoff for (i=0; i < d; i++) \ 1553b3a8eb9SGleb Smirnoff printf(" "); \ 1563b3a8eb9SGleb Smirnoff } \ 1573b3a8eb9SGleb Smirnoff } while (0); \ 1583b3a8eb9SGleb Smirnoff 1593b3a8eb9SGleb Smirnoff 1603b3a8eb9SGleb Smirnoff static const struct { 1613b3a8eb9SGleb Smirnoff const char *name; 1623b3a8eb9SGleb Smirnoff int index; 1633b3a8eb9SGleb Smirnoff } pf_limits[] = { 1643b3a8eb9SGleb Smirnoff { "states", PF_LIMIT_STATES }, 1653b3a8eb9SGleb Smirnoff { "src-nodes", PF_LIMIT_SRC_NODES }, 1663b3a8eb9SGleb Smirnoff { "frags", PF_LIMIT_FRAGS }, 1673b3a8eb9SGleb Smirnoff { "table-entries", PF_LIMIT_TABLE_ENTRIES }, 1683b3a8eb9SGleb Smirnoff { NULL, 0 } 1693b3a8eb9SGleb Smirnoff }; 1703b3a8eb9SGleb Smirnoff 1713b3a8eb9SGleb Smirnoff struct pf_hint { 1723b3a8eb9SGleb Smirnoff const char *name; 1733b3a8eb9SGleb Smirnoff int timeout; 1743b3a8eb9SGleb Smirnoff }; 1753b3a8eb9SGleb Smirnoff static const struct pf_hint pf_hint_normal[] = { 1763b3a8eb9SGleb Smirnoff { "tcp.first", 2 * 60 }, 1773b3a8eb9SGleb Smirnoff { "tcp.opening", 30 }, 1783b3a8eb9SGleb Smirnoff { "tcp.established", 24 * 60 * 60 }, 1793b3a8eb9SGleb Smirnoff { "tcp.closing", 15 * 60 }, 1803b3a8eb9SGleb Smirnoff { "tcp.finwait", 45 }, 1813b3a8eb9SGleb Smirnoff { "tcp.closed", 90 }, 1823b3a8eb9SGleb Smirnoff { "tcp.tsdiff", 30 }, 1833b3a8eb9SGleb Smirnoff { NULL, 0 } 1843b3a8eb9SGleb Smirnoff }; 1853b3a8eb9SGleb Smirnoff static const struct pf_hint pf_hint_satellite[] = { 1863b3a8eb9SGleb Smirnoff { "tcp.first", 3 * 60 }, 1873b3a8eb9SGleb Smirnoff { "tcp.opening", 30 + 5 }, 1883b3a8eb9SGleb Smirnoff { "tcp.established", 24 * 60 * 60 }, 1893b3a8eb9SGleb Smirnoff { "tcp.closing", 15 * 60 + 5 }, 1903b3a8eb9SGleb Smirnoff { "tcp.finwait", 45 + 5 }, 1913b3a8eb9SGleb Smirnoff { "tcp.closed", 90 + 5 }, 1923b3a8eb9SGleb Smirnoff { "tcp.tsdiff", 60 }, 1933b3a8eb9SGleb Smirnoff { NULL, 0 } 1943b3a8eb9SGleb Smirnoff }; 1953b3a8eb9SGleb Smirnoff static const struct pf_hint pf_hint_conservative[] = { 1963b3a8eb9SGleb Smirnoff { "tcp.first", 60 * 60 }, 1973b3a8eb9SGleb Smirnoff { "tcp.opening", 15 * 60 }, 1983b3a8eb9SGleb Smirnoff { "tcp.established", 5 * 24 * 60 * 60 }, 1993b3a8eb9SGleb Smirnoff { "tcp.closing", 60 * 60 }, 2003b3a8eb9SGleb Smirnoff { "tcp.finwait", 10 * 60 }, 2013b3a8eb9SGleb Smirnoff { "tcp.closed", 3 * 60 }, 2023b3a8eb9SGleb Smirnoff { "tcp.tsdiff", 60 }, 2033b3a8eb9SGleb Smirnoff { NULL, 0 } 2043b3a8eb9SGleb Smirnoff }; 2053b3a8eb9SGleb Smirnoff static const struct pf_hint pf_hint_aggressive[] = { 2063b3a8eb9SGleb Smirnoff { "tcp.first", 30 }, 2073b3a8eb9SGleb Smirnoff { "tcp.opening", 5 }, 2083b3a8eb9SGleb Smirnoff { "tcp.established", 5 * 60 * 60 }, 2093b3a8eb9SGleb Smirnoff { "tcp.closing", 60 }, 2103b3a8eb9SGleb Smirnoff { "tcp.finwait", 30 }, 2113b3a8eb9SGleb Smirnoff { "tcp.closed", 30 }, 2123b3a8eb9SGleb Smirnoff { "tcp.tsdiff", 10 }, 2133b3a8eb9SGleb Smirnoff { NULL, 0 } 2143b3a8eb9SGleb Smirnoff }; 2153b3a8eb9SGleb Smirnoff 2163b3a8eb9SGleb Smirnoff static const struct { 2173b3a8eb9SGleb Smirnoff const char *name; 2183b3a8eb9SGleb Smirnoff const struct pf_hint *hint; 2193b3a8eb9SGleb Smirnoff } pf_hints[] = { 2203b3a8eb9SGleb Smirnoff { "normal", pf_hint_normal }, 2213b3a8eb9SGleb Smirnoff { "satellite", pf_hint_satellite }, 2223b3a8eb9SGleb Smirnoff { "high-latency", pf_hint_satellite }, 2233b3a8eb9SGleb Smirnoff { "conservative", pf_hint_conservative }, 2243b3a8eb9SGleb Smirnoff { "aggressive", pf_hint_aggressive }, 2253b3a8eb9SGleb Smirnoff { NULL, NULL } 2263b3a8eb9SGleb Smirnoff }; 2273b3a8eb9SGleb Smirnoff 22872a3cf0fSKristof Provost static const char * const clearopt_list[] = { 2293b3a8eb9SGleb Smirnoff "nat", "queue", "rules", "Sources", 2306ea1c3cfSKristof Provost "states", "info", "Tables", "osfp", "all", 2316ea1c3cfSKristof Provost "ethernet", NULL 2323b3a8eb9SGleb Smirnoff }; 2333b3a8eb9SGleb Smirnoff 23472a3cf0fSKristof Provost static const char * const showopt_list[] = { 2352b29ceb8SKristof Provost "ether", "nat", "queue", "rules", "Anchors", "Sources", "states", 2362b29ceb8SKristof Provost "info", "Interfaces", "labels", "timeouts", "memory", "Tables", 237a7191e5dSKristof Provost "osfp", "Running", "all", "creatorids", NULL 2383b3a8eb9SGleb Smirnoff }; 2393b3a8eb9SGleb Smirnoff 24072a3cf0fSKristof Provost static const char * const tblcmdopt_list[] = { 2413b3a8eb9SGleb Smirnoff "kill", "flush", "add", "delete", "load", "replace", "show", 2425b59b0c6SLeonid Evdokimov "test", "zero", "expire", "reset", NULL 2433b3a8eb9SGleb Smirnoff }; 2443b3a8eb9SGleb Smirnoff 24572a3cf0fSKristof Provost static const char * const debugopt_list[] = { 2463b3a8eb9SGleb Smirnoff "none", "urgent", "misc", "loud", NULL 2473b3a8eb9SGleb Smirnoff }; 2483b3a8eb9SGleb Smirnoff 24972a3cf0fSKristof Provost static const char * const optiopt_list[] = { 2503b3a8eb9SGleb Smirnoff "none", "basic", "profile", NULL 2513b3a8eb9SGleb Smirnoff }; 2523b3a8eb9SGleb Smirnoff 2533b3a8eb9SGleb Smirnoff void 2543b3a8eb9SGleb Smirnoff usage(void) 2553b3a8eb9SGleb Smirnoff { 2563b3a8eb9SGleb Smirnoff extern char *__progname; 2573b3a8eb9SGleb Smirnoff 2580c46447bSGleb Smirnoff fprintf(stderr, 25993abcf17SKristof Provost "usage: %s [-AdeghMmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n" 2600c46447bSGleb Smirnoff "\t[-f file] [-i interface] [-K host | network]\n" 261abbcba9cSKristof Provost "\t[-k host | network | gateway | label | id] [-o level] [-p device]\n" 2620c46447bSGleb Smirnoff "\t[-s modifier] [-t table -T command [address ...]] [-x level]\n", 2630c46447bSGleb Smirnoff __progname); 2640c46447bSGleb Smirnoff 2653b3a8eb9SGleb Smirnoff exit(1); 2663b3a8eb9SGleb Smirnoff } 2673b3a8eb9SGleb Smirnoff 268858937beSMateusz Guzik /* 269858937beSMateusz Guzik * Cache protocol number to name translations. 270858937beSMateusz Guzik * 271858937beSMateusz Guzik * Translation is performed a lot e.g., when dumping states and 272858937beSMateusz Guzik * getprotobynumber is incredibly expensive. 273858937beSMateusz Guzik * 274858937beSMateusz Guzik * Note from the getprotobynumber(3) manpage: 275858937beSMateusz Guzik * <quote> 276858937beSMateusz Guzik * These functions use a thread-specific data space; if the data is needed 277858937beSMateusz Guzik * for future use, it should be copied before any subsequent calls overwrite 278858937beSMateusz Guzik * it. Only the Internet protocols are currently understood. 279858937beSMateusz Guzik * </quote> 280858937beSMateusz Guzik * 281858937beSMateusz Guzik * Consequently we only cache the name and strdup it for safety. 282858937beSMateusz Guzik * 283858937beSMateusz Guzik * At the time of writing this comment the last entry in /etc/protocols is: 284858937beSMateusz Guzik * divert 258 DIVERT # Divert pseudo-protocol [non IANA] 285858937beSMateusz Guzik */ 286858937beSMateusz Guzik const char * 287858937beSMateusz Guzik pfctl_proto2name(int proto) 288858937beSMateusz Guzik { 289858937beSMateusz Guzik static const char *pfctl_proto_cache[259]; 290858937beSMateusz Guzik struct protoent *p; 291858937beSMateusz Guzik 292858937beSMateusz Guzik if (proto >= nitems(pfctl_proto_cache)) { 293858937beSMateusz Guzik p = getprotobynumber(proto); 294858937beSMateusz Guzik if (p == NULL) { 295858937beSMateusz Guzik return (NULL); 296858937beSMateusz Guzik } 297858937beSMateusz Guzik return (p->p_name); 298858937beSMateusz Guzik } 299858937beSMateusz Guzik 300858937beSMateusz Guzik if (pfctl_proto_cache[proto] == NULL) { 301858937beSMateusz Guzik p = getprotobynumber(proto); 302858937beSMateusz Guzik if (p == NULL) { 303858937beSMateusz Guzik return (NULL); 304858937beSMateusz Guzik } 305858937beSMateusz Guzik pfctl_proto_cache[proto] = strdup(p->p_name); 306858937beSMateusz Guzik } 307858937beSMateusz Guzik 308858937beSMateusz Guzik return (pfctl_proto_cache[proto]); 309858937beSMateusz Guzik } 310858937beSMateusz Guzik 3113b3a8eb9SGleb Smirnoff int 3123b3a8eb9SGleb Smirnoff pfctl_enable(int dev, int opts) 3133b3a8eb9SGleb Smirnoff { 31481647eb6SKristof Provost int ret; 31581647eb6SKristof Provost 31666cacc14SKristof Provost if ((ret = pfctl_startstop(pfh, 1)) != 0) { 31781647eb6SKristof Provost if (ret == EEXIST) 3183b3a8eb9SGleb Smirnoff errx(1, "pf already enabled"); 31981647eb6SKristof Provost else if (ret == ESRCH) 3203b3a8eb9SGleb Smirnoff errx(1, "pfil registeration failed"); 3213b3a8eb9SGleb Smirnoff else 322375aaa29SKristof Provost errc(1, ret, "DIOCSTART"); 3233b3a8eb9SGleb Smirnoff } 3243b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 3253b3a8eb9SGleb Smirnoff fprintf(stderr, "pf enabled\n"); 3263b3a8eb9SGleb Smirnoff 3273b3a8eb9SGleb Smirnoff if (altqsupport && ioctl(dev, DIOCSTARTALTQ)) 3283b3a8eb9SGleb Smirnoff if (errno != EEXIST) 3293b3a8eb9SGleb Smirnoff err(1, "DIOCSTARTALTQ"); 3303b3a8eb9SGleb Smirnoff 3313b3a8eb9SGleb Smirnoff return (0); 3323b3a8eb9SGleb Smirnoff } 3333b3a8eb9SGleb Smirnoff 3343b3a8eb9SGleb Smirnoff int 3353b3a8eb9SGleb Smirnoff pfctl_disable(int dev, int opts) 3363b3a8eb9SGleb Smirnoff { 33781647eb6SKristof Provost int ret; 33881647eb6SKristof Provost 33966cacc14SKristof Provost if ((ret = pfctl_startstop(pfh, 0)) != 0) { 34081647eb6SKristof Provost if (ret == ENOENT) 3413b3a8eb9SGleb Smirnoff errx(1, "pf not enabled"); 3423b3a8eb9SGleb Smirnoff else 343375aaa29SKristof Provost errc(1, ret, "DIOCSTOP"); 3443b3a8eb9SGleb Smirnoff } 3453b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 3463b3a8eb9SGleb Smirnoff fprintf(stderr, "pf disabled\n"); 3473b3a8eb9SGleb Smirnoff 3483b3a8eb9SGleb Smirnoff if (altqsupport && ioctl(dev, DIOCSTOPALTQ)) 3493b3a8eb9SGleb Smirnoff if (errno != ENOENT) 3503b3a8eb9SGleb Smirnoff err(1, "DIOCSTOPALTQ"); 3513b3a8eb9SGleb Smirnoff 3523b3a8eb9SGleb Smirnoff return (0); 3533b3a8eb9SGleb Smirnoff } 3543b3a8eb9SGleb Smirnoff 3553b3a8eb9SGleb Smirnoff int 3569dbbe68bSKristof Provost pfctl_clear_stats(struct pfctl_handle *h, int opts) 3573b3a8eb9SGleb Smirnoff { 358375aaa29SKristof Provost int ret; 359375aaa29SKristof Provost if ((ret = pfctl_clear_status(h)) != 0) 360375aaa29SKristof Provost errc(1, ret, "DIOCCLRSTATUS"); 3613b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 3623b3a8eb9SGleb Smirnoff fprintf(stderr, "pf: statistics cleared\n"); 3633b3a8eb9SGleb Smirnoff return (0); 3643b3a8eb9SGleb Smirnoff } 3653b3a8eb9SGleb Smirnoff 3663b3a8eb9SGleb Smirnoff int 367c5e10565SKristof Provost pfctl_get_skip_ifaces(void) 368c5e10565SKristof Provost { 369c5e10565SKristof Provost bzero(&skip_b, sizeof(skip_b)); 370c5e10565SKristof Provost skip_b.pfrb_type = PFRB_IFACES; 371c5e10565SKristof Provost for (;;) { 372c5e10565SKristof Provost pfr_buf_grow(&skip_b, skip_b.pfrb_size); 373c5e10565SKristof Provost skip_b.pfrb_size = skip_b.pfrb_msize; 374c5e10565SKristof Provost if (pfi_get_ifaces(NULL, skip_b.pfrb_caddr, &skip_b.pfrb_size)) 375c5e10565SKristof Provost err(1, "pfi_get_ifaces"); 376c5e10565SKristof Provost if (skip_b.pfrb_size <= skip_b.pfrb_msize) 377c5e10565SKristof Provost break; 378c5e10565SKristof Provost } 379c5e10565SKristof Provost return (0); 380c5e10565SKristof Provost } 381c5e10565SKristof Provost 382c5e10565SKristof Provost int 383c5e10565SKristof Provost pfctl_check_skip_ifaces(char *ifname) 384c5e10565SKristof Provost { 385c5e10565SKristof Provost struct pfi_kif *p; 3867a831fecSKristof Provost struct node_host *h = NULL, *n = NULL; 387c5e10565SKristof Provost 3887a831fecSKristof Provost PFRB_FOREACH(p, &skip_b) { 3897a831fecSKristof Provost if (!strcmp(ifname, p->pfik_name) && 3907a831fecSKristof Provost (p->pfik_flags & PFI_IFLAG_SKIP)) 391c5e10565SKristof Provost p->pfik_flags &= ~PFI_IFLAG_SKIP; 3927a831fecSKristof Provost if (!strcmp(ifname, p->pfik_name) && p->pfik_group != NULL) { 3937a831fecSKristof Provost if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL) 3947a831fecSKristof Provost continue; 3957a831fecSKristof Provost 3967a831fecSKristof Provost for (n = h; n != NULL; n = n->next) { 3977a831fecSKristof Provost if (strncmp(p->pfik_name, ifname, IFNAMSIZ)) 3987a831fecSKristof Provost continue; 3997a831fecSKristof Provost 4007a831fecSKristof Provost p->pfik_flags &= ~PFI_IFLAG_SKIP; 4017a831fecSKristof Provost } 4027a831fecSKristof Provost } 4037a831fecSKristof Provost } 404c5e10565SKristof Provost return (0); 405c5e10565SKristof Provost } 406c5e10565SKristof Provost 4077a831fecSKristof Provost int 4087a831fecSKristof Provost pfctl_adjust_skip_ifaces(struct pfctl *pf) 4097a831fecSKristof Provost { 4107a831fecSKristof Provost struct pfi_kif *p, *pp; 4117a831fecSKristof Provost struct node_host *h = NULL, *n = NULL; 4127a831fecSKristof Provost 4137a831fecSKristof Provost PFRB_FOREACH(p, &skip_b) { 4147a831fecSKristof Provost if (p->pfik_group == NULL || !(p->pfik_flags & PFI_IFLAG_SKIP)) 4157a831fecSKristof Provost continue; 4167a831fecSKristof Provost 417c5e10565SKristof Provost pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0); 4187a831fecSKristof Provost if ((h = ifa_grouplookup(p->pfik_name, 0)) == NULL) 4197a831fecSKristof Provost continue; 4207a831fecSKristof Provost 4217a831fecSKristof Provost for (n = h; n != NULL; n = n->next) 4227a831fecSKristof Provost PFRB_FOREACH(pp, &skip_b) { 4237a831fecSKristof Provost if (strncmp(pp->pfik_name, n->ifname, IFNAMSIZ)) 4247a831fecSKristof Provost continue; 4257a831fecSKristof Provost 4267a831fecSKristof Provost if (!(pp->pfik_flags & PFI_IFLAG_SKIP)) 4277a831fecSKristof Provost pfctl_set_interface_flags(pf, 4287a831fecSKristof Provost pp->pfik_name, PFI_IFLAG_SKIP, 1); 4297a831fecSKristof Provost if (pp->pfik_flags & PFI_IFLAG_SKIP) 4307a831fecSKristof Provost pp->pfik_flags &= ~PFI_IFLAG_SKIP; 4317a831fecSKristof Provost } 4327a831fecSKristof Provost } 4337a831fecSKristof Provost 4347a831fecSKristof Provost PFRB_FOREACH(p, &skip_b) { 4356a88e227SKristof Provost if (! (p->pfik_flags & PFI_IFLAG_SKIP)) 4367a831fecSKristof Provost continue; 4377a831fecSKristof Provost 4387a831fecSKristof Provost pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0); 4397a831fecSKristof Provost } 4407a831fecSKristof Provost 441c5e10565SKristof Provost return (0); 442c5e10565SKristof Provost } 443c5e10565SKristof Provost 444c5e10565SKristof Provost int 4453b3a8eb9SGleb Smirnoff pfctl_clear_interface_flags(int dev, int opts) 4463b3a8eb9SGleb Smirnoff { 4473b3a8eb9SGleb Smirnoff struct pfioc_iface pi; 4483b3a8eb9SGleb Smirnoff 4493b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_NOACTION) == 0) { 4503b3a8eb9SGleb Smirnoff bzero(&pi, sizeof(pi)); 4513b3a8eb9SGleb Smirnoff pi.pfiio_flags = PFI_IFLAG_SKIP; 4523b3a8eb9SGleb Smirnoff 4533b3a8eb9SGleb Smirnoff if (ioctl(dev, DIOCCLRIFFLAG, &pi)) 4543b3a8eb9SGleb Smirnoff err(1, "DIOCCLRIFFLAG"); 4553b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 4563b3a8eb9SGleb Smirnoff fprintf(stderr, "pf: interface flags reset\n"); 4573b3a8eb9SGleb Smirnoff } 4583b3a8eb9SGleb Smirnoff return (0); 4593b3a8eb9SGleb Smirnoff } 4603b3a8eb9SGleb Smirnoff 4613b3a8eb9SGleb Smirnoff int 462f0c334e4SKristof Provost pfctl_flush_eth_rules(int dev, int opts, char *anchorname) 4636ea1c3cfSKristof Provost { 464f0c334e4SKristof Provost int ret; 4656ea1c3cfSKristof Provost 466f0c334e4SKristof Provost ret = pfctl_clear_eth_rules(dev, anchorname); 467f0c334e4SKristof Provost if (ret != 0) 4686ea1c3cfSKristof Provost err(1, "pfctl_clear_eth_rules"); 469f0c334e4SKristof Provost 4706ea1c3cfSKristof Provost if ((opts & PF_OPT_QUIET) == 0) 4716ea1c3cfSKristof Provost fprintf(stderr, "Ethernet rules cleared\n"); 472f0c334e4SKristof Provost 473f0c334e4SKristof Provost return (ret); 4746ea1c3cfSKristof Provost } 4756ea1c3cfSKristof Provost 4766ea1c3cfSKristof Provost int 477f0c334e4SKristof Provost pfctl_flush_rules(int dev, int opts, char *anchorname) 4783b3a8eb9SGleb Smirnoff { 479f0c334e4SKristof Provost int ret; 4803b3a8eb9SGleb Smirnoff 481f0c334e4SKristof Provost ret = pfctl_clear_rules(dev, anchorname); 482f0c334e4SKristof Provost if (ret != 0) 4833b3a8eb9SGleb Smirnoff err(1, "pfctl_clear_rules"); 4843b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 4853b3a8eb9SGleb Smirnoff fprintf(stderr, "rules cleared\n"); 4863b3a8eb9SGleb Smirnoff return (0); 4873b3a8eb9SGleb Smirnoff } 4883b3a8eb9SGleb Smirnoff 4893b3a8eb9SGleb Smirnoff int 490f0c334e4SKristof Provost pfctl_flush_nat(int dev, int opts, char *anchorname) 4913b3a8eb9SGleb Smirnoff { 492f0c334e4SKristof Provost int ret; 4933b3a8eb9SGleb Smirnoff 494f0c334e4SKristof Provost ret = pfctl_clear_nat(dev, anchorname); 495f0c334e4SKristof Provost if (ret != 0) 4963b3a8eb9SGleb Smirnoff err(1, "pfctl_clear_nat"); 4973b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 4983b3a8eb9SGleb Smirnoff fprintf(stderr, "nat cleared\n"); 4993b3a8eb9SGleb Smirnoff return (0); 5003b3a8eb9SGleb Smirnoff } 5013b3a8eb9SGleb Smirnoff 5023b3a8eb9SGleb Smirnoff int 5033b3a8eb9SGleb Smirnoff pfctl_clear_altq(int dev, int opts) 5043b3a8eb9SGleb Smirnoff { 5053b3a8eb9SGleb Smirnoff struct pfr_buffer t; 5063b3a8eb9SGleb Smirnoff 5073b3a8eb9SGleb Smirnoff if (!altqsupport) 5083b3a8eb9SGleb Smirnoff return (-1); 5093b3a8eb9SGleb Smirnoff memset(&t, 0, sizeof(t)); 5103b3a8eb9SGleb Smirnoff t.pfrb_type = PFRB_TRANS; 5113b3a8eb9SGleb Smirnoff if (pfctl_add_trans(&t, PF_RULESET_ALTQ, "") || 5123b3a8eb9SGleb Smirnoff pfctl_trans(dev, &t, DIOCXBEGIN, 0) || 5133b3a8eb9SGleb Smirnoff pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) 5143b3a8eb9SGleb Smirnoff err(1, "pfctl_clear_altq"); 5153b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 5163b3a8eb9SGleb Smirnoff fprintf(stderr, "altq cleared\n"); 5173b3a8eb9SGleb Smirnoff return (0); 5183b3a8eb9SGleb Smirnoff } 5193b3a8eb9SGleb Smirnoff 5203b3a8eb9SGleb Smirnoff int 5213b3a8eb9SGleb Smirnoff pfctl_clear_src_nodes(int dev, int opts) 5223b3a8eb9SGleb Smirnoff { 5233b3a8eb9SGleb Smirnoff if (ioctl(dev, DIOCCLRSRCNODES)) 5243b3a8eb9SGleb Smirnoff err(1, "DIOCCLRSRCNODES"); 5253b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 5263b3a8eb9SGleb Smirnoff fprintf(stderr, "source tracking entries cleared\n"); 5273b3a8eb9SGleb Smirnoff return (0); 5283b3a8eb9SGleb Smirnoff } 5293b3a8eb9SGleb Smirnoff 5303b3a8eb9SGleb Smirnoff int 53153714a58SKristof Provost pfctl_clear_iface_states(int dev, const char *iface, int opts) 5323b3a8eb9SGleb Smirnoff { 53353714a58SKristof Provost struct pfctl_kill kill; 53453714a58SKristof Provost unsigned int killed; 535375aaa29SKristof Provost int ret; 5363b3a8eb9SGleb Smirnoff 53753714a58SKristof Provost memset(&kill, 0, sizeof(kill)); 53853714a58SKristof Provost if (iface != NULL && strlcpy(kill.ifname, iface, 53953714a58SKristof Provost sizeof(kill.ifname)) >= sizeof(kill.ifname)) 5403b3a8eb9SGleb Smirnoff errx(1, "invalid interface: %s", iface); 5413b3a8eb9SGleb Smirnoff 54293abcf17SKristof Provost if (opts & PF_OPT_KILLMATCH) 54393abcf17SKristof Provost kill.kill_match = true; 54493abcf17SKristof Provost 545375aaa29SKristof Provost if ((ret = pfctl_clear_states_h(pfh, &kill, &killed)) != 0) 546375aaa29SKristof Provost errc(1, ret, "DIOCCLRSTATES"); 5473b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 54853714a58SKristof Provost fprintf(stderr, "%d states cleared\n", killed); 5493b3a8eb9SGleb Smirnoff return (0); 5503b3a8eb9SGleb Smirnoff } 5513b3a8eb9SGleb Smirnoff 5523b3a8eb9SGleb Smirnoff void 5533b3a8eb9SGleb Smirnoff pfctl_addrprefix(char *addr, struct pf_addr *mask) 5543b3a8eb9SGleb Smirnoff { 5553b3a8eb9SGleb Smirnoff char *p; 5563b3a8eb9SGleb Smirnoff const char *errstr; 5573b3a8eb9SGleb Smirnoff int prefix, ret_ga, q, r; 5583b3a8eb9SGleb Smirnoff struct addrinfo hints, *res; 5593b3a8eb9SGleb Smirnoff 5603b3a8eb9SGleb Smirnoff if ((p = strchr(addr, '/')) == NULL) 5613b3a8eb9SGleb Smirnoff return; 5623b3a8eb9SGleb Smirnoff 5633b3a8eb9SGleb Smirnoff *p++ = '\0'; 5643b3a8eb9SGleb Smirnoff prefix = strtonum(p, 0, 128, &errstr); 5653b3a8eb9SGleb Smirnoff if (errstr) 5663b3a8eb9SGleb Smirnoff errx(1, "prefix is %s: %s", errstr, p); 5673b3a8eb9SGleb Smirnoff 5683b3a8eb9SGleb Smirnoff bzero(&hints, sizeof(hints)); 5693b3a8eb9SGleb Smirnoff /* prefix only with numeric addresses */ 5703b3a8eb9SGleb Smirnoff hints.ai_flags |= AI_NUMERICHOST; 5713b3a8eb9SGleb Smirnoff 5723b3a8eb9SGleb Smirnoff if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) { 5733b3a8eb9SGleb Smirnoff errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 5743b3a8eb9SGleb Smirnoff /* NOTREACHED */ 5753b3a8eb9SGleb Smirnoff } 5763b3a8eb9SGleb Smirnoff 5773b3a8eb9SGleb Smirnoff if (res->ai_family == AF_INET && prefix > 32) 5783b3a8eb9SGleb Smirnoff errx(1, "prefix too long for AF_INET"); 5793b3a8eb9SGleb Smirnoff else if (res->ai_family == AF_INET6 && prefix > 128) 5803b3a8eb9SGleb Smirnoff errx(1, "prefix too long for AF_INET6"); 5813b3a8eb9SGleb Smirnoff 5823b3a8eb9SGleb Smirnoff q = prefix >> 3; 5833b3a8eb9SGleb Smirnoff r = prefix & 7; 5843b3a8eb9SGleb Smirnoff switch (res->ai_family) { 5853b3a8eb9SGleb Smirnoff case AF_INET: 5863b3a8eb9SGleb Smirnoff bzero(&mask->v4, sizeof(mask->v4)); 5873b3a8eb9SGleb Smirnoff mask->v4.s_addr = htonl((u_int32_t) 5883b3a8eb9SGleb Smirnoff (0xffffffffffULL << (32 - prefix))); 5893b3a8eb9SGleb Smirnoff break; 5903b3a8eb9SGleb Smirnoff case AF_INET6: 5913b3a8eb9SGleb Smirnoff bzero(&mask->v6, sizeof(mask->v6)); 5923b3a8eb9SGleb Smirnoff if (q > 0) 5933b3a8eb9SGleb Smirnoff memset((void *)&mask->v6, 0xff, q); 5943b3a8eb9SGleb Smirnoff if (r > 0) 5953b3a8eb9SGleb Smirnoff *((u_char *)&mask->v6 + q) = 5963b3a8eb9SGleb Smirnoff (0xff00 >> r) & 0xff; 5973b3a8eb9SGleb Smirnoff break; 5983b3a8eb9SGleb Smirnoff } 5993b3a8eb9SGleb Smirnoff freeaddrinfo(res); 6003b3a8eb9SGleb Smirnoff } 6013b3a8eb9SGleb Smirnoff 6023b3a8eb9SGleb Smirnoff int 6033b3a8eb9SGleb Smirnoff pfctl_kill_src_nodes(int dev, const char *iface, int opts) 6043b3a8eb9SGleb Smirnoff { 6053b3a8eb9SGleb Smirnoff struct pfioc_src_node_kill psnk; 6063b3a8eb9SGleb Smirnoff struct addrinfo *res[2], *resp[2]; 6073b3a8eb9SGleb Smirnoff struct sockaddr last_src, last_dst; 6083b3a8eb9SGleb Smirnoff int killed, sources, dests; 6093b3a8eb9SGleb Smirnoff int ret_ga; 6103b3a8eb9SGleb Smirnoff 6113b3a8eb9SGleb Smirnoff killed = sources = dests = 0; 6123b3a8eb9SGleb Smirnoff 6133b3a8eb9SGleb Smirnoff memset(&psnk, 0, sizeof(psnk)); 6143b3a8eb9SGleb Smirnoff memset(&psnk.psnk_src.addr.v.a.mask, 0xff, 6153b3a8eb9SGleb Smirnoff sizeof(psnk.psnk_src.addr.v.a.mask)); 6163b3a8eb9SGleb Smirnoff memset(&last_src, 0xff, sizeof(last_src)); 6173b3a8eb9SGleb Smirnoff memset(&last_dst, 0xff, sizeof(last_dst)); 6183b3a8eb9SGleb Smirnoff 6193b3a8eb9SGleb Smirnoff pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask); 6203b3a8eb9SGleb Smirnoff 6213b3a8eb9SGleb Smirnoff if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) { 6223b3a8eb9SGleb Smirnoff errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 6233b3a8eb9SGleb Smirnoff /* NOTREACHED */ 6243b3a8eb9SGleb Smirnoff } 6253b3a8eb9SGleb Smirnoff for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 6263b3a8eb9SGleb Smirnoff if (resp[0]->ai_addr == NULL) 6273b3a8eb9SGleb Smirnoff continue; 6283b3a8eb9SGleb Smirnoff /* We get lots of duplicates. Catch the easy ones */ 6293b3a8eb9SGleb Smirnoff if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 6303b3a8eb9SGleb Smirnoff continue; 6313b3a8eb9SGleb Smirnoff last_src = *(struct sockaddr *)resp[0]->ai_addr; 6323b3a8eb9SGleb Smirnoff 6333b3a8eb9SGleb Smirnoff psnk.psnk_af = resp[0]->ai_family; 6343b3a8eb9SGleb Smirnoff sources++; 6353b3a8eb9SGleb Smirnoff 6363b3a8eb9SGleb Smirnoff if (psnk.psnk_af == AF_INET) 6373b3a8eb9SGleb Smirnoff psnk.psnk_src.addr.v.a.addr.v4 = 6383b3a8eb9SGleb Smirnoff ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 6393b3a8eb9SGleb Smirnoff else if (psnk.psnk_af == AF_INET6) 6403b3a8eb9SGleb Smirnoff psnk.psnk_src.addr.v.a.addr.v6 = 6413b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 6423b3a8eb9SGleb Smirnoff sin6_addr; 6433b3a8eb9SGleb Smirnoff else 6443b3a8eb9SGleb Smirnoff errx(1, "Unknown address family %d", psnk.psnk_af); 6453b3a8eb9SGleb Smirnoff 6463b3a8eb9SGleb Smirnoff if (src_node_killers > 1) { 6473b3a8eb9SGleb Smirnoff dests = 0; 6483b3a8eb9SGleb Smirnoff memset(&psnk.psnk_dst.addr.v.a.mask, 0xff, 6493b3a8eb9SGleb Smirnoff sizeof(psnk.psnk_dst.addr.v.a.mask)); 6503b3a8eb9SGleb Smirnoff memset(&last_dst, 0xff, sizeof(last_dst)); 6513b3a8eb9SGleb Smirnoff pfctl_addrprefix(src_node_kill[1], 6523b3a8eb9SGleb Smirnoff &psnk.psnk_dst.addr.v.a.mask); 6533b3a8eb9SGleb Smirnoff if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL, 6543b3a8eb9SGleb Smirnoff &res[1]))) { 6553b3a8eb9SGleb Smirnoff errx(1, "getaddrinfo: %s", 6563b3a8eb9SGleb Smirnoff gai_strerror(ret_ga)); 6573b3a8eb9SGleb Smirnoff /* NOTREACHED */ 6583b3a8eb9SGleb Smirnoff } 6593b3a8eb9SGleb Smirnoff for (resp[1] = res[1]; resp[1]; 6603b3a8eb9SGleb Smirnoff resp[1] = resp[1]->ai_next) { 6613b3a8eb9SGleb Smirnoff if (resp[1]->ai_addr == NULL) 6623b3a8eb9SGleb Smirnoff continue; 6633b3a8eb9SGleb Smirnoff if (psnk.psnk_af != resp[1]->ai_family) 6643b3a8eb9SGleb Smirnoff continue; 6653b3a8eb9SGleb Smirnoff 6663b3a8eb9SGleb Smirnoff if (memcmp(&last_dst, resp[1]->ai_addr, 6673b3a8eb9SGleb Smirnoff sizeof(last_dst)) == 0) 6683b3a8eb9SGleb Smirnoff continue; 6693b3a8eb9SGleb Smirnoff last_dst = *(struct sockaddr *)resp[1]->ai_addr; 6703b3a8eb9SGleb Smirnoff 6713b3a8eb9SGleb Smirnoff dests++; 6723b3a8eb9SGleb Smirnoff 6733b3a8eb9SGleb Smirnoff if (psnk.psnk_af == AF_INET) 6743b3a8eb9SGleb Smirnoff psnk.psnk_dst.addr.v.a.addr.v4 = 6753b3a8eb9SGleb Smirnoff ((struct sockaddr_in *)resp[1]-> 6763b3a8eb9SGleb Smirnoff ai_addr)->sin_addr; 6773b3a8eb9SGleb Smirnoff else if (psnk.psnk_af == AF_INET6) 6783b3a8eb9SGleb Smirnoff psnk.psnk_dst.addr.v.a.addr.v6 = 6793b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)resp[1]-> 6803b3a8eb9SGleb Smirnoff ai_addr)->sin6_addr; 6813b3a8eb9SGleb Smirnoff else 6823b3a8eb9SGleb Smirnoff errx(1, "Unknown address family %d", 6833b3a8eb9SGleb Smirnoff psnk.psnk_af); 6843b3a8eb9SGleb Smirnoff 6853b3a8eb9SGleb Smirnoff if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 6863b3a8eb9SGleb Smirnoff err(1, "DIOCKILLSRCNODES"); 6873b3a8eb9SGleb Smirnoff killed += psnk.psnk_killed; 6883b3a8eb9SGleb Smirnoff } 6893b3a8eb9SGleb Smirnoff freeaddrinfo(res[1]); 6903b3a8eb9SGleb Smirnoff } else { 6913b3a8eb9SGleb Smirnoff if (ioctl(dev, DIOCKILLSRCNODES, &psnk)) 6923b3a8eb9SGleb Smirnoff err(1, "DIOCKILLSRCNODES"); 6933b3a8eb9SGleb Smirnoff killed += psnk.psnk_killed; 6943b3a8eb9SGleb Smirnoff } 6953b3a8eb9SGleb Smirnoff } 6963b3a8eb9SGleb Smirnoff 6973b3a8eb9SGleb Smirnoff freeaddrinfo(res[0]); 6983b3a8eb9SGleb Smirnoff 6993b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 7003b3a8eb9SGleb Smirnoff fprintf(stderr, "killed %d src nodes from %d sources and %d " 7013b3a8eb9SGleb Smirnoff "destinations\n", killed, sources, dests); 7023b3a8eb9SGleb Smirnoff return (0); 7033b3a8eb9SGleb Smirnoff } 7043b3a8eb9SGleb Smirnoff 7053b3a8eb9SGleb Smirnoff int 7063b3a8eb9SGleb Smirnoff pfctl_net_kill_states(int dev, const char *iface, int opts) 7073b3a8eb9SGleb Smirnoff { 7082a00c4dbSKristof Provost struct pfctl_kill kill; 7093b3a8eb9SGleb Smirnoff struct addrinfo *res[2], *resp[2]; 7103b3a8eb9SGleb Smirnoff struct sockaddr last_src, last_dst; 7112a00c4dbSKristof Provost unsigned int newkilled; 7123b3a8eb9SGleb Smirnoff int killed, sources, dests; 713375aaa29SKristof Provost int ret_ga, ret; 7143b3a8eb9SGleb Smirnoff 7153b3a8eb9SGleb Smirnoff killed = sources = dests = 0; 7163b3a8eb9SGleb Smirnoff 7172a00c4dbSKristof Provost memset(&kill, 0, sizeof(kill)); 7182a00c4dbSKristof Provost memset(&kill.src.addr.v.a.mask, 0xff, 7192a00c4dbSKristof Provost sizeof(kill.src.addr.v.a.mask)); 7203b3a8eb9SGleb Smirnoff memset(&last_src, 0xff, sizeof(last_src)); 7213b3a8eb9SGleb Smirnoff memset(&last_dst, 0xff, sizeof(last_dst)); 7222a00c4dbSKristof Provost if (iface != NULL && strlcpy(kill.ifname, iface, 7232a00c4dbSKristof Provost sizeof(kill.ifname)) >= sizeof(kill.ifname)) 7243b3a8eb9SGleb Smirnoff errx(1, "invalid interface: %s", iface); 7253b3a8eb9SGleb Smirnoff 7264f337550SKristof Provost if (state_killers == 2 && (strcmp(state_kill[0], "nat") == 0)) { 7274f337550SKristof Provost kill.nat = true; 7284f337550SKristof Provost state_kill[0] = state_kill[1]; 7294f337550SKristof Provost state_killers = 1; 7304f337550SKristof Provost } 7314f337550SKristof Provost 7322a00c4dbSKristof Provost pfctl_addrprefix(state_kill[0], &kill.src.addr.v.a.mask); 7333b3a8eb9SGleb Smirnoff 73493abcf17SKristof Provost if (opts & PF_OPT_KILLMATCH) 73593abcf17SKristof Provost kill.kill_match = true; 73693abcf17SKristof Provost 7373b3a8eb9SGleb Smirnoff if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) { 7383b3a8eb9SGleb Smirnoff errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 7393b3a8eb9SGleb Smirnoff /* NOTREACHED */ 7403b3a8eb9SGleb Smirnoff } 7413b3a8eb9SGleb Smirnoff for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) { 7423b3a8eb9SGleb Smirnoff if (resp[0]->ai_addr == NULL) 7433b3a8eb9SGleb Smirnoff continue; 7443b3a8eb9SGleb Smirnoff /* We get lots of duplicates. Catch the easy ones */ 7453b3a8eb9SGleb Smirnoff if (memcmp(&last_src, resp[0]->ai_addr, sizeof(last_src)) == 0) 7463b3a8eb9SGleb Smirnoff continue; 7473b3a8eb9SGleb Smirnoff last_src = *(struct sockaddr *)resp[0]->ai_addr; 7483b3a8eb9SGleb Smirnoff 7492a00c4dbSKristof Provost kill.af = resp[0]->ai_family; 7503b3a8eb9SGleb Smirnoff sources++; 7513b3a8eb9SGleb Smirnoff 7522a00c4dbSKristof Provost if (kill.af == AF_INET) 7532a00c4dbSKristof Provost kill.src.addr.v.a.addr.v4 = 7543b3a8eb9SGleb Smirnoff ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr; 7552a00c4dbSKristof Provost else if (kill.af == AF_INET6) 7562a00c4dbSKristof Provost kill.src.addr.v.a.addr.v6 = 7573b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)resp[0]->ai_addr)-> 7583b3a8eb9SGleb Smirnoff sin6_addr; 7593b3a8eb9SGleb Smirnoff else 7602a00c4dbSKristof Provost errx(1, "Unknown address family %d", kill.af); 7613b3a8eb9SGleb Smirnoff 7623b3a8eb9SGleb Smirnoff if (state_killers > 1) { 7633b3a8eb9SGleb Smirnoff dests = 0; 7642a00c4dbSKristof Provost memset(&kill.dst.addr.v.a.mask, 0xff, 7652a00c4dbSKristof Provost sizeof(kill.dst.addr.v.a.mask)); 7663b3a8eb9SGleb Smirnoff memset(&last_dst, 0xff, sizeof(last_dst)); 7673b3a8eb9SGleb Smirnoff pfctl_addrprefix(state_kill[1], 7682a00c4dbSKristof Provost &kill.dst.addr.v.a.mask); 7693b3a8eb9SGleb Smirnoff if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, 7703b3a8eb9SGleb Smirnoff &res[1]))) { 7713b3a8eb9SGleb Smirnoff errx(1, "getaddrinfo: %s", 7723b3a8eb9SGleb Smirnoff gai_strerror(ret_ga)); 7733b3a8eb9SGleb Smirnoff /* NOTREACHED */ 7743b3a8eb9SGleb Smirnoff } 7753b3a8eb9SGleb Smirnoff for (resp[1] = res[1]; resp[1]; 7763b3a8eb9SGleb Smirnoff resp[1] = resp[1]->ai_next) { 7773b3a8eb9SGleb Smirnoff if (resp[1]->ai_addr == NULL) 7783b3a8eb9SGleb Smirnoff continue; 7792a00c4dbSKristof Provost if (kill.af != resp[1]->ai_family) 7803b3a8eb9SGleb Smirnoff continue; 7813b3a8eb9SGleb Smirnoff 7823b3a8eb9SGleb Smirnoff if (memcmp(&last_dst, resp[1]->ai_addr, 7833b3a8eb9SGleb Smirnoff sizeof(last_dst)) == 0) 7843b3a8eb9SGleb Smirnoff continue; 7853b3a8eb9SGleb Smirnoff last_dst = *(struct sockaddr *)resp[1]->ai_addr; 7863b3a8eb9SGleb Smirnoff 7873b3a8eb9SGleb Smirnoff dests++; 7883b3a8eb9SGleb Smirnoff 7892a00c4dbSKristof Provost if (kill.af == AF_INET) 7902a00c4dbSKristof Provost kill.dst.addr.v.a.addr.v4 = 7913b3a8eb9SGleb Smirnoff ((struct sockaddr_in *)resp[1]-> 7923b3a8eb9SGleb Smirnoff ai_addr)->sin_addr; 7932a00c4dbSKristof Provost else if (kill.af == AF_INET6) 7942a00c4dbSKristof Provost kill.dst.addr.v.a.addr.v6 = 7953b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)resp[1]-> 7963b3a8eb9SGleb Smirnoff ai_addr)->sin6_addr; 7973b3a8eb9SGleb Smirnoff else 7983b3a8eb9SGleb Smirnoff errx(1, "Unknown address family %d", 7992a00c4dbSKristof Provost kill.af); 8003b3a8eb9SGleb Smirnoff 801375aaa29SKristof Provost if ((ret = pfctl_kill_states_h(pfh, &kill, &newkilled)) != 0) 802375aaa29SKristof Provost errc(1, ret, "DIOCKILLSTATES"); 8032a00c4dbSKristof Provost killed += newkilled; 8043b3a8eb9SGleb Smirnoff } 8053b3a8eb9SGleb Smirnoff freeaddrinfo(res[1]); 8063b3a8eb9SGleb Smirnoff } else { 807375aaa29SKristof Provost if ((ret = pfctl_kill_states_h(pfh, &kill, &newkilled)) != 0) 808375aaa29SKristof Provost errc(1, ret, "DIOCKILLSTATES"); 8092a00c4dbSKristof Provost killed += newkilled; 8103b3a8eb9SGleb Smirnoff } 8113b3a8eb9SGleb Smirnoff } 8123b3a8eb9SGleb Smirnoff 8133b3a8eb9SGleb Smirnoff freeaddrinfo(res[0]); 8143b3a8eb9SGleb Smirnoff 8153b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 8163b3a8eb9SGleb Smirnoff fprintf(stderr, "killed %d states from %d sources and %d " 8173b3a8eb9SGleb Smirnoff "destinations\n", killed, sources, dests); 8183b3a8eb9SGleb Smirnoff return (0); 8193b3a8eb9SGleb Smirnoff } 8203b3a8eb9SGleb Smirnoff 8213b3a8eb9SGleb Smirnoff int 822abbcba9cSKristof Provost pfctl_gateway_kill_states(int dev, const char *iface, int opts) 823abbcba9cSKristof Provost { 824abbcba9cSKristof Provost struct pfctl_kill kill; 825abbcba9cSKristof Provost struct addrinfo *res, *resp; 826abbcba9cSKristof Provost struct sockaddr last_src; 827abbcba9cSKristof Provost unsigned int newkilled; 828abbcba9cSKristof Provost int killed = 0; 829abbcba9cSKristof Provost int ret_ga; 830abbcba9cSKristof Provost 831abbcba9cSKristof Provost if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 832abbcba9cSKristof Provost warnx("no gateway specified"); 833abbcba9cSKristof Provost usage(); 834abbcba9cSKristof Provost } 835abbcba9cSKristof Provost 836abbcba9cSKristof Provost memset(&kill, 0, sizeof(kill)); 837abbcba9cSKristof Provost memset(&kill.rt_addr.addr.v.a.mask, 0xff, 838abbcba9cSKristof Provost sizeof(kill.rt_addr.addr.v.a.mask)); 839abbcba9cSKristof Provost memset(&last_src, 0xff, sizeof(last_src)); 840abbcba9cSKristof Provost if (iface != NULL && strlcpy(kill.ifname, iface, 841abbcba9cSKristof Provost sizeof(kill.ifname)) >= sizeof(kill.ifname)) 842abbcba9cSKristof Provost errx(1, "invalid interface: %s", iface); 843abbcba9cSKristof Provost 84493abcf17SKristof Provost if (opts & PF_OPT_KILLMATCH) 84593abcf17SKristof Provost kill.kill_match = true; 84693abcf17SKristof Provost 847abbcba9cSKristof Provost pfctl_addrprefix(state_kill[1], &kill.rt_addr.addr.v.a.mask); 848abbcba9cSKristof Provost 849abbcba9cSKristof Provost if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, &res))) { 850abbcba9cSKristof Provost errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); 851abbcba9cSKristof Provost /* NOTREACHED */ 852abbcba9cSKristof Provost } 853abbcba9cSKristof Provost for (resp = res; resp; resp = resp->ai_next) { 854abbcba9cSKristof Provost if (resp->ai_addr == NULL) 855abbcba9cSKristof Provost continue; 856abbcba9cSKristof Provost /* We get lots of duplicates. Catch the easy ones */ 857abbcba9cSKristof Provost if (memcmp(&last_src, resp->ai_addr, sizeof(last_src)) == 0) 858abbcba9cSKristof Provost continue; 859abbcba9cSKristof Provost last_src = *(struct sockaddr *)resp->ai_addr; 860abbcba9cSKristof Provost 861abbcba9cSKristof Provost kill.af = resp->ai_family; 862abbcba9cSKristof Provost 863abbcba9cSKristof Provost if (kill.af == AF_INET) 864abbcba9cSKristof Provost kill.rt_addr.addr.v.a.addr.v4 = 865abbcba9cSKristof Provost ((struct sockaddr_in *)resp->ai_addr)->sin_addr; 866abbcba9cSKristof Provost else if (kill.af == AF_INET6) 867abbcba9cSKristof Provost kill.rt_addr.addr.v.a.addr.v6 = 868abbcba9cSKristof Provost ((struct sockaddr_in6 *)resp->ai_addr)-> 869abbcba9cSKristof Provost sin6_addr; 870abbcba9cSKristof Provost else 871abbcba9cSKristof Provost errx(1, "Unknown address family %d", kill.af); 872abbcba9cSKristof Provost 873706d465dSKristof Provost if (pfctl_kill_states_h(pfh, &kill, &newkilled)) 874abbcba9cSKristof Provost err(1, "DIOCKILLSTATES"); 875abbcba9cSKristof Provost killed += newkilled; 876abbcba9cSKristof Provost } 877abbcba9cSKristof Provost 878abbcba9cSKristof Provost freeaddrinfo(res); 879abbcba9cSKristof Provost 880abbcba9cSKristof Provost if ((opts & PF_OPT_QUIET) == 0) 881abbcba9cSKristof Provost fprintf(stderr, "killed %d states\n", killed); 882abbcba9cSKristof Provost return (0); 883abbcba9cSKristof Provost } 884abbcba9cSKristof Provost 885abbcba9cSKristof Provost int 8863b3a8eb9SGleb Smirnoff pfctl_label_kill_states(int dev, const char *iface, int opts) 8873b3a8eb9SGleb Smirnoff { 8882a00c4dbSKristof Provost struct pfctl_kill kill; 8892a00c4dbSKristof Provost unsigned int killed; 890375aaa29SKristof Provost int ret; 8913b3a8eb9SGleb Smirnoff 8923b3a8eb9SGleb Smirnoff if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 8933b3a8eb9SGleb Smirnoff warnx("no label specified"); 8943b3a8eb9SGleb Smirnoff usage(); 8953b3a8eb9SGleb Smirnoff } 8962a00c4dbSKristof Provost memset(&kill, 0, sizeof(kill)); 8972a00c4dbSKristof Provost if (iface != NULL && strlcpy(kill.ifname, iface, 8982a00c4dbSKristof Provost sizeof(kill.ifname)) >= sizeof(kill.ifname)) 8993b3a8eb9SGleb Smirnoff errx(1, "invalid interface: %s", iface); 9003b3a8eb9SGleb Smirnoff 90193abcf17SKristof Provost if (opts & PF_OPT_KILLMATCH) 90293abcf17SKristof Provost kill.kill_match = true; 90393abcf17SKristof Provost 9042a00c4dbSKristof Provost if (strlcpy(kill.label, state_kill[1], sizeof(kill.label)) >= 9052a00c4dbSKristof Provost sizeof(kill.label)) 9063b3a8eb9SGleb Smirnoff errx(1, "label too long: %s", state_kill[1]); 9073b3a8eb9SGleb Smirnoff 908375aaa29SKristof Provost if ((ret = pfctl_kill_states_h(pfh, &kill, &killed)) != 0) 909375aaa29SKristof Provost errc(1, ret, "DIOCKILLSTATES"); 9103b3a8eb9SGleb Smirnoff 9113b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 9122a00c4dbSKristof Provost fprintf(stderr, "killed %d states\n", killed); 9133b3a8eb9SGleb Smirnoff 9143b3a8eb9SGleb Smirnoff return (0); 9153b3a8eb9SGleb Smirnoff } 9163b3a8eb9SGleb Smirnoff 9173b3a8eb9SGleb Smirnoff int 9183b3a8eb9SGleb Smirnoff pfctl_id_kill_states(int dev, const char *iface, int opts) 9193b3a8eb9SGleb Smirnoff { 9202a00c4dbSKristof Provost struct pfctl_kill kill; 9212a00c4dbSKristof Provost unsigned int killed; 922375aaa29SKristof Provost int ret; 9233b3a8eb9SGleb Smirnoff 9243b3a8eb9SGleb Smirnoff if (state_killers != 2 || (strlen(state_kill[1]) == 0)) { 9253b3a8eb9SGleb Smirnoff warnx("no id specified"); 9263b3a8eb9SGleb Smirnoff usage(); 9273b3a8eb9SGleb Smirnoff } 9283b3a8eb9SGleb Smirnoff 9292a00c4dbSKristof Provost memset(&kill, 0, sizeof(kill)); 93093abcf17SKristof Provost 93193abcf17SKristof Provost if (opts & PF_OPT_KILLMATCH) 93293abcf17SKristof Provost kill.kill_match = true; 93393abcf17SKristof Provost 9343b3a8eb9SGleb Smirnoff if ((sscanf(state_kill[1], "%jx/%x", 9359ce32082SKristof Provost &kill.cmp.id, &kill.cmp.creatorid)) == 2) { 9369ce32082SKristof Provost } 9372a00c4dbSKristof Provost else if ((sscanf(state_kill[1], "%jx", &kill.cmp.id)) == 1) { 9382a00c4dbSKristof Provost kill.cmp.creatorid = 0; 9393b3a8eb9SGleb Smirnoff } else { 9403b3a8eb9SGleb Smirnoff warnx("wrong id format specified"); 9413b3a8eb9SGleb Smirnoff usage(); 9423b3a8eb9SGleb Smirnoff } 9432a00c4dbSKristof Provost if (kill.cmp.id == 0) { 9443b3a8eb9SGleb Smirnoff warnx("cannot kill id 0"); 9453b3a8eb9SGleb Smirnoff usage(); 9463b3a8eb9SGleb Smirnoff } 9473b3a8eb9SGleb Smirnoff 948375aaa29SKristof Provost if ((ret = pfctl_kill_states_h(pfh, &kill, &killed)) != 0) 949375aaa29SKristof Provost errc(1, ret, "DIOCKILLSTATES"); 9503b3a8eb9SGleb Smirnoff 9513b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) 9522a00c4dbSKristof Provost fprintf(stderr, "killed %d states\n", killed); 9533b3a8eb9SGleb Smirnoff 9543b3a8eb9SGleb Smirnoff return (0); 9553b3a8eb9SGleb Smirnoff } 9563b3a8eb9SGleb Smirnoff 9573b3a8eb9SGleb Smirnoff int 958600bd6ceSKurosawa Takahiro pfctl_get_pool(int dev, struct pfctl_pool *pool, u_int32_t nr, 959aa69fdf1SKristof Provost u_int32_t ticket, int r_action, char *anchorname, int which) 9603b3a8eb9SGleb Smirnoff { 9613b3a8eb9SGleb Smirnoff struct pfioc_pooladdr pp; 9623b3a8eb9SGleb Smirnoff struct pf_pooladdr *pa; 9633b3a8eb9SGleb Smirnoff u_int32_t pnr, mpnr; 964375aaa29SKristof Provost int ret; 9653b3a8eb9SGleb Smirnoff 9663b3a8eb9SGleb Smirnoff memset(&pp, 0, sizeof(pp)); 967aa69fdf1SKristof Provost if ((ret = pfctl_get_addrs(pfh, ticket, nr, r_action, anchorname, &mpnr, which)) != 0) { 968375aaa29SKristof Provost warnc(ret, "DIOCGETADDRS"); 9693b3a8eb9SGleb Smirnoff return (-1); 9703b3a8eb9SGleb Smirnoff } 9719ae91f59SKristof Provost 9723b3a8eb9SGleb Smirnoff TAILQ_INIT(&pool->list); 9733b3a8eb9SGleb Smirnoff for (pnr = 0; pnr < mpnr; ++pnr) { 974aa69fdf1SKristof Provost if ((ret = pfctl_get_addr(pfh, ticket, nr, r_action, anchorname, pnr, &pp, which)) != 0) { 975375aaa29SKristof Provost warnc(ret, "DIOCGETADDR"); 9763b3a8eb9SGleb Smirnoff return (-1); 9773b3a8eb9SGleb Smirnoff } 9783b3a8eb9SGleb Smirnoff pa = calloc(1, sizeof(struct pf_pooladdr)); 9793b3a8eb9SGleb Smirnoff if (pa == NULL) 9803b3a8eb9SGleb Smirnoff err(1, "calloc"); 9813b3a8eb9SGleb Smirnoff bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr)); 9823b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(&pool->list, pa, entries); 9833b3a8eb9SGleb Smirnoff } 9843b3a8eb9SGleb Smirnoff 9853b3a8eb9SGleb Smirnoff return (0); 9863b3a8eb9SGleb Smirnoff } 9873b3a8eb9SGleb Smirnoff 9883b3a8eb9SGleb Smirnoff void 989600bd6ceSKurosawa Takahiro pfctl_move_pool(struct pfctl_pool *src, struct pfctl_pool *dst) 9903b3a8eb9SGleb Smirnoff { 9913b3a8eb9SGleb Smirnoff struct pf_pooladdr *pa; 9923b3a8eb9SGleb Smirnoff 9933b3a8eb9SGleb Smirnoff while ((pa = TAILQ_FIRST(&src->list)) != NULL) { 9943b3a8eb9SGleb Smirnoff TAILQ_REMOVE(&src->list, pa, entries); 9953b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(&dst->list, pa, entries); 9963b3a8eb9SGleb Smirnoff } 9973b3a8eb9SGleb Smirnoff } 9983b3a8eb9SGleb Smirnoff 9993b3a8eb9SGleb Smirnoff void 1000600bd6ceSKurosawa Takahiro pfctl_clear_pool(struct pfctl_pool *pool) 10013b3a8eb9SGleb Smirnoff { 10023b3a8eb9SGleb Smirnoff struct pf_pooladdr *pa; 10033b3a8eb9SGleb Smirnoff 10043b3a8eb9SGleb Smirnoff while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { 10053b3a8eb9SGleb Smirnoff TAILQ_REMOVE(&pool->list, pa, entries); 10063b3a8eb9SGleb Smirnoff free(pa); 10073b3a8eb9SGleb Smirnoff } 10083b3a8eb9SGleb Smirnoff } 10093b3a8eb9SGleb Smirnoff 10103b3a8eb9SGleb Smirnoff void 10112b29ceb8SKristof Provost pfctl_print_eth_rule_counters(struct pfctl_eth_rule *rule, int opts) 10122b29ceb8SKristof Provost { 10132b29ceb8SKristof Provost if (opts & PF_OPT_VERBOSE) { 10142b29ceb8SKristof Provost printf(" [ Evaluations: %-8llu Packets: %-8llu " 10152b29ceb8SKristof Provost "Bytes: %-10llu]\n", 10162b29ceb8SKristof Provost (unsigned long long)rule->evaluations, 10172b29ceb8SKristof Provost (unsigned long long)(rule->packets[0] + 10182b29ceb8SKristof Provost rule->packets[1]), 10192b29ceb8SKristof Provost (unsigned long long)(rule->bytes[0] + 10202b29ceb8SKristof Provost rule->bytes[1])); 10212b29ceb8SKristof Provost } 10220abcc1d2SReid Linnemann if (opts & PF_OPT_VERBOSE2) { 10230abcc1d2SReid Linnemann char timestr[30]; 10240abcc1d2SReid Linnemann 10250abcc1d2SReid Linnemann if (rule->last_active_timestamp != 0) { 10261d090028SKristof Provost bcopy(ctime(&rule->last_active_timestamp), timestr, 10271d090028SKristof Provost sizeof(timestr)); 10280abcc1d2SReid Linnemann *strchr(timestr, '\n') = '\0'; 10290abcc1d2SReid Linnemann } else { 10300abcc1d2SReid Linnemann snprintf(timestr, sizeof(timestr), "N/A"); 10310abcc1d2SReid Linnemann } 10320abcc1d2SReid Linnemann printf(" [ Last Active Time: %s ]\n", timestr); 10330abcc1d2SReid Linnemann } 10342b29ceb8SKristof Provost } 10352b29ceb8SKristof Provost 10362b29ceb8SKristof Provost void 1037e9eb0941SKristof Provost pfctl_print_rule_counters(struct pfctl_rule *rule, int opts) 10383b3a8eb9SGleb Smirnoff { 10393b3a8eb9SGleb Smirnoff if (opts & PF_OPT_DEBUG) { 10403b3a8eb9SGleb Smirnoff const char *t[PF_SKIP_COUNT] = { "i", "d", "f", 1041ee9f418cSKristof Provost "p", "sa", "da", "sp", "dp" }; 10423b3a8eb9SGleb Smirnoff int i; 10433b3a8eb9SGleb Smirnoff 10443b3a8eb9SGleb Smirnoff printf(" [ Skip steps: "); 10453b3a8eb9SGleb Smirnoff for (i = 0; i < PF_SKIP_COUNT; ++i) { 10463b3a8eb9SGleb Smirnoff if (rule->skip[i].nr == rule->nr + 1) 10473b3a8eb9SGleb Smirnoff continue; 10483b3a8eb9SGleb Smirnoff printf("%s=", t[i]); 10493b3a8eb9SGleb Smirnoff if (rule->skip[i].nr == -1) 10503b3a8eb9SGleb Smirnoff printf("end "); 10513b3a8eb9SGleb Smirnoff else 10523b3a8eb9SGleb Smirnoff printf("%u ", rule->skip[i].nr); 10533b3a8eb9SGleb Smirnoff } 10543b3a8eb9SGleb Smirnoff printf("]\n"); 10553b3a8eb9SGleb Smirnoff 10563b3a8eb9SGleb Smirnoff printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n", 10573b3a8eb9SGleb Smirnoff rule->qname, rule->qid, rule->pqname, rule->pqid); 10583b3a8eb9SGleb Smirnoff } 10593b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 10603b3a8eb9SGleb Smirnoff printf(" [ Evaluations: %-8llu Packets: %-8llu " 10615a9ab487SGleb Smirnoff "Bytes: %-10llu States: %-6ju]\n", 10623b3a8eb9SGleb Smirnoff (unsigned long long)rule->evaluations, 10633b3a8eb9SGleb Smirnoff (unsigned long long)(rule->packets[0] + 10643b3a8eb9SGleb Smirnoff rule->packets[1]), 10653b3a8eb9SGleb Smirnoff (unsigned long long)(rule->bytes[0] + 1066ab5707a5SKristof Provost rule->bytes[1]), (uintmax_t)rule->states_cur); 10673b3a8eb9SGleb Smirnoff if (!(opts & PF_OPT_DEBUG)) 10683b3a8eb9SGleb Smirnoff printf(" [ Inserted: uid %u pid %u " 10695a9ab487SGleb Smirnoff "State Creations: %-6ju]\n", 10703b3a8eb9SGleb Smirnoff (unsigned)rule->cuid, (unsigned)rule->cpid, 1071ab5707a5SKristof Provost (uintmax_t)rule->states_tot); 10723b3a8eb9SGleb Smirnoff } 10730abcc1d2SReid Linnemann if (opts & PF_OPT_VERBOSE2) { 10740abcc1d2SReid Linnemann char timestr[30]; 10750abcc1d2SReid Linnemann if (rule->last_active_timestamp != 0) { 10761d090028SKristof Provost bcopy(ctime(&rule->last_active_timestamp), timestr, 10771d090028SKristof Provost sizeof(timestr)); 10780abcc1d2SReid Linnemann *strchr(timestr, '\n') = '\0'; 10790abcc1d2SReid Linnemann } else { 10800abcc1d2SReid Linnemann snprintf(timestr, sizeof(timestr), "N/A"); 10810abcc1d2SReid Linnemann } 10820abcc1d2SReid Linnemann printf(" [ Last Active Time: %s ]\n", timestr); 10830abcc1d2SReid Linnemann } 10843b3a8eb9SGleb Smirnoff } 10853b3a8eb9SGleb Smirnoff 10863b3a8eb9SGleb Smirnoff void 10873b3a8eb9SGleb Smirnoff pfctl_print_title(char *title) 10883b3a8eb9SGleb Smirnoff { 10893b3a8eb9SGleb Smirnoff if (!first_title) 10903b3a8eb9SGleb Smirnoff printf("\n"); 10913b3a8eb9SGleb Smirnoff first_title = 0; 10923b3a8eb9SGleb Smirnoff printf("%s\n", title); 10933b3a8eb9SGleb Smirnoff } 10943b3a8eb9SGleb Smirnoff 10953b3a8eb9SGleb Smirnoff int 1096c5131afeSKristof Provost pfctl_show_eth_rules(int dev, char *path, int opts, enum pfctl_show format, 1097cfa1a130SKristof Provost char *anchorname, int depth, int wildcard) 10982b29ceb8SKristof Provost { 1099c5131afeSKristof Provost char anchor_call[MAXPATHLEN]; 11002b29ceb8SKristof Provost struct pfctl_eth_rules_info info; 11012b29ceb8SKristof Provost struct pfctl_eth_rule rule; 1102cfa1a130SKristof Provost int brace; 11032b29ceb8SKristof Provost int dotitle = opts & PF_OPT_SHOWALL; 1104c5131afeSKristof Provost int len = strlen(path); 1105375aaa29SKristof Provost int ret; 1106cfa1a130SKristof Provost char *npath, *p; 11072b29ceb8SKristof Provost 1108cfa1a130SKristof Provost /* 1109cfa1a130SKristof Provost * Truncate a trailing / and * on an anchorname before searching for 1110cfa1a130SKristof Provost * the ruleset, this is syntactic sugar that doesn't actually make it 1111cfa1a130SKristof Provost * to the kernel. 1112cfa1a130SKristof Provost */ 1113cfa1a130SKristof Provost if ((p = strrchr(anchorname, '/')) != NULL && 1114cfa1a130SKristof Provost p[1] == '*' && p[2] == '\0') { 1115cfa1a130SKristof Provost p[0] = '\0'; 1116cfa1a130SKristof Provost } 1117cfa1a130SKristof Provost 1118cfa1a130SKristof Provost if (anchorname[0] == '/') { 1119cfa1a130SKristof Provost if ((npath = calloc(1, MAXPATHLEN)) == NULL) 1120cfa1a130SKristof Provost errx(1, "pfctl_rules: calloc"); 1121cfa1a130SKristof Provost snprintf(npath, MAXPATHLEN, "%s", anchorname); 1122cfa1a130SKristof Provost } else { 1123c5131afeSKristof Provost if (path[0]) 1124c5131afeSKristof Provost snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 1125c5131afeSKristof Provost else 1126c5131afeSKristof Provost snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 1127cfa1a130SKristof Provost npath = path; 1128cfa1a130SKristof Provost } 1129cfa1a130SKristof Provost 1130cfa1a130SKristof Provost /* 1131cfa1a130SKristof Provost * If this anchor was called with a wildcard path, go through 1132cfa1a130SKristof Provost * the rulesets in the anchor rather than the rules. 1133cfa1a130SKristof Provost */ 1134cfa1a130SKristof Provost if (wildcard && (opts & PF_OPT_RECURSE)) { 1135cfa1a130SKristof Provost struct pfctl_eth_rulesets_info ri; 1136cfa1a130SKristof Provost u_int32_t mnr, nr; 1137cfa1a130SKristof Provost 1138375aaa29SKristof Provost if ((ret = pfctl_get_eth_rulesets_info(dev, &ri, npath)) != 0) { 1139375aaa29SKristof Provost if (ret == EINVAL) { 1140cfa1a130SKristof Provost fprintf(stderr, "Anchor '%s' " 1141cfa1a130SKristof Provost "not found.\n", anchorname); 1142cfa1a130SKristof Provost } else { 1143375aaa29SKristof Provost warnc(ret, "DIOCGETETHRULESETS"); 1144cfa1a130SKristof Provost return (-1); 1145cfa1a130SKristof Provost } 1146cfa1a130SKristof Provost } 1147cfa1a130SKristof Provost mnr = ri.nr; 1148cfa1a130SKristof Provost 1149cfa1a130SKristof Provost pfctl_print_eth_rule_counters(&rule, opts); 1150cfa1a130SKristof Provost for (nr = 0; nr < mnr; ++nr) { 1151cfa1a130SKristof Provost struct pfctl_eth_ruleset_info rs; 1152cfa1a130SKristof Provost 1153375aaa29SKristof Provost if ((ret = pfctl_get_eth_ruleset(dev, npath, nr, &rs)) != 0) 1154375aaa29SKristof Provost errc(1, ret, "DIOCGETETHRULESET"); 1155cfa1a130SKristof Provost INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1156cfa1a130SKristof Provost printf("anchor \"%s\" all {\n", rs.name); 1157cfa1a130SKristof Provost pfctl_show_eth_rules(dev, npath, opts, 1158cfa1a130SKristof Provost format, rs.name, depth + 1, 0); 1159cfa1a130SKristof Provost INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1160cfa1a130SKristof Provost printf("}\n"); 1161cfa1a130SKristof Provost } 1162cfa1a130SKristof Provost path[len] = '\0'; 1163cfa1a130SKristof Provost return (0); 1164cfa1a130SKristof Provost } 1165c5131afeSKristof Provost 1166375aaa29SKristof Provost if ((ret = pfctl_get_eth_rules_info(dev, &info, path)) != 0) { 1167375aaa29SKristof Provost warnc(ret, "DIOCGETETHRULES"); 11682b29ceb8SKristof Provost return (-1); 11692b29ceb8SKristof Provost } 11702b29ceb8SKristof Provost for (int nr = 0; nr < info.nr; nr++) { 1171c5131afeSKristof Provost brace = 0; 1172c5131afeSKristof Provost INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1173375aaa29SKristof Provost if ((ret = pfctl_get_eth_rule(dev, nr, info.ticket, path, &rule, 1174375aaa29SKristof Provost opts & PF_OPT_CLRRULECTRS, anchor_call)) != 0) { 1175375aaa29SKristof Provost warnc(ret, "DIOCGETETHRULE"); 11762b29ceb8SKristof Provost return (-1); 11772b29ceb8SKristof Provost } 1178c5131afeSKristof Provost if (anchor_call[0] && 1179c5131afeSKristof Provost ((((p = strrchr(anchor_call, '_')) != NULL) && 1180c5131afeSKristof Provost (p == anchor_call || 1181c5131afeSKristof Provost *(--p) == '/')) || (opts & PF_OPT_RECURSE))) { 1182c5131afeSKristof Provost brace++; 1183ed5eb77eSKristof Provost int aclen = strlen(anchor_call); 1184ed5eb77eSKristof Provost if (anchor_call[aclen - 1] == '*') 1185ed5eb77eSKristof Provost anchor_call[aclen - 2] = '\0'; 1186ed5eb77eSKristof Provost } 1187c5131afeSKristof Provost p = &anchor_call[0]; 11882b29ceb8SKristof Provost if (dotitle) { 11892b29ceb8SKristof Provost pfctl_print_title("ETH RULES:"); 11902b29ceb8SKristof Provost dotitle = 0; 11912b29ceb8SKristof Provost } 1192c5131afeSKristof Provost print_eth_rule(&rule, anchor_call, 1193c5131afeSKristof Provost opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG)); 1194c5131afeSKristof Provost if (brace) 1195c5131afeSKristof Provost printf(" {\n"); 1196c5131afeSKristof Provost else 11972b29ceb8SKristof Provost printf("\n"); 11982b29ceb8SKristof Provost pfctl_print_eth_rule_counters(&rule, opts); 1199c5131afeSKristof Provost if (brace) { 1200c5131afeSKristof Provost pfctl_show_eth_rules(dev, path, opts, format, 1201cfa1a130SKristof Provost p, depth + 1, rule.anchor_wildcard); 1202c5131afeSKristof Provost INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1203c5131afeSKristof Provost printf("}\n"); 1204c5131afeSKristof Provost } 12052b29ceb8SKristof Provost } 12062b29ceb8SKristof Provost 1207c5131afeSKristof Provost path[len] = '\0'; 12082b29ceb8SKristof Provost return (0); 12092b29ceb8SKristof Provost } 12102b29ceb8SKristof Provost 12112b29ceb8SKristof Provost int 12123b3a8eb9SGleb Smirnoff pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, 1213585a5ed0SKristof Provost char *anchorname, int depth, int wildcard) 12143b3a8eb9SGleb Smirnoff { 12158c1400b0SKristof Provost struct pfctl_rules_info ri; 1216e9eb0941SKristof Provost struct pfctl_rule rule; 12178c1400b0SKristof Provost char anchor_call[MAXPATHLEN]; 12188c1400b0SKristof Provost u_int32_t nr, header = 0; 12193b3a8eb9SGleb Smirnoff int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); 12203b3a8eb9SGleb Smirnoff int numeric = opts & PF_OPT_NUMERIC; 1221585a5ed0SKristof Provost int len = strlen(path), ret = 0; 1222585a5ed0SKristof Provost char *npath, *p; 12233b3a8eb9SGleb Smirnoff 1224585a5ed0SKristof Provost /* 1225585a5ed0SKristof Provost * Truncate a trailing / and * on an anchorname before searching for 1226585a5ed0SKristof Provost * the ruleset, this is syntactic sugar that doesn't actually make it 1227585a5ed0SKristof Provost * to the kernel. 1228585a5ed0SKristof Provost */ 1229585a5ed0SKristof Provost if ((p = strrchr(anchorname, '/')) != NULL && 1230585a5ed0SKristof Provost p[1] == '*' && p[2] == '\0') { 1231585a5ed0SKristof Provost p[0] = '\0'; 1232585a5ed0SKristof Provost } 1233585a5ed0SKristof Provost 1234585a5ed0SKristof Provost if (anchorname[0] == '/') { 1235585a5ed0SKristof Provost if ((npath = calloc(1, MAXPATHLEN)) == NULL) 1236585a5ed0SKristof Provost errx(1, "pfctl_rules: calloc"); 1237a8136ab4SKristof Provost strlcpy(npath, anchorname, MAXPATHLEN); 1238585a5ed0SKristof Provost } else { 12393b3a8eb9SGleb Smirnoff if (path[0]) 12403b3a8eb9SGleb Smirnoff snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 12413b3a8eb9SGleb Smirnoff else 12423b3a8eb9SGleb Smirnoff snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 1243585a5ed0SKristof Provost npath = path; 1244585a5ed0SKristof Provost } 1245585a5ed0SKristof Provost 1246585a5ed0SKristof Provost /* 1247585a5ed0SKristof Provost * If this anchor was called with a wildcard path, go through 1248585a5ed0SKristof Provost * the rulesets in the anchor rather than the rules. 1249585a5ed0SKristof Provost */ 1250585a5ed0SKristof Provost if (wildcard && (opts & PF_OPT_RECURSE)) { 1251585a5ed0SKristof Provost struct pfioc_ruleset prs; 1252585a5ed0SKristof Provost u_int32_t mnr, nr; 1253585a5ed0SKristof Provost 1254585a5ed0SKristof Provost memset(&prs, 0, sizeof(prs)); 125525e0f8f9SKristof Provost if ((ret = pfctl_get_rulesets(pfh, npath, &mnr)) != 0) { 125625e0f8f9SKristof Provost if (ret == EINVAL) 1257585a5ed0SKristof Provost fprintf(stderr, "Anchor '%s' " 1258585a5ed0SKristof Provost "not found.\n", anchorname); 1259585a5ed0SKristof Provost else 126025e0f8f9SKristof Provost errc(1, ret, "DIOCGETRULESETS"); 1261585a5ed0SKristof Provost } 1262585a5ed0SKristof Provost 1263585a5ed0SKristof Provost pfctl_print_rule_counters(&rule, opts); 1264585a5ed0SKristof Provost for (nr = 0; nr < mnr; ++nr) { 126548f5bf8bSKristof Provost if ((ret = pfctl_get_ruleset(pfh, npath, nr, &prs)) != 0) 126648f5bf8bSKristof Provost errc(1, ret, "DIOCGETRULESET"); 1267585a5ed0SKristof Provost INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1268585a5ed0SKristof Provost printf("anchor \"%s\" all {\n", prs.name); 1269585a5ed0SKristof Provost pfctl_show_rules(dev, npath, opts, 1270585a5ed0SKristof Provost format, prs.name, depth + 1, 0); 1271585a5ed0SKristof Provost INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1272585a5ed0SKristof Provost printf("}\n"); 1273585a5ed0SKristof Provost } 1274585a5ed0SKristof Provost path[len] = '\0'; 1275585a5ed0SKristof Provost return (0); 1276585a5ed0SKristof Provost } 12773b3a8eb9SGleb Smirnoff 12783b3a8eb9SGleb Smirnoff if (opts & PF_OPT_SHOWALL) { 1279f1612e70SKristof Provost ret = pfctl_get_rules_info_h(pfh, &ri, PF_PASS, path); 12808c1400b0SKristof Provost if (ret != 0) { 1281375aaa29SKristof Provost warnc(ret, "DIOCGETRULES"); 12823b3a8eb9SGleb Smirnoff goto error; 12833b3a8eb9SGleb Smirnoff } 12843b3a8eb9SGleb Smirnoff header++; 12853b3a8eb9SGleb Smirnoff } 1286f1612e70SKristof Provost ret = pfctl_get_rules_info_h(pfh, &ri, PF_SCRUB, path); 12878c1400b0SKristof Provost if (ret != 0) { 1288375aaa29SKristof Provost warnc(ret, "DIOCGETRULES"); 12893b3a8eb9SGleb Smirnoff goto error; 12903b3a8eb9SGleb Smirnoff } 12913b3a8eb9SGleb Smirnoff if (opts & PF_OPT_SHOWALL) { 12928c1400b0SKristof Provost if (format == PFCTL_SHOW_RULES && (ri.nr > 0 || header)) 12933b3a8eb9SGleb Smirnoff pfctl_print_title("FILTER RULES:"); 12943b3a8eb9SGleb Smirnoff else if (format == PFCTL_SHOW_LABELS && labels) 12953b3a8eb9SGleb Smirnoff pfctl_print_title("LABEL COUNTERS:"); 12963b3a8eb9SGleb Smirnoff } 12973b3a8eb9SGleb Smirnoff 12988c1400b0SKristof Provost for (nr = 0; nr < ri.nr; ++nr) { 1299375aaa29SKristof Provost if ((ret = pfctl_get_clear_rule_h(pfh, nr, ri.ticket, path, PF_SCRUB, 1300375aaa29SKristof Provost &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) != 0) { 1301375aaa29SKristof Provost warnc(ret, "DIOCGETRULENV"); 13023b3a8eb9SGleb Smirnoff goto error; 13033b3a8eb9SGleb Smirnoff } 13043b3a8eb9SGleb Smirnoff 1305096efeb6SKristof Provost if (pfctl_get_pool(dev, &rule.rdr, 1306aa69fdf1SKristof Provost nr, ri.ticket, PF_SCRUB, path, PF_RDR) != 0) 1307aa69fdf1SKristof Provost goto error; 1308aa69fdf1SKristof Provost 1309aa69fdf1SKristof Provost if (pfctl_get_pool(dev, &rule.nat, 1310aa69fdf1SKristof Provost nr, ri.ticket, PF_SCRUB, path, PF_NAT) != 0) 13113b3a8eb9SGleb Smirnoff goto error; 13123b3a8eb9SGleb Smirnoff 1313*0972294eSKristof Provost if (pfctl_get_pool(dev, &rule.route, 1314*0972294eSKristof Provost nr, ri.ticket, PF_SCRUB, path, PF_RT) != 0) 1315*0972294eSKristof Provost goto error; 1316*0972294eSKristof Provost 13173b3a8eb9SGleb Smirnoff switch (format) { 13183b3a8eb9SGleb Smirnoff case PFCTL_SHOW_LABELS: 13193b3a8eb9SGleb Smirnoff break; 13203b3a8eb9SGleb Smirnoff case PFCTL_SHOW_RULES: 1321cd80c52cSKristof Provost if (rule.label[0][0] && (opts & PF_OPT_SHOWALL)) 13223b3a8eb9SGleb Smirnoff labels = 1; 13238c1400b0SKristof Provost print_rule(&rule, anchor_call, rule_numbers, numeric); 13243b3a8eb9SGleb Smirnoff printf("\n"); 1325e9eb0941SKristof Provost pfctl_print_rule_counters(&rule, opts); 13263b3a8eb9SGleb Smirnoff break; 13273b3a8eb9SGleb Smirnoff case PFCTL_SHOW_NOTHING: 13283b3a8eb9SGleb Smirnoff break; 13293b3a8eb9SGleb Smirnoff } 1330096efeb6SKristof Provost pfctl_clear_pool(&rule.rdr); 13315cb08fddSKristof Provost pfctl_clear_pool(&rule.nat); 1332*0972294eSKristof Provost pfctl_clear_pool(&rule.route); 13333b3a8eb9SGleb Smirnoff } 1334f1612e70SKristof Provost ret = pfctl_get_rules_info_h(pfh, &ri, PF_PASS, path); 13358c1400b0SKristof Provost if (ret != 0) { 1336375aaa29SKristof Provost warnc(ret, "DIOCGETRULES"); 13373b3a8eb9SGleb Smirnoff goto error; 13383b3a8eb9SGleb Smirnoff } 13398c1400b0SKristof Provost for (nr = 0; nr < ri.nr; ++nr) { 1340375aaa29SKristof Provost if ((ret = pfctl_get_clear_rule_h(pfh, nr, ri.ticket, path, PF_PASS, 1341375aaa29SKristof Provost &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) != 0) { 1342375aaa29SKristof Provost warnc(ret, "DIOCGETRULE"); 13433b3a8eb9SGleb Smirnoff goto error; 13443b3a8eb9SGleb Smirnoff } 13453b3a8eb9SGleb Smirnoff 1346096efeb6SKristof Provost if (pfctl_get_pool(dev, &rule.rdr, 1347aa69fdf1SKristof Provost nr, ri.ticket, PF_PASS, path, PF_RDR) != 0) 1348aa69fdf1SKristof Provost goto error; 1349aa69fdf1SKristof Provost 1350aa69fdf1SKristof Provost if (pfctl_get_pool(dev, &rule.nat, 1351aa69fdf1SKristof Provost nr, ri.ticket, PF_PASS, path, PF_NAT) != 0) 13523b3a8eb9SGleb Smirnoff goto error; 13533b3a8eb9SGleb Smirnoff 1354*0972294eSKristof Provost if (pfctl_get_pool(dev, &rule.route, 1355*0972294eSKristof Provost nr, ri.ticket, PF_PASS, path, PF_RT) != 0) 1356*0972294eSKristof Provost goto error; 1357*0972294eSKristof Provost 13583b3a8eb9SGleb Smirnoff switch (format) { 13596fcc8e04SKristof Provost case PFCTL_SHOW_LABELS: { 13606fcc8e04SKristof Provost bool show = false; 13616fcc8e04SKristof Provost int i = 0; 13626fcc8e04SKristof Provost 13636fcc8e04SKristof Provost while (rule.label[i][0]) { 13646fcc8e04SKristof Provost printf("%s ", rule.label[i++]); 13656fcc8e04SKristof Provost show = true; 13666fcc8e04SKristof Provost } 13676fcc8e04SKristof Provost 13686fcc8e04SKristof Provost if (show) { 13696fcc8e04SKristof Provost printf("%llu %llu %llu %llu" 13705a9ab487SGleb Smirnoff " %llu %llu %llu %ju\n", 1371e9eb0941SKristof Provost (unsigned long long)rule.evaluations, 1372e9eb0941SKristof Provost (unsigned long long)(rule.packets[0] + 1373e9eb0941SKristof Provost rule.packets[1]), 1374e9eb0941SKristof Provost (unsigned long long)(rule.bytes[0] + 1375e9eb0941SKristof Provost rule.bytes[1]), 1376e9eb0941SKristof Provost (unsigned long long)rule.packets[0], 1377e9eb0941SKristof Provost (unsigned long long)rule.bytes[0], 1378e9eb0941SKristof Provost (unsigned long long)rule.packets[1], 1379e9eb0941SKristof Provost (unsigned long long)rule.bytes[1], 1380ab5707a5SKristof Provost (uintmax_t)rule.states_tot); 13813b3a8eb9SGleb Smirnoff } 13820187875aSLuiz Amaral 13830187875aSLuiz Amaral if (anchor_call[0] && 13840187875aSLuiz Amaral (((p = strrchr(anchor_call, '/')) ? 13850187875aSLuiz Amaral p[1] == '_' : anchor_call[0] == '_') || 13860187875aSLuiz Amaral opts & PF_OPT_RECURSE)) { 13870187875aSLuiz Amaral pfctl_show_rules(dev, npath, opts, format, 13880187875aSLuiz Amaral anchor_call, depth, rule.anchor_wildcard); 13890187875aSLuiz Amaral } 13903b3a8eb9SGleb Smirnoff break; 13916fcc8e04SKristof Provost } 13923b3a8eb9SGleb Smirnoff case PFCTL_SHOW_RULES: 1393cd80c52cSKristof Provost if (rule.label[0][0] && (opts & PF_OPT_SHOWALL)) 13943b3a8eb9SGleb Smirnoff labels = 1; 13953b3a8eb9SGleb Smirnoff INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1396585a5ed0SKristof Provost print_rule(&rule, anchor_call, rule_numbers, numeric); 13973b3a8eb9SGleb Smirnoff 1398585a5ed0SKristof Provost /* 1399585a5ed0SKristof Provost * If this is a 'unnamed' brace notation 1400585a5ed0SKristof Provost * anchor, OR the user has explicitly requested 1401585a5ed0SKristof Provost * recursion, print it recursively. 1402585a5ed0SKristof Provost */ 1403585a5ed0SKristof Provost if (anchor_call[0] && 1404585a5ed0SKristof Provost (((p = strrchr(anchor_call, '/')) ? 1405585a5ed0SKristof Provost p[1] == '_' : anchor_call[0] == '_') || 1406585a5ed0SKristof Provost opts & PF_OPT_RECURSE)) { 14073b3a8eb9SGleb Smirnoff printf(" {\n"); 1408e9eb0941SKristof Provost pfctl_print_rule_counters(&rule, opts); 1409585a5ed0SKristof Provost pfctl_show_rules(dev, npath, opts, format, 1410585a5ed0SKristof Provost anchor_call, depth + 1, 1411585a5ed0SKristof Provost rule.anchor_wildcard); 14123b3a8eb9SGleb Smirnoff INDENT(depth, !(opts & PF_OPT_VERBOSE)); 14133b3a8eb9SGleb Smirnoff printf("}\n"); 1414585a5ed0SKristof Provost } else { 1415585a5ed0SKristof Provost printf("\n"); 1416585a5ed0SKristof Provost pfctl_print_rule_counters(&rule, opts); 14173b3a8eb9SGleb Smirnoff } 14183b3a8eb9SGleb Smirnoff break; 14193b3a8eb9SGleb Smirnoff case PFCTL_SHOW_NOTHING: 14203b3a8eb9SGleb Smirnoff break; 14213b3a8eb9SGleb Smirnoff } 1422096efeb6SKristof Provost pfctl_clear_pool(&rule.rdr); 14235cb08fddSKristof Provost pfctl_clear_pool(&rule.nat); 14243b3a8eb9SGleb Smirnoff } 14253b3a8eb9SGleb Smirnoff 14263b3a8eb9SGleb Smirnoff error: 14273b3a8eb9SGleb Smirnoff path[len] = '\0'; 1428585a5ed0SKristof Provost return (ret); 14293b3a8eb9SGleb Smirnoff } 14303b3a8eb9SGleb Smirnoff 14313b3a8eb9SGleb Smirnoff int 14328ddd0359SKristof Provost pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth, 14338ddd0359SKristof Provost int wildcard) 14343b3a8eb9SGleb Smirnoff { 14358c1400b0SKristof Provost struct pfctl_rules_info ri; 1436e9eb0941SKristof Provost struct pfctl_rule rule; 14378c1400b0SKristof Provost char anchor_call[MAXPATHLEN]; 14388c1400b0SKristof Provost u_int32_t nr; 14393b3a8eb9SGleb Smirnoff static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT }; 14403b3a8eb9SGleb Smirnoff int i, dotitle = opts & PF_OPT_SHOWALL; 14418ddd0359SKristof Provost int ret; 1442a632d9e3SKristof Provost int len = strlen(path); 14438ddd0359SKristof Provost char *npath, *p; 14443b3a8eb9SGleb Smirnoff 14458ddd0359SKristof Provost /* 14468ddd0359SKristof Provost * Truncate a trailing / and * on an anchorname before searching for 14478ddd0359SKristof Provost * the ruleset, this is syntactic sugar that doesn't actually make it 14488ddd0359SKristof Provost * to the kernel. 14498ddd0359SKristof Provost */ 14508ddd0359SKristof Provost if ((p = strrchr(anchorname, '/')) != NULL && 14518ddd0359SKristof Provost p[1] == '*' && p[2] == '\0') { 14528ddd0359SKristof Provost p[0] = '\0'; 14538ddd0359SKristof Provost } 14548ddd0359SKristof Provost 14558ddd0359SKristof Provost if (anchorname[0] == '/') { 14568ddd0359SKristof Provost if ((npath = calloc(1, MAXPATHLEN)) == NULL) 14578ddd0359SKristof Provost errx(1, "pfctl_rules: calloc"); 14588ddd0359SKristof Provost snprintf(npath, MAXPATHLEN, "%s", anchorname); 14598ddd0359SKristof Provost } else { 1460a632d9e3SKristof Provost if (path[0]) 1461a632d9e3SKristof Provost snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname); 1462a632d9e3SKristof Provost else 1463a632d9e3SKristof Provost snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname); 14648ddd0359SKristof Provost npath = path; 14658ddd0359SKristof Provost } 14668ddd0359SKristof Provost 14678ddd0359SKristof Provost /* 14688ddd0359SKristof Provost * If this anchor was called with a wildcard path, go through 14698ddd0359SKristof Provost * the rulesets in the anchor rather than the rules. 14708ddd0359SKristof Provost */ 14718ddd0359SKristof Provost if (wildcard && (opts & PF_OPT_RECURSE)) { 14728ddd0359SKristof Provost struct pfioc_ruleset prs; 14738ddd0359SKristof Provost u_int32_t mnr, nr; 14748ddd0359SKristof Provost memset(&prs, 0, sizeof(prs)); 147525e0f8f9SKristof Provost if ((ret = pfctl_get_rulesets(pfh, npath, &mnr)) != 0) { 147625e0f8f9SKristof Provost if (ret == EINVAL) 14778ddd0359SKristof Provost fprintf(stderr, "NAT anchor '%s' " 14788ddd0359SKristof Provost "not found.\n", anchorname); 14798ddd0359SKristof Provost else 148025e0f8f9SKristof Provost errc(1, ret, "DIOCGETRULESETS"); 14818ddd0359SKristof Provost } 14828ddd0359SKristof Provost 14838ddd0359SKristof Provost pfctl_print_rule_counters(&rule, opts); 14848ddd0359SKristof Provost for (nr = 0; nr < mnr; ++nr) { 148548f5bf8bSKristof Provost if ((ret = pfctl_get_ruleset(pfh, npath, nr, &prs)) != 0) 148648f5bf8bSKristof Provost errc(1, ret, "DIOCGETRULESET"); 14878ddd0359SKristof Provost INDENT(depth, !(opts & PF_OPT_VERBOSE)); 14888ddd0359SKristof Provost printf("nat-anchor \"%s\" all {\n", prs.name); 14898ddd0359SKristof Provost pfctl_show_nat(dev, npath, opts, 14908ddd0359SKristof Provost prs.name, depth + 1, 0); 14918ddd0359SKristof Provost INDENT(depth, !(opts & PF_OPT_VERBOSE)); 14928ddd0359SKristof Provost printf("}\n"); 14938ddd0359SKristof Provost } 14948ddd0359SKristof Provost path[len] = '\0'; 14958ddd0359SKristof Provost return (0); 14968ddd0359SKristof Provost } 1497a632d9e3SKristof Provost 1498a20773c8SKristof Provost for (i = 0; i < 3; i++) { 1499f1612e70SKristof Provost ret = pfctl_get_rules_info_h(pfh, &ri, nattype[i], path); 15008c1400b0SKristof Provost if (ret != 0) { 1501375aaa29SKristof Provost warnc(ret, "DIOCGETRULES"); 15023b3a8eb9SGleb Smirnoff return (-1); 15033b3a8eb9SGleb Smirnoff } 15048c1400b0SKristof Provost for (nr = 0; nr < ri.nr; ++nr) { 1505a20773c8SKristof Provost INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1506a20773c8SKristof Provost 1507375aaa29SKristof Provost if ((ret = pfctl_get_rule_h(pfh, nr, ri.ticket, path, 1508375aaa29SKristof Provost nattype[i], &rule, anchor_call)) != 0) { 1509375aaa29SKristof Provost warnc(ret, "DIOCGETRULE"); 15103b3a8eb9SGleb Smirnoff return (-1); 15113b3a8eb9SGleb Smirnoff } 1512096efeb6SKristof Provost if (pfctl_get_pool(dev, &rule.rdr, nr, 1513aa69fdf1SKristof Provost ri.ticket, nattype[i], path, PF_RDR) != 0) 1514aa69fdf1SKristof Provost return (-1); 1515aa69fdf1SKristof Provost if (pfctl_get_pool(dev, &rule.nat, nr, 1516aa69fdf1SKristof Provost ri.ticket, nattype[i], path, PF_NAT) != 0) 15173b3a8eb9SGleb Smirnoff return (-1); 1518*0972294eSKristof Provost if (pfctl_get_pool(dev, &rule.route, nr, 1519*0972294eSKristof Provost ri.ticket, nattype[i], path, PF_RT) != 0) 1520*0972294eSKristof Provost return (-1); 1521a20773c8SKristof Provost 15223b3a8eb9SGleb Smirnoff if (dotitle) { 15233b3a8eb9SGleb Smirnoff pfctl_print_title("TRANSLATION RULES:"); 15243b3a8eb9SGleb Smirnoff dotitle = 0; 15253b3a8eb9SGleb Smirnoff } 15268c1400b0SKristof Provost print_rule(&rule, anchor_call, 15273b3a8eb9SGleb Smirnoff opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC); 15288ddd0359SKristof Provost if (anchor_call[0] && 15298ddd0359SKristof Provost (((p = strrchr(anchor_call, '/')) ? 15308ddd0359SKristof Provost p[1] == '_' : anchor_call[0] == '_') || 15318ddd0359SKristof Provost opts & PF_OPT_RECURSE)) { 1532a20773c8SKristof Provost printf(" {\n"); 1533e9eb0941SKristof Provost pfctl_print_rule_counters(&rule, opts); 15348ddd0359SKristof Provost pfctl_show_nat(dev, npath, opts, anchor_call, 15358ddd0359SKristof Provost depth + 1, rule.anchor_wildcard); 1536a20773c8SKristof Provost INDENT(depth, !(opts & PF_OPT_VERBOSE)); 1537a20773c8SKristof Provost printf("}\n"); 15388ddd0359SKristof Provost } else { 15398ddd0359SKristof Provost printf("\n"); 15408ddd0359SKristof Provost pfctl_print_rule_counters(&rule, opts); 1541a20773c8SKristof Provost } 15423b3a8eb9SGleb Smirnoff } 15433b3a8eb9SGleb Smirnoff } 15443b3a8eb9SGleb Smirnoff return (0); 15453b3a8eb9SGleb Smirnoff } 15463b3a8eb9SGleb Smirnoff 15479c125336SKristof Provost static int 15489c125336SKristof Provost pfctl_print_src_node(struct pfctl_src_node *sn, void *arg) 15499c125336SKristof Provost { 15509c125336SKristof Provost int *opts = (int *)arg; 15519c125336SKristof Provost 15529c125336SKristof Provost if (*opts & PF_OPT_SHOWALL) { 15539c125336SKristof Provost pfctl_print_title("SOURCE TRACKING NODES:"); 15549c125336SKristof Provost *opts &= ~PF_OPT_SHOWALL; 15559c125336SKristof Provost } 15569c125336SKristof Provost 15579c125336SKristof Provost print_src_node(sn, *opts); 15589c125336SKristof Provost 15599c125336SKristof Provost return (0); 15609c125336SKristof Provost } 15619c125336SKristof Provost 15623b3a8eb9SGleb Smirnoff int 15633b3a8eb9SGleb Smirnoff pfctl_show_src_nodes(int dev, int opts) 15643b3a8eb9SGleb Smirnoff { 15659c125336SKristof Provost int error; 15663b3a8eb9SGleb Smirnoff 15679c125336SKristof Provost error = pfctl_get_srcnodes(pfh, pfctl_print_src_node, &opts); 15689c125336SKristof Provost 15699c125336SKristof Provost return (error); 15703b3a8eb9SGleb Smirnoff } 15713b3a8eb9SGleb Smirnoff 1572f218b851SKristof Provost struct pfctl_show_state_arg { 1573f218b851SKristof Provost int opts; 1574f218b851SKristof Provost int dotitle; 1575f218b851SKristof Provost const char *iface; 1576f218b851SKristof Provost }; 1577f218b851SKristof Provost 1578f218b851SKristof Provost static int 1579f218b851SKristof Provost pfctl_show_state(struct pfctl_state *s, void *arg) 1580f218b851SKristof Provost { 1581f218b851SKristof Provost struct pfctl_show_state_arg *a = (struct pfctl_show_state_arg *)arg; 1582f218b851SKristof Provost 1583f218b851SKristof Provost if (a->dotitle) { 1584f218b851SKristof Provost pfctl_print_title("STATES:"); 1585f218b851SKristof Provost a->dotitle = 0; 1586f218b851SKristof Provost } 1587f218b851SKristof Provost print_state(s, a->opts); 1588f218b851SKristof Provost 1589f218b851SKristof Provost return (0); 1590f218b851SKristof Provost } 1591f218b851SKristof Provost 15923b3a8eb9SGleb Smirnoff int 15933b3a8eb9SGleb Smirnoff pfctl_show_states(int dev, const char *iface, int opts) 15943b3a8eb9SGleb Smirnoff { 1595f218b851SKristof Provost struct pfctl_show_state_arg arg; 1596044eef6aSKristof Provost struct pfctl_state_filter filter = {}; 1597044eef6aSKristof Provost 1598044eef6aSKristof Provost if (iface != NULL) 1599044eef6aSKristof Provost strncpy(filter.ifname, iface, IFNAMSIZ); 16003b3a8eb9SGleb Smirnoff 1601f218b851SKristof Provost arg.opts = opts; 1602f218b851SKristof Provost arg.dotitle = opts & PF_OPT_SHOWALL; 1603f218b851SKristof Provost arg.iface = iface; 1604bc941291SKristof Provost 1605044eef6aSKristof Provost if (pfctl_get_filtered_states_iter(&filter, pfctl_show_state, &arg)) 16063b3a8eb9SGleb Smirnoff return (-1); 1607bc941291SKristof Provost 16083b3a8eb9SGleb Smirnoff return (0); 16093b3a8eb9SGleb Smirnoff } 16103b3a8eb9SGleb Smirnoff 16113b3a8eb9SGleb Smirnoff int 16123b3a8eb9SGleb Smirnoff pfctl_show_status(int dev, int opts) 16133b3a8eb9SGleb Smirnoff { 161480078d9dSKristof Provost struct pfctl_status *status; 1615c69121c4SKristof Provost struct pfctl_syncookies cookies; 1616375aaa29SKristof Provost int ret; 16173b3a8eb9SGleb Smirnoff 16185824df8dSKristof Provost if ((status = pfctl_get_status_h(pfh)) == NULL) { 16193b3a8eb9SGleb Smirnoff warn("DIOCGETSTATUS"); 16203b3a8eb9SGleb Smirnoff return (-1); 16213b3a8eb9SGleb Smirnoff } 1622375aaa29SKristof Provost if ((ret = pfctl_get_syncookies(dev, &cookies)) != 0) { 162380078d9dSKristof Provost pfctl_free_status(status); 1624375aaa29SKristof Provost warnc(ret, "DIOCGETSYNCOOKIES"); 1625c69121c4SKristof Provost return (-1); 1626c69121c4SKristof Provost } 16273b3a8eb9SGleb Smirnoff if (opts & PF_OPT_SHOWALL) 16283b3a8eb9SGleb Smirnoff pfctl_print_title("INFO:"); 162980078d9dSKristof Provost print_status(status, &cookies, opts); 163080078d9dSKristof Provost pfctl_free_status(status); 16313b3a8eb9SGleb Smirnoff return (0); 16323b3a8eb9SGleb Smirnoff } 16333b3a8eb9SGleb Smirnoff 16343b3a8eb9SGleb Smirnoff int 1635fa1d4439SKristof Provost pfctl_show_running(int dev) 1636fa1d4439SKristof Provost { 163780078d9dSKristof Provost struct pfctl_status *status; 163880078d9dSKristof Provost int running; 1639fa1d4439SKristof Provost 16405824df8dSKristof Provost if ((status = pfctl_get_status_h(pfh)) == NULL) { 1641fa1d4439SKristof Provost warn("DIOCGETSTATUS"); 1642fa1d4439SKristof Provost return (-1); 1643fa1d4439SKristof Provost } 1644fa1d4439SKristof Provost 164580078d9dSKristof Provost running = status->running; 164680078d9dSKristof Provost 164780078d9dSKristof Provost print_running(status); 164880078d9dSKristof Provost pfctl_free_status(status); 164980078d9dSKristof Provost return (!running); 1650fa1d4439SKristof Provost } 1651fa1d4439SKristof Provost 1652fa1d4439SKristof Provost int 16533b3a8eb9SGleb Smirnoff pfctl_show_timeouts(int dev, int opts) 16543b3a8eb9SGleb Smirnoff { 165530bad751SKristof Provost uint32_t seconds; 16563b3a8eb9SGleb Smirnoff int i; 1657375aaa29SKristof Provost int ret; 16583b3a8eb9SGleb Smirnoff 16593b3a8eb9SGleb Smirnoff if (opts & PF_OPT_SHOWALL) 16603b3a8eb9SGleb Smirnoff pfctl_print_title("TIMEOUTS:"); 16613b3a8eb9SGleb Smirnoff for (i = 0; pf_timeouts[i].name; i++) { 1662375aaa29SKristof Provost if ((ret = pfctl_get_timeout(pfh, pf_timeouts[i].timeout, &seconds)) != 0) 1663375aaa29SKristof Provost errc(1, ret, "DIOCGETTIMEOUT"); 166430bad751SKristof Provost printf("%-20s %10d", pf_timeouts[i].name, seconds); 16653b3a8eb9SGleb Smirnoff if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START && 16663b3a8eb9SGleb Smirnoff pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END) 16673b3a8eb9SGleb Smirnoff printf(" states"); 16683b3a8eb9SGleb Smirnoff else 16693b3a8eb9SGleb Smirnoff printf("s"); 16703b3a8eb9SGleb Smirnoff printf("\n"); 16713b3a8eb9SGleb Smirnoff } 16723b3a8eb9SGleb Smirnoff return (0); 16733b3a8eb9SGleb Smirnoff 16743b3a8eb9SGleb Smirnoff } 16753b3a8eb9SGleb Smirnoff 16763b3a8eb9SGleb Smirnoff int 16773b3a8eb9SGleb Smirnoff pfctl_show_limits(int dev, int opts) 16783b3a8eb9SGleb Smirnoff { 1679d9ab8999SKristof Provost unsigned int limit; 16803b3a8eb9SGleb Smirnoff int i; 1681375aaa29SKristof Provost int ret; 16823b3a8eb9SGleb Smirnoff 16833b3a8eb9SGleb Smirnoff if (opts & PF_OPT_SHOWALL) 16843b3a8eb9SGleb Smirnoff pfctl_print_title("LIMITS:"); 16853b3a8eb9SGleb Smirnoff for (i = 0; pf_limits[i].name; i++) { 1686375aaa29SKristof Provost if ((ret = pfctl_get_limit(pfh, pf_limits[i].index, &limit)) != 0) 1687375aaa29SKristof Provost errc(1, ret, "DIOCGETLIMIT"); 16883b3a8eb9SGleb Smirnoff printf("%-13s ", pf_limits[i].name); 1689d9ab8999SKristof Provost if (limit == UINT_MAX) 16903b3a8eb9SGleb Smirnoff printf("unlimited\n"); 16913b3a8eb9SGleb Smirnoff else 1692d9ab8999SKristof Provost printf("hard limit %8u\n", limit); 16933b3a8eb9SGleb Smirnoff } 16943b3a8eb9SGleb Smirnoff return (0); 16953b3a8eb9SGleb Smirnoff } 16963b3a8eb9SGleb Smirnoff 1697a7191e5dSKristof Provost void 1698a7191e5dSKristof Provost pfctl_show_creators(int opts) 1699a7191e5dSKristof Provost { 1700a7191e5dSKristof Provost int ret; 1701a7191e5dSKristof Provost uint32_t creators[16]; 1702a7191e5dSKristof Provost size_t count = nitems(creators); 1703a7191e5dSKristof Provost 170466cacc14SKristof Provost ret = pfctl_get_creatorids(pfh, creators, &count); 1705a7191e5dSKristof Provost if (ret != 0) 1706a7191e5dSKristof Provost errx(ret, "Failed to retrieve creators"); 1707a7191e5dSKristof Provost 1708a7191e5dSKristof Provost printf("Creator IDs:\n"); 1709a7191e5dSKristof Provost for (size_t i = 0; i < count; i++) 1710a7191e5dSKristof Provost printf("%08x\n", creators[i]); 1711a7191e5dSKristof Provost } 1712a7191e5dSKristof Provost 17133b3a8eb9SGleb Smirnoff /* callbacks for rule/nat/rdr/addr */ 17143b3a8eb9SGleb Smirnoff int 1715e11dacbfSKristof Provost pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af, int which) 17163b3a8eb9SGleb Smirnoff { 17173b3a8eb9SGleb Smirnoff struct pf_pooladdr *pa; 1718375aaa29SKristof Provost int ret; 17193b3a8eb9SGleb Smirnoff 17203b3a8eb9SGleb Smirnoff pf->paddr.af = af; 17213b3a8eb9SGleb Smirnoff TAILQ_FOREACH(pa, &p->list, entries) { 17223b3a8eb9SGleb Smirnoff memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); 17233b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_NOACTION) == 0) { 1724e11dacbfSKristof Provost if ((ret = pfctl_add_addr(pf->h, &pf->paddr, which)) != 0) 1725375aaa29SKristof Provost errc(1, ret, "DIOCADDADDR"); 17263b3a8eb9SGleb Smirnoff } 17273b3a8eb9SGleb Smirnoff } 17283b3a8eb9SGleb Smirnoff return (0); 17293b3a8eb9SGleb Smirnoff } 17303b3a8eb9SGleb Smirnoff 17313b3a8eb9SGleb Smirnoff int 1732e9eb0941SKristof Provost pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r, 1733e9eb0941SKristof Provost const char *anchor_call) 17343b3a8eb9SGleb Smirnoff { 17353b3a8eb9SGleb Smirnoff u_int8_t rs_num; 1736e9eb0941SKristof Provost struct pfctl_rule *rule; 1737e9eb0941SKristof Provost struct pfctl_ruleset *rs; 17383b3a8eb9SGleb Smirnoff char *p; 17393b3a8eb9SGleb Smirnoff 17403b3a8eb9SGleb Smirnoff rs_num = pf_get_ruleset_number(r->action); 17413b3a8eb9SGleb Smirnoff if (rs_num == PF_RULESET_MAX) 17423b3a8eb9SGleb Smirnoff errx(1, "Invalid rule type %d", r->action); 17433b3a8eb9SGleb Smirnoff 17443b3a8eb9SGleb Smirnoff rs = &pf->anchor->ruleset; 17453b3a8eb9SGleb Smirnoff 17463b3a8eb9SGleb Smirnoff if (anchor_call[0] && r->anchor == NULL) { 17473b3a8eb9SGleb Smirnoff /* 17483b3a8eb9SGleb Smirnoff * Don't make non-brace anchors part of the main anchor pool. 17493b3a8eb9SGleb Smirnoff */ 17503b3a8eb9SGleb Smirnoff if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 17510d71f9f3SKristof Provost err(1, "pfctl_append_rule: calloc"); 17523b3a8eb9SGleb Smirnoff 17533b3a8eb9SGleb Smirnoff pf_init_ruleset(&r->anchor->ruleset); 17543b3a8eb9SGleb Smirnoff r->anchor->ruleset.anchor = r->anchor; 17553b3a8eb9SGleb Smirnoff if (strlcpy(r->anchor->path, anchor_call, 17563b3a8eb9SGleb Smirnoff sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 17570d71f9f3SKristof Provost errx(1, "pfctl_append_rule: strlcpy"); 17583b3a8eb9SGleb Smirnoff if ((p = strrchr(anchor_call, '/')) != NULL) { 17593b3a8eb9SGleb Smirnoff if (!strlen(p)) 17600d71f9f3SKristof Provost err(1, "pfctl_append_rule: bad anchor name %s", 17613b3a8eb9SGleb Smirnoff anchor_call); 17623b3a8eb9SGleb Smirnoff } else 17633b3a8eb9SGleb Smirnoff p = (char *)anchor_call; 17643b3a8eb9SGleb Smirnoff if (strlcpy(r->anchor->name, p, 17653b3a8eb9SGleb Smirnoff sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 17660d71f9f3SKristof Provost errx(1, "pfctl_append_rule: strlcpy"); 17673b3a8eb9SGleb Smirnoff } 17683b3a8eb9SGleb Smirnoff 17693b3a8eb9SGleb Smirnoff if ((rule = calloc(1, sizeof(*rule))) == NULL) 17703b3a8eb9SGleb Smirnoff err(1, "calloc"); 17713b3a8eb9SGleb Smirnoff bcopy(r, rule, sizeof(*rule)); 1772096efeb6SKristof Provost TAILQ_INIT(&rule->rdr.list); 1773096efeb6SKristof Provost pfctl_move_pool(&r->rdr, &rule->rdr); 17745cb08fddSKristof Provost TAILQ_INIT(&rule->nat.list); 17755cb08fddSKristof Provost pfctl_move_pool(&r->nat, &rule->nat); 1776*0972294eSKristof Provost TAILQ_INIT(&rule->route.list); 1777*0972294eSKristof Provost pfctl_move_pool(&r->route, &rule->route); 17783b3a8eb9SGleb Smirnoff 17793b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries); 17803b3a8eb9SGleb Smirnoff return (0); 17813b3a8eb9SGleb Smirnoff } 17823b3a8eb9SGleb Smirnoff 17833b3a8eb9SGleb Smirnoff int 1784c5131afeSKristof Provost pfctl_append_eth_rule(struct pfctl *pf, struct pfctl_eth_rule *r, 1785c5131afeSKristof Provost const char *anchor_call) 1786c5131afeSKristof Provost { 1787c5131afeSKristof Provost struct pfctl_eth_rule *rule; 1788c5131afeSKristof Provost struct pfctl_eth_ruleset *rs; 1789c5131afeSKristof Provost char *p; 1790c5131afeSKristof Provost 1791c5131afeSKristof Provost rs = &pf->eanchor->ruleset; 1792c5131afeSKristof Provost 1793c5131afeSKristof Provost if (anchor_call[0] && r->anchor == NULL) { 1794c5131afeSKristof Provost /* 1795c5131afeSKristof Provost * Don't make non-brace anchors part of the main anchor pool. 1796c5131afeSKristof Provost */ 1797c5131afeSKristof Provost if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) 1798c5131afeSKristof Provost err(1, "pfctl_append_rule: calloc"); 1799c5131afeSKristof Provost 1800c5131afeSKristof Provost pf_init_eth_ruleset(&r->anchor->ruleset); 1801c5131afeSKristof Provost r->anchor->ruleset.anchor = r->anchor; 1802c5131afeSKristof Provost if (strlcpy(r->anchor->path, anchor_call, 1803c5131afeSKristof Provost sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path)) 1804c5131afeSKristof Provost errx(1, "pfctl_append_rule: strlcpy"); 1805c5131afeSKristof Provost if ((p = strrchr(anchor_call, '/')) != NULL) { 1806c5131afeSKristof Provost if (!strlen(p)) 1807c5131afeSKristof Provost err(1, "pfctl_append_eth_rule: bad anchor name %s", 1808c5131afeSKristof Provost anchor_call); 1809c5131afeSKristof Provost } else 1810c5131afeSKristof Provost p = (char *)anchor_call; 1811c5131afeSKristof Provost if (strlcpy(r->anchor->name, p, 1812c5131afeSKristof Provost sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name)) 1813c5131afeSKristof Provost errx(1, "pfctl_append_eth_rule: strlcpy"); 1814c5131afeSKristof Provost } 1815c5131afeSKristof Provost 1816c5131afeSKristof Provost if ((rule = calloc(1, sizeof(*rule))) == NULL) 1817c5131afeSKristof Provost err(1, "calloc"); 1818c5131afeSKristof Provost bcopy(r, rule, sizeof(*rule)); 1819c5131afeSKristof Provost 1820c5131afeSKristof Provost TAILQ_INSERT_TAIL(&rs->rules, rule, entries); 1821c5131afeSKristof Provost return (0); 1822c5131afeSKristof Provost } 1823c5131afeSKristof Provost 1824c5131afeSKristof Provost int 1825c5131afeSKristof Provost pfctl_eth_ruleset_trans(struct pfctl *pf, char *path, 1826c5131afeSKristof Provost struct pfctl_eth_anchor *a) 18273b3a8eb9SGleb Smirnoff { 18283b3a8eb9SGleb Smirnoff int osize = pf->trans->pfrb_size; 18293b3a8eb9SGleb Smirnoff 18302b29ceb8SKristof Provost if ((pf->loadopt & PFCTL_FLAG_ETH) != 0) { 18312b29ceb8SKristof Provost if (pfctl_add_trans(pf->trans, PF_RULESET_ETH, path)) 18322b29ceb8SKristof Provost return (1); 18332b29ceb8SKristof Provost } 1834c5131afeSKristof Provost if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 1835c5131afeSKristof Provost return (5); 1836c5131afeSKristof Provost 1837c5131afeSKristof Provost return (0); 1838c5131afeSKristof Provost } 1839c5131afeSKristof Provost 1840c5131afeSKristof Provost int 1841c5131afeSKristof Provost pfctl_ruleset_trans(struct pfctl *pf, char *path, struct pfctl_anchor *a, bool do_eth) 1842c5131afeSKristof Provost { 1843c5131afeSKristof Provost int osize = pf->trans->pfrb_size; 1844c5131afeSKristof Provost 1845c5131afeSKristof Provost if ((pf->loadopt & PFCTL_FLAG_ETH) != 0 && do_eth) { 1846c5131afeSKristof Provost if (pfctl_add_trans(pf->trans, PF_RULESET_ETH, path)) 1847c5131afeSKristof Provost return (1); 18482b29ceb8SKristof Provost } 18493b3a8eb9SGleb Smirnoff if ((pf->loadopt & PFCTL_FLAG_NAT) != 0) { 18503b3a8eb9SGleb Smirnoff if (pfctl_add_trans(pf->trans, PF_RULESET_NAT, path) || 18513b3a8eb9SGleb Smirnoff pfctl_add_trans(pf->trans, PF_RULESET_BINAT, path) || 18523b3a8eb9SGleb Smirnoff pfctl_add_trans(pf->trans, PF_RULESET_RDR, path)) 18533b3a8eb9SGleb Smirnoff return (1); 18543b3a8eb9SGleb Smirnoff } 18553b3a8eb9SGleb Smirnoff if (a == pf->astack[0] && ((altqsupport && 18563b3a8eb9SGleb Smirnoff (pf->loadopt & PFCTL_FLAG_ALTQ) != 0))) { 18573b3a8eb9SGleb Smirnoff if (pfctl_add_trans(pf->trans, PF_RULESET_ALTQ, path)) 18583b3a8eb9SGleb Smirnoff return (2); 18593b3a8eb9SGleb Smirnoff } 18603b3a8eb9SGleb Smirnoff if ((pf->loadopt & PFCTL_FLAG_FILTER) != 0) { 18613b3a8eb9SGleb Smirnoff if (pfctl_add_trans(pf->trans, PF_RULESET_SCRUB, path) || 18623b3a8eb9SGleb Smirnoff pfctl_add_trans(pf->trans, PF_RULESET_FILTER, path)) 18633b3a8eb9SGleb Smirnoff return (3); 18643b3a8eb9SGleb Smirnoff } 18653b3a8eb9SGleb Smirnoff if (pf->loadopt & PFCTL_FLAG_TABLE) 18663b3a8eb9SGleb Smirnoff if (pfctl_add_trans(pf->trans, PF_RULESET_TABLE, path)) 18673b3a8eb9SGleb Smirnoff return (4); 18683b3a8eb9SGleb Smirnoff if (pfctl_trans(pf->dev, pf->trans, DIOCXBEGIN, osize)) 18693b3a8eb9SGleb Smirnoff return (5); 18703b3a8eb9SGleb Smirnoff 18713b3a8eb9SGleb Smirnoff return (0); 18723b3a8eb9SGleb Smirnoff } 18733b3a8eb9SGleb Smirnoff 18743b3a8eb9SGleb Smirnoff int 1875c5131afeSKristof Provost pfctl_load_eth_ruleset(struct pfctl *pf, char *path, 1876c5131afeSKristof Provost struct pfctl_eth_ruleset *rs, int depth) 18772b29ceb8SKristof Provost { 18782b29ceb8SKristof Provost struct pfctl_eth_rule *r; 1879c5131afeSKristof Provost int error, len = strlen(path); 1880c5131afeSKristof Provost int brace = 0; 18812b29ceb8SKristof Provost 1882c5131afeSKristof Provost pf->eanchor = rs->anchor; 1883c5131afeSKristof Provost if (path[0]) 1884c5131afeSKristof Provost snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->eanchor->name); 1885c5131afeSKristof Provost else 1886c5131afeSKristof Provost snprintf(&path[len], MAXPATHLEN - len, "%s", pf->eanchor->name); 18872b29ceb8SKristof Provost 1888c5131afeSKristof Provost if (depth) { 1889c5131afeSKristof Provost if (TAILQ_FIRST(&rs->rules) != NULL) { 1890c5131afeSKristof Provost brace++; 1891c5131afeSKristof Provost if (pf->opts & PF_OPT_VERBOSE) 1892c5131afeSKristof Provost printf(" {\n"); 1893c5131afeSKristof Provost if ((pf->opts & PF_OPT_NOACTION) == 0 && 1894c5131afeSKristof Provost (error = pfctl_eth_ruleset_trans(pf, 1895c5131afeSKristof Provost path, rs->anchor))) { 1896c5131afeSKristof Provost printf("pfctl_load_eth_rulesets: " 1897c5131afeSKristof Provost "pfctl_eth_ruleset_trans %d\n", error); 1898c5131afeSKristof Provost goto error; 1899c5131afeSKristof Provost } 1900c5131afeSKristof Provost } else if (pf->opts & PF_OPT_VERBOSE) 1901c5131afeSKristof Provost printf("\n"); 1902c5131afeSKristof Provost } 1903c5131afeSKristof Provost 1904c5131afeSKristof Provost while ((r = TAILQ_FIRST(&rs->rules)) != NULL) { 1905c5131afeSKristof Provost TAILQ_REMOVE(&rs->rules, r, entries); 1906c5131afeSKristof Provost 1907c5131afeSKristof Provost error = pfctl_load_eth_rule(pf, path, r, depth); 19082b29ceb8SKristof Provost if (error) 19092b29ceb8SKristof Provost return (error); 1910c5131afeSKristof Provost 1911c5131afeSKristof Provost if (r->anchor) { 1912c5131afeSKristof Provost if ((error = pfctl_load_eth_ruleset(pf, path, 1913c5131afeSKristof Provost &r->anchor->ruleset, depth + 1))) 1914c5131afeSKristof Provost return (error); 1915c32cd180SKristof Provost } else if (pf->opts & PF_OPT_VERBOSE) 1916c32cd180SKristof Provost printf("\n"); 1917c5131afeSKristof Provost free(r); 1918c5131afeSKristof Provost } 1919c5131afeSKristof Provost if (brace && pf->opts & PF_OPT_VERBOSE) { 1920c5131afeSKristof Provost INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 1921c5131afeSKristof Provost printf("}\n"); 1922c5131afeSKristof Provost } 1923c5131afeSKristof Provost path[len] = '\0'; 1924c5131afeSKristof Provost 1925c5131afeSKristof Provost return (0); 1926c5131afeSKristof Provost error: 1927c5131afeSKristof Provost path[len] = '\0'; 1928c5131afeSKristof Provost return (error); 19292b29ceb8SKristof Provost } 19302b29ceb8SKristof Provost 1931c5131afeSKristof Provost int 1932c5131afeSKristof Provost pfctl_load_eth_rule(struct pfctl *pf, char *path, struct pfctl_eth_rule *r, 1933c5131afeSKristof Provost int depth) 1934c5131afeSKristof Provost { 1935c5131afeSKristof Provost char *name; 1936c5131afeSKristof Provost char anchor[PF_ANCHOR_NAME_SIZE]; 1937c5131afeSKristof Provost int len = strlen(path); 1938375aaa29SKristof Provost int ret; 1939c5131afeSKristof Provost 1940c5131afeSKristof Provost if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor)) 1941c5131afeSKristof Provost errx(1, "pfctl_load_eth_rule: strlcpy"); 1942c5131afeSKristof Provost 1943c5131afeSKristof Provost if (r->anchor) { 1944c5131afeSKristof Provost if (r->anchor->match) { 1945c5131afeSKristof Provost if (path[0]) 1946c5131afeSKristof Provost snprintf(&path[len], MAXPATHLEN - len, 1947c5131afeSKristof Provost "/%s", r->anchor->name); 1948c5131afeSKristof Provost else 1949c5131afeSKristof Provost snprintf(&path[len], MAXPATHLEN - len, 1950c5131afeSKristof Provost "%s", r->anchor->name); 1951c5131afeSKristof Provost name = r->anchor->name; 1952c5131afeSKristof Provost } else 1953c5131afeSKristof Provost name = r->anchor->path; 1954c5131afeSKristof Provost } else 1955c5131afeSKristof Provost name = ""; 1956c5131afeSKristof Provost 1957c5131afeSKristof Provost if ((pf->opts & PF_OPT_NOACTION) == 0) 1958375aaa29SKristof Provost if ((ret = pfctl_add_eth_rule(pf->dev, r, anchor, name, 1959375aaa29SKristof Provost pf->eth_ticket)) != 0) 1960375aaa29SKristof Provost errc(1, ret, "DIOCADDETHRULENV"); 1961c5131afeSKristof Provost 1962c32cd180SKristof Provost if (pf->opts & PF_OPT_VERBOSE) { 1963c32cd180SKristof Provost INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 1964c32cd180SKristof Provost print_eth_rule(r, r->anchor ? r->anchor->name : "", 1965c32cd180SKristof Provost pf->opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG)); 1966c32cd180SKristof Provost } 1967c32cd180SKristof Provost 1968c5131afeSKristof Provost path[len] = '\0'; 19692b29ceb8SKristof Provost 19702b29ceb8SKristof Provost return (0); 19712b29ceb8SKristof Provost } 19722b29ceb8SKristof Provost 19732b29ceb8SKristof Provost int 1974e9eb0941SKristof Provost pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs, 19753b3a8eb9SGleb Smirnoff int rs_num, int depth) 19763b3a8eb9SGleb Smirnoff { 1977e9eb0941SKristof Provost struct pfctl_rule *r; 19783b3a8eb9SGleb Smirnoff int error, len = strlen(path); 19793b3a8eb9SGleb Smirnoff int brace = 0; 19803b3a8eb9SGleb Smirnoff 19813b3a8eb9SGleb Smirnoff pf->anchor = rs->anchor; 19823b3a8eb9SGleb Smirnoff 19833b3a8eb9SGleb Smirnoff if (path[0]) 19843b3a8eb9SGleb Smirnoff snprintf(&path[len], MAXPATHLEN - len, "/%s", pf->anchor->name); 19853b3a8eb9SGleb Smirnoff else 19863b3a8eb9SGleb Smirnoff snprintf(&path[len], MAXPATHLEN - len, "%s", pf->anchor->name); 19873b3a8eb9SGleb Smirnoff 19883b3a8eb9SGleb Smirnoff if (depth) { 19893b3a8eb9SGleb Smirnoff if (TAILQ_FIRST(rs->rules[rs_num].active.ptr) != NULL) { 19903b3a8eb9SGleb Smirnoff brace++; 19913b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 19923b3a8eb9SGleb Smirnoff printf(" {\n"); 19933b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_NOACTION) == 0 && 19943b3a8eb9SGleb Smirnoff (error = pfctl_ruleset_trans(pf, 1995c5131afeSKristof Provost path, rs->anchor, false))) { 19963b3a8eb9SGleb Smirnoff printf("pfctl_load_rulesets: " 19973b3a8eb9SGleb Smirnoff "pfctl_ruleset_trans %d\n", error); 19983b3a8eb9SGleb Smirnoff goto error; 19993b3a8eb9SGleb Smirnoff } 20003b3a8eb9SGleb Smirnoff } else if (pf->opts & PF_OPT_VERBOSE) 20013b3a8eb9SGleb Smirnoff printf("\n"); 20023b3a8eb9SGleb Smirnoff 20033b3a8eb9SGleb Smirnoff } 20043b3a8eb9SGleb Smirnoff 20053b3a8eb9SGleb Smirnoff if (pf->optimize && rs_num == PF_RULESET_FILTER) 20063b3a8eb9SGleb Smirnoff pfctl_optimize_ruleset(pf, rs); 20073b3a8eb9SGleb Smirnoff 20083b3a8eb9SGleb Smirnoff while ((r = TAILQ_FIRST(rs->rules[rs_num].active.ptr)) != NULL) { 20093b3a8eb9SGleb Smirnoff TAILQ_REMOVE(rs->rules[rs_num].active.ptr, r, entries); 201009c7f238SKristof Provost 201109c7f238SKristof Provost for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) 201209c7f238SKristof Provost expand_label(r->label[i], PF_RULE_LABEL_SIZE, r); 201309c7f238SKristof Provost expand_label(r->tagname, PF_TAG_NAME_SIZE, r); 201409c7f238SKristof Provost expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r); 201509c7f238SKristof Provost 20163b3a8eb9SGleb Smirnoff if ((error = pfctl_load_rule(pf, path, r, depth))) 20173b3a8eb9SGleb Smirnoff goto error; 20183b3a8eb9SGleb Smirnoff if (r->anchor) { 20193b3a8eb9SGleb Smirnoff if ((error = pfctl_load_ruleset(pf, path, 20203b3a8eb9SGleb Smirnoff &r->anchor->ruleset, rs_num, depth + 1))) 20213b3a8eb9SGleb Smirnoff goto error; 20223b3a8eb9SGleb Smirnoff } else if (pf->opts & PF_OPT_VERBOSE) 20233b3a8eb9SGleb Smirnoff printf("\n"); 20243b3a8eb9SGleb Smirnoff free(r); 20253b3a8eb9SGleb Smirnoff } 20263b3a8eb9SGleb Smirnoff if (brace && pf->opts & PF_OPT_VERBOSE) { 20273b3a8eb9SGleb Smirnoff INDENT(depth - 1, (pf->opts & PF_OPT_VERBOSE)); 20283b3a8eb9SGleb Smirnoff printf("}\n"); 20293b3a8eb9SGleb Smirnoff } 20303b3a8eb9SGleb Smirnoff path[len] = '\0'; 20313b3a8eb9SGleb Smirnoff return (0); 20323b3a8eb9SGleb Smirnoff 20333b3a8eb9SGleb Smirnoff error: 20343b3a8eb9SGleb Smirnoff path[len] = '\0'; 20353b3a8eb9SGleb Smirnoff return (error); 20363b3a8eb9SGleb Smirnoff 20373b3a8eb9SGleb Smirnoff } 20383b3a8eb9SGleb Smirnoff 20393b3a8eb9SGleb Smirnoff int 2040e9eb0941SKristof Provost pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth) 20413b3a8eb9SGleb Smirnoff { 20423b3a8eb9SGleb Smirnoff u_int8_t rs_num = pf_get_ruleset_number(r->action); 20433b3a8eb9SGleb Smirnoff char *name; 20445c11c5a3SKristof Provost u_int32_t ticket; 20455c11c5a3SKristof Provost char anchor[PF_ANCHOR_NAME_SIZE]; 20463b3a8eb9SGleb Smirnoff int len = strlen(path); 2047c4a08ef2SMateusz Guzik int error; 2048c4a08ef2SMateusz Guzik bool was_present; 20493b3a8eb9SGleb Smirnoff 20503b3a8eb9SGleb Smirnoff /* set up anchor before adding to path for anchor_call */ 20513b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_NOACTION) == 0) 20525c11c5a3SKristof Provost ticket = pfctl_get_ticket(pf->trans, rs_num, path); 20535c11c5a3SKristof Provost if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor)) 20543b3a8eb9SGleb Smirnoff errx(1, "pfctl_load_rule: strlcpy"); 20553b3a8eb9SGleb Smirnoff 20563b3a8eb9SGleb Smirnoff if (r->anchor) { 20573b3a8eb9SGleb Smirnoff if (r->anchor->match) { 20583b3a8eb9SGleb Smirnoff if (path[0]) 20593b3a8eb9SGleb Smirnoff snprintf(&path[len], MAXPATHLEN - len, 20603b3a8eb9SGleb Smirnoff "/%s", r->anchor->name); 20613b3a8eb9SGleb Smirnoff else 20623b3a8eb9SGleb Smirnoff snprintf(&path[len], MAXPATHLEN - len, 20633b3a8eb9SGleb Smirnoff "%s", r->anchor->name); 20642fd47deaSKristof Provost name = r->anchor->name; 20653b3a8eb9SGleb Smirnoff } else 20663b3a8eb9SGleb Smirnoff name = r->anchor->path; 20673b3a8eb9SGleb Smirnoff } else 20683b3a8eb9SGleb Smirnoff name = ""; 20693b3a8eb9SGleb Smirnoff 2070c4a08ef2SMateusz Guzik was_present = false; 20713b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_NOACTION) == 0) { 2072aa69fdf1SKristof Provost if ((pf->opts & PF_OPT_NOACTION) == 0) { 2073aa69fdf1SKristof Provost if ((error = pfctl_begin_addrs(pf->h, 2074aa69fdf1SKristof Provost &pf->paddr.ticket)) != 0) 2075aa69fdf1SKristof Provost errc(1, error, "DIOCBEGINADDRS"); 2076aa69fdf1SKristof Provost } 2077aa69fdf1SKristof Provost 2078096efeb6SKristof Provost if (pfctl_add_pool(pf, &r->rdr, r->af, PF_RDR)) 20793b3a8eb9SGleb Smirnoff return (1); 2080aa69fdf1SKristof Provost if (pfctl_add_pool(pf, &r->nat, r->naf ? r->naf : r->af, PF_NAT)) 2081aa69fdf1SKristof Provost return (1); 2082*0972294eSKristof Provost if (pfctl_add_pool(pf, &r->route, r->af, PF_RT)) 2083*0972294eSKristof Provost return (1); 208476bc4a77SKristof Provost error = pfctl_add_rule_h(pf->h, r, anchor, name, ticket, 2085c4a08ef2SMateusz Guzik pf->paddr.ticket); 2086c4a08ef2SMateusz Guzik switch (error) { 2087c4a08ef2SMateusz Guzik case 0: 2088c4a08ef2SMateusz Guzik /* things worked, do nothing */ 2089c4a08ef2SMateusz Guzik break; 2090c4a08ef2SMateusz Guzik case EEXIST: 2091c4a08ef2SMateusz Guzik /* an identical rule is already present */ 2092c4a08ef2SMateusz Guzik was_present = true; 2093c4a08ef2SMateusz Guzik break; 2094c4a08ef2SMateusz Guzik default: 2095375aaa29SKristof Provost errc(1, error, "DIOCADDRULE"); 20963b3a8eb9SGleb Smirnoff } 2097c4a08ef2SMateusz Guzik } 20983b3a8eb9SGleb Smirnoff 20993b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) { 21003b3a8eb9SGleb Smirnoff INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); 2101585a5ed0SKristof Provost print_rule(r, name, 21023b3a8eb9SGleb Smirnoff pf->opts & PF_OPT_VERBOSE2, 21033b3a8eb9SGleb Smirnoff pf->opts & PF_OPT_NUMERIC); 2104c4a08ef2SMateusz Guzik if (was_present) 2105c4a08ef2SMateusz Guzik printf(" -- rule was already present"); 21063b3a8eb9SGleb Smirnoff } 21073b3a8eb9SGleb Smirnoff path[len] = '\0'; 2108096efeb6SKristof Provost pfctl_clear_pool(&r->rdr); 21095cb08fddSKristof Provost pfctl_clear_pool(&r->nat); 21103b3a8eb9SGleb Smirnoff return (0); 21113b3a8eb9SGleb Smirnoff } 21123b3a8eb9SGleb Smirnoff 21133b3a8eb9SGleb Smirnoff int 21143b3a8eb9SGleb Smirnoff pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 21153b3a8eb9SGleb Smirnoff { 21163b3a8eb9SGleb Smirnoff if (altqsupport && 21173b3a8eb9SGleb Smirnoff (loadopt & PFCTL_FLAG_ALTQ) != 0) { 21183b3a8eb9SGleb Smirnoff memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq)); 21193b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_NOACTION) == 0) { 21203b3a8eb9SGleb Smirnoff if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) { 21213b3a8eb9SGleb Smirnoff if (errno == ENXIO) 21223b3a8eb9SGleb Smirnoff errx(1, "qtype not configured"); 21233b3a8eb9SGleb Smirnoff else if (errno == ENODEV) 21243b3a8eb9SGleb Smirnoff errx(1, "%s: driver does not support " 21253b3a8eb9SGleb Smirnoff "altq", a->ifname); 21263b3a8eb9SGleb Smirnoff else 21273b3a8eb9SGleb Smirnoff err(1, "DIOCADDALTQ"); 21283b3a8eb9SGleb Smirnoff } 21293b3a8eb9SGleb Smirnoff } 21303b3a8eb9SGleb Smirnoff pfaltq_store(&pf->paltq->altq); 21313b3a8eb9SGleb Smirnoff } 21323b3a8eb9SGleb Smirnoff return (0); 21333b3a8eb9SGleb Smirnoff } 21343b3a8eb9SGleb Smirnoff 21353b3a8eb9SGleb Smirnoff int 21363b3a8eb9SGleb Smirnoff pfctl_rules(int dev, char *filename, int opts, int optimize, 21373b3a8eb9SGleb Smirnoff char *anchorname, struct pfr_buffer *trans) 21383b3a8eb9SGleb Smirnoff { 21393b3a8eb9SGleb Smirnoff #define ERR(x) do { warn(x); goto _error; } while(0) 21403b3a8eb9SGleb Smirnoff #define ERRX(x) do { warnx(x); goto _error; } while(0) 21413b3a8eb9SGleb Smirnoff 21423b3a8eb9SGleb Smirnoff struct pfr_buffer *t, buf; 21433b3a8eb9SGleb Smirnoff struct pfioc_altq pa; 21443b3a8eb9SGleb Smirnoff struct pfctl pf; 2145e9eb0941SKristof Provost struct pfctl_ruleset *rs; 2146c5131afeSKristof Provost struct pfctl_eth_ruleset *ethrs; 21473b3a8eb9SGleb Smirnoff struct pfr_table trs; 21483b3a8eb9SGleb Smirnoff char *path; 21493b3a8eb9SGleb Smirnoff int osize; 21503b3a8eb9SGleb Smirnoff 21513b3a8eb9SGleb Smirnoff RB_INIT(&pf_anchors); 21523b3a8eb9SGleb Smirnoff memset(&pf_main_anchor, 0, sizeof(pf_main_anchor)); 21533b3a8eb9SGleb Smirnoff pf_init_ruleset(&pf_main_anchor.ruleset); 21543b3a8eb9SGleb Smirnoff pf_main_anchor.ruleset.anchor = &pf_main_anchor; 2155c5131afeSKristof Provost 2156c5131afeSKristof Provost memset(&pf_eth_main_anchor, 0, sizeof(pf_eth_main_anchor)); 2157c5131afeSKristof Provost pf_init_eth_ruleset(&pf_eth_main_anchor.ruleset); 2158c5131afeSKristof Provost pf_eth_main_anchor.ruleset.anchor = &pf_eth_main_anchor; 2159c5131afeSKristof Provost 21603b3a8eb9SGleb Smirnoff if (trans == NULL) { 21613b3a8eb9SGleb Smirnoff bzero(&buf, sizeof(buf)); 21623b3a8eb9SGleb Smirnoff buf.pfrb_type = PFRB_TRANS; 21633b3a8eb9SGleb Smirnoff t = &buf; 21643b3a8eb9SGleb Smirnoff osize = 0; 21653b3a8eb9SGleb Smirnoff } else { 21663b3a8eb9SGleb Smirnoff t = trans; 21673b3a8eb9SGleb Smirnoff osize = t->pfrb_size; 21683b3a8eb9SGleb Smirnoff } 21693b3a8eb9SGleb Smirnoff 21703b3a8eb9SGleb Smirnoff memset(&pa, 0, sizeof(pa)); 2171249cc75fSPatrick Kelsey pa.version = PFIOC_ALTQ_VERSION; 21723b3a8eb9SGleb Smirnoff memset(&pf, 0, sizeof(pf)); 21733b3a8eb9SGleb Smirnoff memset(&trs, 0, sizeof(trs)); 21743b3a8eb9SGleb Smirnoff if ((path = calloc(1, MAXPATHLEN)) == NULL) 21753b3a8eb9SGleb Smirnoff ERRX("pfctl_rules: calloc"); 21763b3a8eb9SGleb Smirnoff if (strlcpy(trs.pfrt_anchor, anchorname, 21773b3a8eb9SGleb Smirnoff sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor)) 21783b3a8eb9SGleb Smirnoff ERRX("pfctl_rules: strlcpy"); 21793b3a8eb9SGleb Smirnoff pf.dev = dev; 2180f1612e70SKristof Provost pf.h = pfh; 21813b3a8eb9SGleb Smirnoff pf.opts = opts; 21823b3a8eb9SGleb Smirnoff pf.optimize = optimize; 21833b3a8eb9SGleb Smirnoff pf.loadopt = loadopt; 21843b3a8eb9SGleb Smirnoff 21853b3a8eb9SGleb Smirnoff /* non-brace anchor, create without resolving the path */ 21863b3a8eb9SGleb Smirnoff if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL) 21873b3a8eb9SGleb Smirnoff ERRX("pfctl_rules: calloc"); 21883b3a8eb9SGleb Smirnoff rs = &pf.anchor->ruleset; 21893b3a8eb9SGleb Smirnoff pf_init_ruleset(rs); 21903b3a8eb9SGleb Smirnoff rs->anchor = pf.anchor; 21913b3a8eb9SGleb Smirnoff if (strlcpy(pf.anchor->path, anchorname, 21923b3a8eb9SGleb Smirnoff sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 2193c5131afeSKristof Provost errx(1, "pfctl_rules: strlcpy"); 21943b3a8eb9SGleb Smirnoff if (strlcpy(pf.anchor->name, anchorname, 21953b3a8eb9SGleb Smirnoff sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 2196c5131afeSKristof Provost errx(1, "pfctl_rules: strlcpy"); 21973b3a8eb9SGleb Smirnoff 21983b3a8eb9SGleb Smirnoff 21993b3a8eb9SGleb Smirnoff pf.astack[0] = pf.anchor; 22003b3a8eb9SGleb Smirnoff pf.asd = 0; 22013b3a8eb9SGleb Smirnoff if (anchorname[0]) 22023b3a8eb9SGleb Smirnoff pf.loadopt &= ~PFCTL_FLAG_ALTQ; 22033b3a8eb9SGleb Smirnoff pf.paltq = &pa; 22043b3a8eb9SGleb Smirnoff pf.trans = t; 22053b3a8eb9SGleb Smirnoff pfctl_init_options(&pf); 22063b3a8eb9SGleb Smirnoff 2207c5131afeSKristof Provost /* Set up ethernet anchor */ 2208c5131afeSKristof Provost if ((pf.eanchor = calloc(1, sizeof(*pf.eanchor))) == NULL) 2209c5131afeSKristof Provost ERRX("pfctl_rules: calloc"); 2210c5131afeSKristof Provost 2211c5131afeSKristof Provost if (strlcpy(pf.eanchor->path, anchorname, 2212c5131afeSKristof Provost sizeof(pf.eanchor->path)) >= sizeof(pf.eanchor->path)) 2213c5131afeSKristof Provost errx(1, "pfctl_rules: strlcpy"); 2214c5131afeSKristof Provost if (strlcpy(pf.eanchor->name, anchorname, 2215c5131afeSKristof Provost sizeof(pf.eanchor->name)) >= sizeof(pf.eanchor->name)) 2216c5131afeSKristof Provost errx(1, "pfctl_rules: strlcpy"); 2217c5131afeSKristof Provost 2218c5131afeSKristof Provost ethrs = &pf.eanchor->ruleset; 2219c5131afeSKristof Provost pf_init_eth_ruleset(ethrs); 2220c5131afeSKristof Provost ethrs->anchor = pf.eanchor; 2221c5131afeSKristof Provost pf.eastack[0] = pf.eanchor; 2222c5131afeSKristof Provost 22233b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_NOACTION) == 0) { 22243b3a8eb9SGleb Smirnoff /* 22253b3a8eb9SGleb Smirnoff * XXX For the time being we need to open transactions for 22263b3a8eb9SGleb Smirnoff * the main ruleset before parsing, because tables are still 22273b3a8eb9SGleb Smirnoff * loaded at parse time. 22283b3a8eb9SGleb Smirnoff */ 2229c5131afeSKristof Provost if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor, true)) 22303b3a8eb9SGleb Smirnoff ERRX("pfctl_rules"); 22312b29ceb8SKristof Provost if (pf.loadopt & PFCTL_FLAG_ETH) 22322b29ceb8SKristof Provost pf.eth_ticket = pfctl_get_ticket(t, PF_RULESET_ETH, anchorname); 22333b3a8eb9SGleb Smirnoff if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ)) 22343b3a8eb9SGleb Smirnoff pa.ticket = 22353b3a8eb9SGleb Smirnoff pfctl_get_ticket(t, PF_RULESET_ALTQ, anchorname); 22363b3a8eb9SGleb Smirnoff if (pf.loadopt & PFCTL_FLAG_TABLE) 22373b3a8eb9SGleb Smirnoff pf.astack[0]->ruleset.tticket = 22383b3a8eb9SGleb Smirnoff pfctl_get_ticket(t, PF_RULESET_TABLE, anchorname); 22393b3a8eb9SGleb Smirnoff } 22403b3a8eb9SGleb Smirnoff 22413b3a8eb9SGleb Smirnoff if (parse_config(filename, &pf) < 0) { 22423b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_NOACTION) == 0) 22433b3a8eb9SGleb Smirnoff ERRX("Syntax error in config file: " 22443b3a8eb9SGleb Smirnoff "pf rules not loaded"); 22453b3a8eb9SGleb Smirnoff else 22463b3a8eb9SGleb Smirnoff goto _error; 22473b3a8eb9SGleb Smirnoff } 2248c5e10565SKristof Provost if (loadopt & PFCTL_FLAG_OPTION) 22497a831fecSKristof Provost pfctl_adjust_skip_ifaces(&pf); 22503b3a8eb9SGleb Smirnoff 22513b3a8eb9SGleb Smirnoff if ((pf.loadopt & PFCTL_FLAG_FILTER && 22523b3a8eb9SGleb Smirnoff (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) || 22532b29ceb8SKristof Provost (pf.loadopt & PFCTL_FLAG_ETH && 2254c5131afeSKristof Provost (pfctl_load_eth_ruleset(&pf, path, ethrs, 0))) || 22553b3a8eb9SGleb Smirnoff (pf.loadopt & PFCTL_FLAG_NAT && 22563b3a8eb9SGleb Smirnoff (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_NAT, 0) || 22573b3a8eb9SGleb Smirnoff pfctl_load_ruleset(&pf, path, rs, PF_RULESET_RDR, 0) || 22583b3a8eb9SGleb Smirnoff pfctl_load_ruleset(&pf, path, rs, PF_RULESET_BINAT, 0))) || 22593b3a8eb9SGleb Smirnoff (pf.loadopt & PFCTL_FLAG_FILTER && 22603b3a8eb9SGleb Smirnoff pfctl_load_ruleset(&pf, path, rs, PF_RULESET_FILTER, 0))) { 22613b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_NOACTION) == 0) 22623b3a8eb9SGleb Smirnoff ERRX("Unable to load rules into kernel"); 22633b3a8eb9SGleb Smirnoff else 22643b3a8eb9SGleb Smirnoff goto _error; 22653b3a8eb9SGleb Smirnoff } 22663b3a8eb9SGleb Smirnoff 22673b3a8eb9SGleb Smirnoff if ((altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ) != 0)) 22683b3a8eb9SGleb Smirnoff if (check_commit_altq(dev, opts) != 0) 22693b3a8eb9SGleb Smirnoff ERRX("errors in altq config"); 22703b3a8eb9SGleb Smirnoff 22713b3a8eb9SGleb Smirnoff /* process "load anchor" directives */ 22723b3a8eb9SGleb Smirnoff if (!anchorname[0]) 22733b3a8eb9SGleb Smirnoff if (pfctl_load_anchors(dev, &pf, t) == -1) 22743b3a8eb9SGleb Smirnoff ERRX("load anchors"); 22753b3a8eb9SGleb Smirnoff 22763b3a8eb9SGleb Smirnoff if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) { 22773b3a8eb9SGleb Smirnoff if (!anchorname[0]) 22783b3a8eb9SGleb Smirnoff if (pfctl_load_options(&pf)) 22793b3a8eb9SGleb Smirnoff goto _error; 22803b3a8eb9SGleb Smirnoff if (pfctl_trans(dev, t, DIOCXCOMMIT, osize)) 22813b3a8eb9SGleb Smirnoff ERR("DIOCXCOMMIT"); 22823b3a8eb9SGleb Smirnoff } 228307695000SWarner Losh free(path); 22843b3a8eb9SGleb Smirnoff return (0); 22853b3a8eb9SGleb Smirnoff 22863b3a8eb9SGleb Smirnoff _error: 22873b3a8eb9SGleb Smirnoff if (trans == NULL) { /* main ruleset */ 22883b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_NOACTION) == 0) 22893b3a8eb9SGleb Smirnoff if (pfctl_trans(dev, t, DIOCXROLLBACK, osize)) 22903b3a8eb9SGleb Smirnoff err(1, "DIOCXROLLBACK"); 22913b3a8eb9SGleb Smirnoff exit(1); 22923b3a8eb9SGleb Smirnoff } else { /* sub ruleset */ 229307695000SWarner Losh free(path); 22943b3a8eb9SGleb Smirnoff return (-1); 22953b3a8eb9SGleb Smirnoff } 22963b3a8eb9SGleb Smirnoff 22973b3a8eb9SGleb Smirnoff #undef ERR 22983b3a8eb9SGleb Smirnoff #undef ERRX 22993b3a8eb9SGleb Smirnoff } 23003b3a8eb9SGleb Smirnoff 23013b3a8eb9SGleb Smirnoff FILE * 23023b3a8eb9SGleb Smirnoff pfctl_fopen(const char *name, const char *mode) 23033b3a8eb9SGleb Smirnoff { 23043b3a8eb9SGleb Smirnoff struct stat st; 23053b3a8eb9SGleb Smirnoff FILE *fp; 23063b3a8eb9SGleb Smirnoff 23073b3a8eb9SGleb Smirnoff fp = fopen(name, mode); 23083b3a8eb9SGleb Smirnoff if (fp == NULL) 23093b3a8eb9SGleb Smirnoff return (NULL); 23103b3a8eb9SGleb Smirnoff if (fstat(fileno(fp), &st)) { 23113b3a8eb9SGleb Smirnoff fclose(fp); 23123b3a8eb9SGleb Smirnoff return (NULL); 23133b3a8eb9SGleb Smirnoff } 23143b3a8eb9SGleb Smirnoff if (S_ISDIR(st.st_mode)) { 23153b3a8eb9SGleb Smirnoff fclose(fp); 23163b3a8eb9SGleb Smirnoff errno = EISDIR; 23173b3a8eb9SGleb Smirnoff return (NULL); 23183b3a8eb9SGleb Smirnoff } 23193b3a8eb9SGleb Smirnoff return (fp); 23203b3a8eb9SGleb Smirnoff } 23213b3a8eb9SGleb Smirnoff 23223b3a8eb9SGleb Smirnoff void 23233b3a8eb9SGleb Smirnoff pfctl_init_options(struct pfctl *pf) 23243b3a8eb9SGleb Smirnoff { 23253b3a8eb9SGleb Smirnoff 23263b3a8eb9SGleb Smirnoff pf->timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 23273b3a8eb9SGleb Smirnoff pf->timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL; 23283b3a8eb9SGleb Smirnoff pf->timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 23293b3a8eb9SGleb Smirnoff pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL; 23303b3a8eb9SGleb Smirnoff pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL; 23313b3a8eb9SGleb Smirnoff pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL; 2332ca9dbde8SKristof Provost pf->timeout[PFTM_SCTP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL; 2333ca9dbde8SKristof Provost pf->timeout[PFTM_SCTP_OPENING] = PFTM_TCP_OPENING_VAL; 2334ca9dbde8SKristof Provost pf->timeout[PFTM_SCTP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL; 2335ca9dbde8SKristof Provost pf->timeout[PFTM_SCTP_CLOSING] = PFTM_TCP_CLOSING_VAL; 2336ca9dbde8SKristof Provost pf->timeout[PFTM_SCTP_CLOSED] = PFTM_TCP_CLOSED_VAL; 23373b3a8eb9SGleb Smirnoff pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL; 23383b3a8eb9SGleb Smirnoff pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL; 23393b3a8eb9SGleb Smirnoff pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL; 23403b3a8eb9SGleb Smirnoff pf->timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL; 23413b3a8eb9SGleb Smirnoff pf->timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL; 23423b3a8eb9SGleb Smirnoff pf->timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL; 23433b3a8eb9SGleb Smirnoff pf->timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL; 23443b3a8eb9SGleb Smirnoff pf->timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL; 23453b3a8eb9SGleb Smirnoff pf->timeout[PFTM_FRAG] = PFTM_FRAG_VAL; 23463b3a8eb9SGleb Smirnoff pf->timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL; 23473b3a8eb9SGleb Smirnoff pf->timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL; 23483b3a8eb9SGleb Smirnoff pf->timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL; 23493b3a8eb9SGleb Smirnoff pf->timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START; 23503b3a8eb9SGleb Smirnoff pf->timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END; 23513b3a8eb9SGleb Smirnoff 23523b3a8eb9SGleb Smirnoff pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT; 23533b3a8eb9SGleb Smirnoff pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT; 23543b3a8eb9SGleb Smirnoff pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT; 23553b3a8eb9SGleb Smirnoff pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT; 23563b3a8eb9SGleb Smirnoff 23573b3a8eb9SGleb Smirnoff pf->debug = PF_DEBUG_URGENT; 235839282ef3SKajetan Staszkiewicz pf->reassemble = 0; 23595062afffSKristof Provost 23605062afffSKristof Provost pf->syncookies = false; 23615062afffSKristof Provost pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT; 23625062afffSKristof Provost pf->syncookieswat[1] = PF_SYNCOOKIES_HIWATPCT; 23633b3a8eb9SGleb Smirnoff } 23643b3a8eb9SGleb Smirnoff 23653b3a8eb9SGleb Smirnoff int 23663b3a8eb9SGleb Smirnoff pfctl_load_options(struct pfctl *pf) 23673b3a8eb9SGleb Smirnoff { 23683b3a8eb9SGleb Smirnoff int i, error = 0; 23693b3a8eb9SGleb Smirnoff 23703b3a8eb9SGleb Smirnoff if ((loadopt & PFCTL_FLAG_OPTION) == 0) 23713b3a8eb9SGleb Smirnoff return (0); 23723b3a8eb9SGleb Smirnoff 23733b3a8eb9SGleb Smirnoff /* load limits */ 23743b3a8eb9SGleb Smirnoff for (i = 0; i < PF_LIMIT_MAX; i++) { 23753b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_MERGE) && !pf->limit_set[i]) 23763b3a8eb9SGleb Smirnoff continue; 23773b3a8eb9SGleb Smirnoff if (pfctl_load_limit(pf, i, pf->limit[i])) 23783b3a8eb9SGleb Smirnoff error = 1; 23793b3a8eb9SGleb Smirnoff } 23803b3a8eb9SGleb Smirnoff 23813b3a8eb9SGleb Smirnoff /* 23823b3a8eb9SGleb Smirnoff * If we've set the limit, but haven't explicitly set adaptive 23833b3a8eb9SGleb Smirnoff * timeouts, do it now with a start of 60% and end of 120%. 23843b3a8eb9SGleb Smirnoff */ 23853b3a8eb9SGleb Smirnoff if (pf->limit_set[PF_LIMIT_STATES] && 23863b3a8eb9SGleb Smirnoff !pf->timeout_set[PFTM_ADAPTIVE_START] && 23873b3a8eb9SGleb Smirnoff !pf->timeout_set[PFTM_ADAPTIVE_END]) { 23883b3a8eb9SGleb Smirnoff pf->timeout[PFTM_ADAPTIVE_START] = 23893b3a8eb9SGleb Smirnoff (pf->limit[PF_LIMIT_STATES] / 10) * 6; 23903b3a8eb9SGleb Smirnoff pf->timeout_set[PFTM_ADAPTIVE_START] = 1; 23913b3a8eb9SGleb Smirnoff pf->timeout[PFTM_ADAPTIVE_END] = 23923b3a8eb9SGleb Smirnoff (pf->limit[PF_LIMIT_STATES] / 10) * 12; 23933b3a8eb9SGleb Smirnoff pf->timeout_set[PFTM_ADAPTIVE_END] = 1; 23943b3a8eb9SGleb Smirnoff } 23953b3a8eb9SGleb Smirnoff 23963b3a8eb9SGleb Smirnoff /* load timeouts */ 23973b3a8eb9SGleb Smirnoff for (i = 0; i < PFTM_MAX; i++) { 23983b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_MERGE) && !pf->timeout_set[i]) 23993b3a8eb9SGleb Smirnoff continue; 24003b3a8eb9SGleb Smirnoff if (pfctl_load_timeout(pf, i, pf->timeout[i])) 24013b3a8eb9SGleb Smirnoff error = 1; 24023b3a8eb9SGleb Smirnoff } 24033b3a8eb9SGleb Smirnoff 24043b3a8eb9SGleb Smirnoff /* load debug */ 24053b3a8eb9SGleb Smirnoff if (!(pf->opts & PF_OPT_MERGE) || pf->debug_set) 24063b3a8eb9SGleb Smirnoff if (pfctl_load_debug(pf, pf->debug)) 24073b3a8eb9SGleb Smirnoff error = 1; 24083b3a8eb9SGleb Smirnoff 24093b3a8eb9SGleb Smirnoff /* load logif */ 24103b3a8eb9SGleb Smirnoff if (!(pf->opts & PF_OPT_MERGE) || pf->ifname_set) 24113b3a8eb9SGleb Smirnoff if (pfctl_load_logif(pf, pf->ifname)) 24123b3a8eb9SGleb Smirnoff error = 1; 24133b3a8eb9SGleb Smirnoff 24143b3a8eb9SGleb Smirnoff /* load hostid */ 24153b3a8eb9SGleb Smirnoff if (!(pf->opts & PF_OPT_MERGE) || pf->hostid_set) 24163b3a8eb9SGleb Smirnoff if (pfctl_load_hostid(pf, pf->hostid)) 24173b3a8eb9SGleb Smirnoff error = 1; 24183b3a8eb9SGleb Smirnoff 241939282ef3SKajetan Staszkiewicz /* load reassembly settings */ 242039282ef3SKajetan Staszkiewicz if (!(pf->opts & PF_OPT_MERGE) || pf->reass_set) 242139282ef3SKajetan Staszkiewicz if (pfctl_load_reassembly(pf, pf->reassemble)) 242239282ef3SKajetan Staszkiewicz error = 1; 242339282ef3SKajetan Staszkiewicz 242442ec75f8SKristof Provost /* load keepcounters */ 242542ec75f8SKristof Provost if (pfctl_set_keepcounters(pf->dev, pf->keep_counters)) 242642ec75f8SKristof Provost error = 1; 242742ec75f8SKristof Provost 2428c69121c4SKristof Provost /* load syncookies settings */ 2429c69121c4SKristof Provost if (pfctl_load_syncookies(pf, pf->syncookies)) 2430c69121c4SKristof Provost error = 1; 2431c69121c4SKristof Provost 24323b3a8eb9SGleb Smirnoff return (error); 24333b3a8eb9SGleb Smirnoff } 24343b3a8eb9SGleb Smirnoff 24353b3a8eb9SGleb Smirnoff int 2436d9ab8999SKristof Provost pfctl_apply_limit(struct pfctl *pf, const char *opt, unsigned int limit) 24373b3a8eb9SGleb Smirnoff { 24383b3a8eb9SGleb Smirnoff int i; 24393b3a8eb9SGleb Smirnoff 24403b3a8eb9SGleb Smirnoff 24413b3a8eb9SGleb Smirnoff for (i = 0; pf_limits[i].name; i++) { 24423b3a8eb9SGleb Smirnoff if (strcasecmp(opt, pf_limits[i].name) == 0) { 24433b3a8eb9SGleb Smirnoff pf->limit[pf_limits[i].index] = limit; 24443b3a8eb9SGleb Smirnoff pf->limit_set[pf_limits[i].index] = 1; 24453b3a8eb9SGleb Smirnoff break; 24463b3a8eb9SGleb Smirnoff } 24473b3a8eb9SGleb Smirnoff } 24483b3a8eb9SGleb Smirnoff if (pf_limits[i].name == NULL) { 24493b3a8eb9SGleb Smirnoff warnx("Bad pool name."); 24503b3a8eb9SGleb Smirnoff return (1); 24513b3a8eb9SGleb Smirnoff } 24523b3a8eb9SGleb Smirnoff 24533b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 24543b3a8eb9SGleb Smirnoff printf("set limit %s %d\n", opt, limit); 24553b3a8eb9SGleb Smirnoff 24563b3a8eb9SGleb Smirnoff return (0); 24573b3a8eb9SGleb Smirnoff } 24583b3a8eb9SGleb Smirnoff 24593b3a8eb9SGleb Smirnoff int 24603b3a8eb9SGleb Smirnoff pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit) 24613b3a8eb9SGleb Smirnoff { 2462d9ab8999SKristof Provost if (pfctl_set_limit(pf->h, index, limit)) { 24633b3a8eb9SGleb Smirnoff if (errno == EBUSY) 24643b3a8eb9SGleb Smirnoff warnx("Current pool size exceeds requested hard limit"); 24653b3a8eb9SGleb Smirnoff else 24663b3a8eb9SGleb Smirnoff warnx("DIOCSETLIMIT"); 24673b3a8eb9SGleb Smirnoff return (1); 24683b3a8eb9SGleb Smirnoff } 24693b3a8eb9SGleb Smirnoff return (0); 24703b3a8eb9SGleb Smirnoff } 24713b3a8eb9SGleb Smirnoff 24723b3a8eb9SGleb Smirnoff int 247330bad751SKristof Provost pfctl_apply_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 24743b3a8eb9SGleb Smirnoff { 24753b3a8eb9SGleb Smirnoff int i; 24763b3a8eb9SGleb Smirnoff 24773b3a8eb9SGleb Smirnoff if ((loadopt & PFCTL_FLAG_OPTION) == 0) 24783b3a8eb9SGleb Smirnoff return (0); 24793b3a8eb9SGleb Smirnoff 24803b3a8eb9SGleb Smirnoff for (i = 0; pf_timeouts[i].name; i++) { 24813b3a8eb9SGleb Smirnoff if (strcasecmp(opt, pf_timeouts[i].name) == 0) { 24823b3a8eb9SGleb Smirnoff pf->timeout[pf_timeouts[i].timeout] = seconds; 24833b3a8eb9SGleb Smirnoff pf->timeout_set[pf_timeouts[i].timeout] = 1; 24843b3a8eb9SGleb Smirnoff break; 24853b3a8eb9SGleb Smirnoff } 24863b3a8eb9SGleb Smirnoff } 24873b3a8eb9SGleb Smirnoff 24883b3a8eb9SGleb Smirnoff if (pf_timeouts[i].name == NULL) { 24893b3a8eb9SGleb Smirnoff warnx("Bad timeout name."); 24903b3a8eb9SGleb Smirnoff return (1); 24913b3a8eb9SGleb Smirnoff } 24923b3a8eb9SGleb Smirnoff 24933b3a8eb9SGleb Smirnoff 24943b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE && ! quiet) 24953b3a8eb9SGleb Smirnoff printf("set timeout %s %d\n", opt, seconds); 24963b3a8eb9SGleb Smirnoff 24973b3a8eb9SGleb Smirnoff return (0); 24983b3a8eb9SGleb Smirnoff } 24993b3a8eb9SGleb Smirnoff 25003b3a8eb9SGleb Smirnoff int 25013b3a8eb9SGleb Smirnoff pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds) 25023b3a8eb9SGleb Smirnoff { 250330bad751SKristof Provost if (pfctl_set_timeout(pf->h, timeout, seconds)) { 25043b3a8eb9SGleb Smirnoff warnx("DIOCSETTIMEOUT"); 25053b3a8eb9SGleb Smirnoff return (1); 25063b3a8eb9SGleb Smirnoff } 25073b3a8eb9SGleb Smirnoff return (0); 25083b3a8eb9SGleb Smirnoff } 25093b3a8eb9SGleb Smirnoff 25103b3a8eb9SGleb Smirnoff int 251139282ef3SKajetan Staszkiewicz pfctl_set_reassembly(struct pfctl *pf, int on, int nodf) 251239282ef3SKajetan Staszkiewicz { 251339282ef3SKajetan Staszkiewicz if ((loadopt & PFCTL_FLAG_OPTION) == 0) 251439282ef3SKajetan Staszkiewicz return (0); 251539282ef3SKajetan Staszkiewicz 251639282ef3SKajetan Staszkiewicz pf->reass_set = 1; 251739282ef3SKajetan Staszkiewicz if (on) { 251839282ef3SKajetan Staszkiewicz pf->reassemble = PF_REASS_ENABLED; 251939282ef3SKajetan Staszkiewicz if (nodf) 252039282ef3SKajetan Staszkiewicz pf->reassemble |= PF_REASS_NODF; 252139282ef3SKajetan Staszkiewicz } else { 252239282ef3SKajetan Staszkiewicz pf->reassemble = 0; 252339282ef3SKajetan Staszkiewicz } 252439282ef3SKajetan Staszkiewicz 252539282ef3SKajetan Staszkiewicz if (pf->opts & PF_OPT_VERBOSE) 252639282ef3SKajetan Staszkiewicz printf("set reassemble %s %s\n", on ? "yes" : "no", 252739282ef3SKajetan Staszkiewicz nodf ? "no-df" : ""); 252839282ef3SKajetan Staszkiewicz 252939282ef3SKajetan Staszkiewicz return (0); 253039282ef3SKajetan Staszkiewicz } 253139282ef3SKajetan Staszkiewicz 253239282ef3SKajetan Staszkiewicz int 25333b3a8eb9SGleb Smirnoff pfctl_set_optimization(struct pfctl *pf, const char *opt) 25343b3a8eb9SGleb Smirnoff { 25353b3a8eb9SGleb Smirnoff const struct pf_hint *hint; 25363b3a8eb9SGleb Smirnoff int i, r; 25373b3a8eb9SGleb Smirnoff 25383b3a8eb9SGleb Smirnoff if ((loadopt & PFCTL_FLAG_OPTION) == 0) 25393b3a8eb9SGleb Smirnoff return (0); 25403b3a8eb9SGleb Smirnoff 25413b3a8eb9SGleb Smirnoff for (i = 0; pf_hints[i].name; i++) 25423b3a8eb9SGleb Smirnoff if (strcasecmp(opt, pf_hints[i].name) == 0) 25433b3a8eb9SGleb Smirnoff break; 25443b3a8eb9SGleb Smirnoff 25453b3a8eb9SGleb Smirnoff hint = pf_hints[i].hint; 25463b3a8eb9SGleb Smirnoff if (hint == NULL) { 25473b3a8eb9SGleb Smirnoff warnx("invalid state timeouts optimization"); 25483b3a8eb9SGleb Smirnoff return (1); 25493b3a8eb9SGleb Smirnoff } 25503b3a8eb9SGleb Smirnoff 25513b3a8eb9SGleb Smirnoff for (i = 0; hint[i].name; i++) 255230bad751SKristof Provost if ((r = pfctl_apply_timeout(pf, hint[i].name, 25533b3a8eb9SGleb Smirnoff hint[i].timeout, 1))) 25543b3a8eb9SGleb Smirnoff return (r); 25553b3a8eb9SGleb Smirnoff 25563b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 25573b3a8eb9SGleb Smirnoff printf("set optimization %s\n", opt); 25583b3a8eb9SGleb Smirnoff 25593b3a8eb9SGleb Smirnoff return (0); 25603b3a8eb9SGleb Smirnoff } 25613b3a8eb9SGleb Smirnoff 25623b3a8eb9SGleb Smirnoff int 25633b3a8eb9SGleb Smirnoff pfctl_set_logif(struct pfctl *pf, char *ifname) 25643b3a8eb9SGleb Smirnoff { 25653b3a8eb9SGleb Smirnoff 25663b3a8eb9SGleb Smirnoff if ((loadopt & PFCTL_FLAG_OPTION) == 0) 25673b3a8eb9SGleb Smirnoff return (0); 25683b3a8eb9SGleb Smirnoff 25693b3a8eb9SGleb Smirnoff if (!strcmp(ifname, "none")) { 25703b3a8eb9SGleb Smirnoff free(pf->ifname); 25713b3a8eb9SGleb Smirnoff pf->ifname = NULL; 25723b3a8eb9SGleb Smirnoff } else { 25733b3a8eb9SGleb Smirnoff pf->ifname = strdup(ifname); 25743b3a8eb9SGleb Smirnoff if (!pf->ifname) 25753b3a8eb9SGleb Smirnoff errx(1, "pfctl_set_logif: strdup"); 25763b3a8eb9SGleb Smirnoff } 25773b3a8eb9SGleb Smirnoff pf->ifname_set = 1; 25783b3a8eb9SGleb Smirnoff 25793b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 25803b3a8eb9SGleb Smirnoff printf("set loginterface %s\n", ifname); 25813b3a8eb9SGleb Smirnoff 25823b3a8eb9SGleb Smirnoff return (0); 25833b3a8eb9SGleb Smirnoff } 25843b3a8eb9SGleb Smirnoff 25853b3a8eb9SGleb Smirnoff int 25863b3a8eb9SGleb Smirnoff pfctl_load_logif(struct pfctl *pf, char *ifname) 25873b3a8eb9SGleb Smirnoff { 2588470a2b33SKristof Provost if (ifname != NULL && strlen(ifname) >= IFNAMSIZ) { 25893b3a8eb9SGleb Smirnoff warnx("pfctl_load_logif: strlcpy"); 25903b3a8eb9SGleb Smirnoff return (1); 25913b3a8eb9SGleb Smirnoff } 2592470a2b33SKristof Provost return (pfctl_set_statusif(pfh, ifname ? ifname : "")); 25933b3a8eb9SGleb Smirnoff } 25943b3a8eb9SGleb Smirnoff 25954aafc73dSKristof Provost void 25963b3a8eb9SGleb Smirnoff pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 25973b3a8eb9SGleb Smirnoff { 25983b3a8eb9SGleb Smirnoff if ((loadopt & PFCTL_FLAG_OPTION) == 0) 25994aafc73dSKristof Provost return; 26003b3a8eb9SGleb Smirnoff 26013b3a8eb9SGleb Smirnoff HTONL(hostid); 26023b3a8eb9SGleb Smirnoff 26033b3a8eb9SGleb Smirnoff pf->hostid = hostid; 26043b3a8eb9SGleb Smirnoff pf->hostid_set = 1; 26053b3a8eb9SGleb Smirnoff 26063b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 26073b3a8eb9SGleb Smirnoff printf("set hostid 0x%08x\n", ntohl(hostid)); 26083b3a8eb9SGleb Smirnoff } 26093b3a8eb9SGleb Smirnoff 26103b3a8eb9SGleb Smirnoff int 26113b3a8eb9SGleb Smirnoff pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid) 26123b3a8eb9SGleb Smirnoff { 26133b3a8eb9SGleb Smirnoff if (ioctl(dev, DIOCSETHOSTID, &hostid)) { 26143b3a8eb9SGleb Smirnoff warnx("DIOCSETHOSTID"); 26153b3a8eb9SGleb Smirnoff return (1); 26163b3a8eb9SGleb Smirnoff } 26173b3a8eb9SGleb Smirnoff return (0); 26183b3a8eb9SGleb Smirnoff } 26193b3a8eb9SGleb Smirnoff 26203b3a8eb9SGleb Smirnoff int 262139282ef3SKajetan Staszkiewicz pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly) 262239282ef3SKajetan Staszkiewicz { 262339282ef3SKajetan Staszkiewicz if (ioctl(dev, DIOCSETREASS, &reassembly)) { 262439282ef3SKajetan Staszkiewicz warnx("DIOCSETREASS"); 262539282ef3SKajetan Staszkiewicz return (1); 262639282ef3SKajetan Staszkiewicz } 262739282ef3SKajetan Staszkiewicz return (0); 262839282ef3SKajetan Staszkiewicz } 262939282ef3SKajetan Staszkiewicz 263039282ef3SKajetan Staszkiewicz int 2631c69121c4SKristof Provost pfctl_load_syncookies(struct pfctl *pf, u_int8_t val) 2632c69121c4SKristof Provost { 2633c69121c4SKristof Provost struct pfctl_syncookies cookies; 2634c69121c4SKristof Provost 2635c69121c4SKristof Provost bzero(&cookies, sizeof(cookies)); 2636c69121c4SKristof Provost 26375062afffSKristof Provost cookies.mode = val; 26385062afffSKristof Provost cookies.lowwater = pf->syncookieswat[0]; 26395062afffSKristof Provost cookies.highwater = pf->syncookieswat[1]; 2640c69121c4SKristof Provost 2641c69121c4SKristof Provost if (pfctl_set_syncookies(dev, &cookies)) { 2642c69121c4SKristof Provost warnx("DIOCSETSYNCOOKIES"); 2643c69121c4SKristof Provost return (1); 2644c69121c4SKristof Provost } 2645c69121c4SKristof Provost return (0); 2646c69121c4SKristof Provost } 2647c69121c4SKristof Provost 2648c69121c4SKristof Provost int 26495062afffSKristof Provost pfctl_cfg_syncookies(struct pfctl *pf, uint8_t val, struct pfctl_watermarks *w) 26505062afffSKristof Provost { 26515062afffSKristof Provost if (val != PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 26525062afffSKristof Provost warnx("syncookies start/end only apply to adaptive"); 26535062afffSKristof Provost return (1); 26545062afffSKristof Provost } 26555062afffSKristof Provost if (val == PF_SYNCOOKIES_ADAPTIVE && w != NULL) { 26565062afffSKristof Provost if (!w->hi) 26575062afffSKristof Provost w->hi = PF_SYNCOOKIES_HIWATPCT; 26585062afffSKristof Provost if (!w->lo) 26595062afffSKristof Provost w->lo = w->hi / 2; 26605062afffSKristof Provost if (w->lo >= w->hi) { 26615062afffSKristof Provost warnx("start must be higher than end"); 26625062afffSKristof Provost return (1); 26635062afffSKristof Provost } 26645062afffSKristof Provost pf->syncookieswat[0] = w->lo; 26655062afffSKristof Provost pf->syncookieswat[1] = w->hi; 26665062afffSKristof Provost pf->syncookieswat_set = 1; 26675062afffSKristof Provost } 26685062afffSKristof Provost 26695062afffSKristof Provost if (pf->opts & PF_OPT_VERBOSE) { 26705062afffSKristof Provost if (val == PF_SYNCOOKIES_NEVER) 26715062afffSKristof Provost printf("set syncookies never\n"); 26725062afffSKristof Provost else if (val == PF_SYNCOOKIES_ALWAYS) 26735062afffSKristof Provost printf("set syncookies always\n"); 26745062afffSKristof Provost else if (val == PF_SYNCOOKIES_ADAPTIVE) { 26755062afffSKristof Provost if (pf->syncookieswat_set) 26765062afffSKristof Provost printf("set syncookies adaptive (start %u%%, " 26775062afffSKristof Provost "end %u%%)\n", pf->syncookieswat[1], 26785062afffSKristof Provost pf->syncookieswat[0]); 26795062afffSKristof Provost else 26805062afffSKristof Provost printf("set syncookies adaptive\n"); 26815062afffSKristof Provost } else { /* cannot happen */ 26825062afffSKristof Provost warnx("king bula ate all syncookies"); 26835062afffSKristof Provost return (1); 26845062afffSKristof Provost } 26855062afffSKristof Provost } 26865062afffSKristof Provost 26875062afffSKristof Provost pf->syncookies = val; 26885062afffSKristof Provost return (0); 26895062afffSKristof Provost } 26905062afffSKristof Provost 26915062afffSKristof Provost int 2692c36c90a2SKristof Provost pfctl_do_set_debug(struct pfctl *pf, char *d) 26933b3a8eb9SGleb Smirnoff { 26943b3a8eb9SGleb Smirnoff u_int32_t level; 2695375aaa29SKristof Provost int ret; 26963b3a8eb9SGleb Smirnoff 26973b3a8eb9SGleb Smirnoff if ((loadopt & PFCTL_FLAG_OPTION) == 0) 26983b3a8eb9SGleb Smirnoff return (0); 26993b3a8eb9SGleb Smirnoff 27003b3a8eb9SGleb Smirnoff if (!strcmp(d, "none")) 27013b3a8eb9SGleb Smirnoff pf->debug = PF_DEBUG_NONE; 27023b3a8eb9SGleb Smirnoff else if (!strcmp(d, "urgent")) 27033b3a8eb9SGleb Smirnoff pf->debug = PF_DEBUG_URGENT; 27043b3a8eb9SGleb Smirnoff else if (!strcmp(d, "misc")) 27053b3a8eb9SGleb Smirnoff pf->debug = PF_DEBUG_MISC; 27063b3a8eb9SGleb Smirnoff else if (!strcmp(d, "loud")) 27073b3a8eb9SGleb Smirnoff pf->debug = PF_DEBUG_NOISY; 27083b3a8eb9SGleb Smirnoff else { 27093b3a8eb9SGleb Smirnoff warnx("unknown debug level \"%s\"", d); 27103b3a8eb9SGleb Smirnoff return (-1); 27113b3a8eb9SGleb Smirnoff } 27123b3a8eb9SGleb Smirnoff 27133b3a8eb9SGleb Smirnoff pf->debug_set = 1; 27143e768368SKristof Provost level = pf->debug; 27153b3a8eb9SGleb Smirnoff 27163b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_NOACTION) == 0) 2717375aaa29SKristof Provost if ((ret = pfctl_set_debug(pfh, level)) != 0) 2718375aaa29SKristof Provost errc(1, ret, "DIOCSETDEBUG"); 27193b3a8eb9SGleb Smirnoff 27203b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 27213b3a8eb9SGleb Smirnoff printf("set debug %s\n", d); 27223b3a8eb9SGleb Smirnoff 27233b3a8eb9SGleb Smirnoff return (0); 27243b3a8eb9SGleb Smirnoff } 27253b3a8eb9SGleb Smirnoff 27263b3a8eb9SGleb Smirnoff int 27273b3a8eb9SGleb Smirnoff pfctl_load_debug(struct pfctl *pf, unsigned int level) 27283b3a8eb9SGleb Smirnoff { 2729c36c90a2SKristof Provost if (pfctl_set_debug(pf->h, level)) { 27303b3a8eb9SGleb Smirnoff warnx("DIOCSETDEBUG"); 27313b3a8eb9SGleb Smirnoff return (1); 27323b3a8eb9SGleb Smirnoff } 27333b3a8eb9SGleb Smirnoff return (0); 27343b3a8eb9SGleb Smirnoff } 27353b3a8eb9SGleb Smirnoff 27363b3a8eb9SGleb Smirnoff int 27373b3a8eb9SGleb Smirnoff pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how) 27383b3a8eb9SGleb Smirnoff { 27393b3a8eb9SGleb Smirnoff struct pfioc_iface pi; 2740b1f3ab00SKristof Provost struct node_host *h = NULL, *n = NULL; 27413b3a8eb9SGleb Smirnoff 27423b3a8eb9SGleb Smirnoff if ((loadopt & PFCTL_FLAG_OPTION) == 0) 27433b3a8eb9SGleb Smirnoff return (0); 27443b3a8eb9SGleb Smirnoff 27453b3a8eb9SGleb Smirnoff bzero(&pi, sizeof(pi)); 27463b3a8eb9SGleb Smirnoff 27473b3a8eb9SGleb Smirnoff pi.pfiio_flags = flags; 27483b3a8eb9SGleb Smirnoff 2749b1f3ab00SKristof Provost /* Make sure our cache matches the kernel. If we set or clear the flag 2750b1f3ab00SKristof Provost * for a group this applies to all members. */ 2751b1f3ab00SKristof Provost h = ifa_grouplookup(ifname, 0); 2752b1f3ab00SKristof Provost for (n = h; n != NULL; n = n->next) 2753b1f3ab00SKristof Provost pfctl_set_interface_flags(pf, n->ifname, flags, how); 2754b1f3ab00SKristof Provost 27553b3a8eb9SGleb Smirnoff if (strlcpy(pi.pfiio_name, ifname, sizeof(pi.pfiio_name)) >= 27563b3a8eb9SGleb Smirnoff sizeof(pi.pfiio_name)) 27573b3a8eb9SGleb Smirnoff errx(1, "pfctl_set_interface_flags: strlcpy"); 27583b3a8eb9SGleb Smirnoff 27593b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_NOACTION) == 0) { 27603b3a8eb9SGleb Smirnoff if (how == 0) { 27613b3a8eb9SGleb Smirnoff if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi)) 27623b3a8eb9SGleb Smirnoff err(1, "DIOCCLRIFFLAG"); 27633b3a8eb9SGleb Smirnoff } else { 27643b3a8eb9SGleb Smirnoff if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) 27653b3a8eb9SGleb Smirnoff err(1, "DIOCSETIFFLAG"); 2766c5e10565SKristof Provost pfctl_check_skip_ifaces(ifname); 27673b3a8eb9SGleb Smirnoff } 27683b3a8eb9SGleb Smirnoff } 27693b3a8eb9SGleb Smirnoff return (0); 27703b3a8eb9SGleb Smirnoff } 27713b3a8eb9SGleb Smirnoff 27723b3a8eb9SGleb Smirnoff void 27733b3a8eb9SGleb Smirnoff pfctl_debug(int dev, u_int32_t level, int opts) 27743b3a8eb9SGleb Smirnoff { 2775375aaa29SKristof Provost int ret; 2776375aaa29SKristof Provost 2777375aaa29SKristof Provost if ((ret = pfctl_set_debug(pfh, level)) != 0) 2778375aaa29SKristof Provost errc(1, ret, "DIOCSETDEBUG"); 27793b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_QUIET) == 0) { 27803b3a8eb9SGleb Smirnoff fprintf(stderr, "debug level set to '"); 27813b3a8eb9SGleb Smirnoff switch (level) { 27823b3a8eb9SGleb Smirnoff case PF_DEBUG_NONE: 27833b3a8eb9SGleb Smirnoff fprintf(stderr, "none"); 27843b3a8eb9SGleb Smirnoff break; 27853b3a8eb9SGleb Smirnoff case PF_DEBUG_URGENT: 27863b3a8eb9SGleb Smirnoff fprintf(stderr, "urgent"); 27873b3a8eb9SGleb Smirnoff break; 27883b3a8eb9SGleb Smirnoff case PF_DEBUG_MISC: 27893b3a8eb9SGleb Smirnoff fprintf(stderr, "misc"); 27903b3a8eb9SGleb Smirnoff break; 27913b3a8eb9SGleb Smirnoff case PF_DEBUG_NOISY: 27923b3a8eb9SGleb Smirnoff fprintf(stderr, "loud"); 27933b3a8eb9SGleb Smirnoff break; 27943b3a8eb9SGleb Smirnoff default: 27953b3a8eb9SGleb Smirnoff fprintf(stderr, "<invalid>"); 27963b3a8eb9SGleb Smirnoff break; 27973b3a8eb9SGleb Smirnoff } 27983b3a8eb9SGleb Smirnoff fprintf(stderr, "'\n"); 27993b3a8eb9SGleb Smirnoff } 28003b3a8eb9SGleb Smirnoff } 28013b3a8eb9SGleb Smirnoff 28023b3a8eb9SGleb Smirnoff int 28033b3a8eb9SGleb Smirnoff pfctl_test_altqsupport(int dev, int opts) 28043b3a8eb9SGleb Smirnoff { 28053b3a8eb9SGleb Smirnoff struct pfioc_altq pa; 28063b3a8eb9SGleb Smirnoff 2807249cc75fSPatrick Kelsey pa.version = PFIOC_ALTQ_VERSION; 28083b3a8eb9SGleb Smirnoff if (ioctl(dev, DIOCGETALTQS, &pa)) { 28093b3a8eb9SGleb Smirnoff if (errno == ENODEV) { 2810a4134647SGeorge V. Neville-Neil if (opts & PF_OPT_VERBOSE) 28113b3a8eb9SGleb Smirnoff fprintf(stderr, "No ALTQ support in kernel\n" 28123b3a8eb9SGleb Smirnoff "ALTQ related functions disabled\n"); 28133b3a8eb9SGleb Smirnoff return (0); 28143b3a8eb9SGleb Smirnoff } else 28153b3a8eb9SGleb Smirnoff err(1, "DIOCGETALTQS"); 28163b3a8eb9SGleb Smirnoff } 28173b3a8eb9SGleb Smirnoff return (1); 28183b3a8eb9SGleb Smirnoff } 28193b3a8eb9SGleb Smirnoff 28203b3a8eb9SGleb Smirnoff int 28213b3a8eb9SGleb Smirnoff pfctl_show_anchors(int dev, int opts, char *anchorname) 28223b3a8eb9SGleb Smirnoff { 28233b3a8eb9SGleb Smirnoff struct pfioc_ruleset pr; 28243b3a8eb9SGleb Smirnoff u_int32_t mnr, nr; 282525e0f8f9SKristof Provost int ret; 28263b3a8eb9SGleb Smirnoff 28273b3a8eb9SGleb Smirnoff memset(&pr, 0, sizeof(pr)); 282825e0f8f9SKristof Provost if ((ret = pfctl_get_rulesets(pfh, anchorname, &mnr)) != 0) { 282925e0f8f9SKristof Provost if (ret == EINVAL) 28303b3a8eb9SGleb Smirnoff fprintf(stderr, "Anchor '%s' not found.\n", 28313b3a8eb9SGleb Smirnoff anchorname); 28323b3a8eb9SGleb Smirnoff else 283325e0f8f9SKristof Provost errc(1, ret, "DIOCGETRULESETS"); 28343b3a8eb9SGleb Smirnoff return (-1); 28353b3a8eb9SGleb Smirnoff } 28363b3a8eb9SGleb Smirnoff for (nr = 0; nr < mnr; ++nr) { 28373b3a8eb9SGleb Smirnoff char sub[MAXPATHLEN]; 28383b3a8eb9SGleb Smirnoff 283948f5bf8bSKristof Provost if ((ret = pfctl_get_ruleset(pfh, anchorname, nr, &pr)) != 0) 284048f5bf8bSKristof Provost errc(1, ret, "DIOCGETRULESET"); 28413b3a8eb9SGleb Smirnoff if (!strcmp(pr.name, PF_RESERVED_ANCHOR)) 28423b3a8eb9SGleb Smirnoff continue; 28433b3a8eb9SGleb Smirnoff sub[0] = 0; 28443b3a8eb9SGleb Smirnoff if (pr.path[0]) { 28453b3a8eb9SGleb Smirnoff strlcat(sub, pr.path, sizeof(sub)); 28463b3a8eb9SGleb Smirnoff strlcat(sub, "/", sizeof(sub)); 28473b3a8eb9SGleb Smirnoff } 28483b3a8eb9SGleb Smirnoff strlcat(sub, pr.name, sizeof(sub)); 28493b3a8eb9SGleb Smirnoff if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 28503b3a8eb9SGleb Smirnoff printf(" %s\n", sub); 28513b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub)) 28523b3a8eb9SGleb Smirnoff return (-1); 28533b3a8eb9SGleb Smirnoff } 28543b3a8eb9SGleb Smirnoff return (0); 28553b3a8eb9SGleb Smirnoff } 28563b3a8eb9SGleb Smirnoff 28579bb06778SKristof Provost int 28589bb06778SKristof Provost pfctl_show_eth_anchors(int dev, int opts, char *anchorname) 28599bb06778SKristof Provost { 28609bb06778SKristof Provost struct pfctl_eth_rulesets_info ri; 28619bb06778SKristof Provost struct pfctl_eth_ruleset_info rs; 28629bb06778SKristof Provost int ret; 28639bb06778SKristof Provost 28649bb06778SKristof Provost if ((ret = pfctl_get_eth_rulesets_info(dev, &ri, anchorname)) != 0) { 28659bb06778SKristof Provost if (ret == ENOENT) 28669bb06778SKristof Provost fprintf(stderr, "Anchor '%s' not found.\n", 28679bb06778SKristof Provost anchorname); 28689bb06778SKristof Provost else 2869375aaa29SKristof Provost errc(1, ret, "DIOCGETETHRULESETS"); 28709bb06778SKristof Provost return (-1); 28719bb06778SKristof Provost } 28729bb06778SKristof Provost 28739bb06778SKristof Provost for (int nr = 0; nr < ri.nr; nr++) { 28749bb06778SKristof Provost char sub[MAXPATHLEN]; 28759bb06778SKristof Provost 2876375aaa29SKristof Provost if ((ret = pfctl_get_eth_ruleset(dev, anchorname, nr, &rs)) != 0) 2877375aaa29SKristof Provost errc(1, ret, "DIOCGETETHRULESET"); 28789bb06778SKristof Provost 28799bb06778SKristof Provost if (!strcmp(rs.name, PF_RESERVED_ANCHOR)) 28809bb06778SKristof Provost continue; 28819bb06778SKristof Provost sub[0] = 0; 28829bb06778SKristof Provost if (rs.path[0]) { 28839bb06778SKristof Provost strlcat(sub, rs.path, sizeof(sub)); 28849bb06778SKristof Provost strlcat(sub, "/", sizeof(sub)); 28859bb06778SKristof Provost } 28869bb06778SKristof Provost strlcat(sub, rs.name, sizeof(sub)); 28879bb06778SKristof Provost if (sub[0] != '_' || (opts & PF_OPT_VERBOSE)) 28889bb06778SKristof Provost printf(" %s\n", sub); 28899bb06778SKristof Provost if ((opts & PF_OPT_VERBOSE) && pfctl_show_eth_anchors(dev, opts, sub)) 28909bb06778SKristof Provost return (-1); 28919bb06778SKristof Provost } 28929bb06778SKristof Provost return (0); 28939bb06778SKristof Provost } 28949bb06778SKristof Provost 28953b3a8eb9SGleb Smirnoff const char * 289672a3cf0fSKristof Provost pfctl_lookup_option(char *cmd, const char * const *list) 28973b3a8eb9SGleb Smirnoff { 28983b3a8eb9SGleb Smirnoff if (cmd != NULL && *cmd) 28993b3a8eb9SGleb Smirnoff for (; *list; list++) 29003b3a8eb9SGleb Smirnoff if (!strncmp(cmd, *list, strlen(cmd))) 29013b3a8eb9SGleb Smirnoff return (*list); 29023b3a8eb9SGleb Smirnoff return (NULL); 29033b3a8eb9SGleb Smirnoff } 29043b3a8eb9SGleb Smirnoff 29053b3a8eb9SGleb Smirnoff int 29063b3a8eb9SGleb Smirnoff main(int argc, char *argv[]) 29073b3a8eb9SGleb Smirnoff { 29083b3a8eb9SGleb Smirnoff int error = 0; 29093b3a8eb9SGleb Smirnoff int ch; 29103b3a8eb9SGleb Smirnoff int mode = O_RDONLY; 29113b3a8eb9SGleb Smirnoff int opts = 0; 29123b3a8eb9SGleb Smirnoff int optimize = PF_OPTIMIZE_BASIC; 29133b3a8eb9SGleb Smirnoff char anchorname[MAXPATHLEN]; 29143b3a8eb9SGleb Smirnoff char *path; 29153b3a8eb9SGleb Smirnoff 29163b3a8eb9SGleb Smirnoff if (argc < 2) 29173b3a8eb9SGleb Smirnoff usage(); 29183b3a8eb9SGleb Smirnoff 29193b3a8eb9SGleb Smirnoff while ((ch = getopt(argc, argv, 292093abcf17SKristof Provost "a:AdD:eqf:F:ghi:k:K:mMnNOo:Pp:rRs:t:T:vx:z")) != -1) { 29213b3a8eb9SGleb Smirnoff switch (ch) { 29223b3a8eb9SGleb Smirnoff case 'a': 29233b3a8eb9SGleb Smirnoff anchoropt = optarg; 29243b3a8eb9SGleb Smirnoff break; 29253b3a8eb9SGleb Smirnoff case 'd': 29263b3a8eb9SGleb Smirnoff opts |= PF_OPT_DISABLE; 29273b3a8eb9SGleb Smirnoff mode = O_RDWR; 29283b3a8eb9SGleb Smirnoff break; 29293b3a8eb9SGleb Smirnoff case 'D': 29303b3a8eb9SGleb Smirnoff if (pfctl_cmdline_symset(optarg) < 0) 29313b3a8eb9SGleb Smirnoff warnx("could not parse macro definition %s", 29323b3a8eb9SGleb Smirnoff optarg); 29333b3a8eb9SGleb Smirnoff break; 29343b3a8eb9SGleb Smirnoff case 'e': 29353b3a8eb9SGleb Smirnoff opts |= PF_OPT_ENABLE; 29363b3a8eb9SGleb Smirnoff mode = O_RDWR; 29373b3a8eb9SGleb Smirnoff break; 29383b3a8eb9SGleb Smirnoff case 'q': 29393b3a8eb9SGleb Smirnoff opts |= PF_OPT_QUIET; 29403b3a8eb9SGleb Smirnoff break; 29413b3a8eb9SGleb Smirnoff case 'F': 29423b3a8eb9SGleb Smirnoff clearopt = pfctl_lookup_option(optarg, clearopt_list); 29433b3a8eb9SGleb Smirnoff if (clearopt == NULL) { 29443b3a8eb9SGleb Smirnoff warnx("Unknown flush modifier '%s'", optarg); 29453b3a8eb9SGleb Smirnoff usage(); 29463b3a8eb9SGleb Smirnoff } 29473b3a8eb9SGleb Smirnoff mode = O_RDWR; 29483b3a8eb9SGleb Smirnoff break; 29493b3a8eb9SGleb Smirnoff case 'i': 29503b3a8eb9SGleb Smirnoff ifaceopt = optarg; 29513b3a8eb9SGleb Smirnoff break; 29523b3a8eb9SGleb Smirnoff case 'k': 29533b3a8eb9SGleb Smirnoff if (state_killers >= 2) { 29543b3a8eb9SGleb Smirnoff warnx("can only specify -k twice"); 29553b3a8eb9SGleb Smirnoff usage(); 29563b3a8eb9SGleb Smirnoff /* NOTREACHED */ 29573b3a8eb9SGleb Smirnoff } 29583b3a8eb9SGleb Smirnoff state_kill[state_killers++] = optarg; 29593b3a8eb9SGleb Smirnoff mode = O_RDWR; 29603b3a8eb9SGleb Smirnoff break; 29613b3a8eb9SGleb Smirnoff case 'K': 29623b3a8eb9SGleb Smirnoff if (src_node_killers >= 2) { 29633b3a8eb9SGleb Smirnoff warnx("can only specify -K twice"); 29643b3a8eb9SGleb Smirnoff usage(); 29653b3a8eb9SGleb Smirnoff /* NOTREACHED */ 29663b3a8eb9SGleb Smirnoff } 29673b3a8eb9SGleb Smirnoff src_node_kill[src_node_killers++] = optarg; 29683b3a8eb9SGleb Smirnoff mode = O_RDWR; 29693b3a8eb9SGleb Smirnoff break; 29703b3a8eb9SGleb Smirnoff case 'm': 29713b3a8eb9SGleb Smirnoff opts |= PF_OPT_MERGE; 29723b3a8eb9SGleb Smirnoff break; 297393abcf17SKristof Provost case 'M': 297493abcf17SKristof Provost opts |= PF_OPT_KILLMATCH; 297593abcf17SKristof Provost break; 29763b3a8eb9SGleb Smirnoff case 'n': 29773b3a8eb9SGleb Smirnoff opts |= PF_OPT_NOACTION; 29783b3a8eb9SGleb Smirnoff break; 29793b3a8eb9SGleb Smirnoff case 'N': 29803b3a8eb9SGleb Smirnoff loadopt |= PFCTL_FLAG_NAT; 29813b3a8eb9SGleb Smirnoff break; 29823b3a8eb9SGleb Smirnoff case 'r': 29833b3a8eb9SGleb Smirnoff opts |= PF_OPT_USEDNS; 29843b3a8eb9SGleb Smirnoff break; 29853b3a8eb9SGleb Smirnoff case 'f': 29863b3a8eb9SGleb Smirnoff rulesopt = optarg; 29873b3a8eb9SGleb Smirnoff mode = O_RDWR; 29883b3a8eb9SGleb Smirnoff break; 29893b3a8eb9SGleb Smirnoff case 'g': 29903b3a8eb9SGleb Smirnoff opts |= PF_OPT_DEBUG; 29913b3a8eb9SGleb Smirnoff break; 29923b3a8eb9SGleb Smirnoff case 'A': 29933b3a8eb9SGleb Smirnoff loadopt |= PFCTL_FLAG_ALTQ; 29943b3a8eb9SGleb Smirnoff break; 29953b3a8eb9SGleb Smirnoff case 'R': 29963b3a8eb9SGleb Smirnoff loadopt |= PFCTL_FLAG_FILTER; 29973b3a8eb9SGleb Smirnoff break; 29983b3a8eb9SGleb Smirnoff case 'o': 29993b3a8eb9SGleb Smirnoff optiopt = pfctl_lookup_option(optarg, optiopt_list); 30003b3a8eb9SGleb Smirnoff if (optiopt == NULL) { 30013b3a8eb9SGleb Smirnoff warnx("Unknown optimization '%s'", optarg); 30023b3a8eb9SGleb Smirnoff usage(); 30033b3a8eb9SGleb Smirnoff } 30043b3a8eb9SGleb Smirnoff opts |= PF_OPT_OPTIMIZE; 30053b3a8eb9SGleb Smirnoff break; 30063b3a8eb9SGleb Smirnoff case 'O': 30073b3a8eb9SGleb Smirnoff loadopt |= PFCTL_FLAG_OPTION; 30083b3a8eb9SGleb Smirnoff break; 30093b3a8eb9SGleb Smirnoff case 'p': 30103b3a8eb9SGleb Smirnoff pf_device = optarg; 30113b3a8eb9SGleb Smirnoff break; 30123b3a8eb9SGleb Smirnoff case 'P': 30133b3a8eb9SGleb Smirnoff opts |= PF_OPT_NUMERIC; 30143b3a8eb9SGleb Smirnoff break; 30153b3a8eb9SGleb Smirnoff case 's': 30163b3a8eb9SGleb Smirnoff showopt = pfctl_lookup_option(optarg, showopt_list); 30173b3a8eb9SGleb Smirnoff if (showopt == NULL) { 30183b3a8eb9SGleb Smirnoff warnx("Unknown show modifier '%s'", optarg); 30193b3a8eb9SGleb Smirnoff usage(); 30203b3a8eb9SGleb Smirnoff } 30213b3a8eb9SGleb Smirnoff break; 30223b3a8eb9SGleb Smirnoff case 't': 30233b3a8eb9SGleb Smirnoff tableopt = optarg; 30243b3a8eb9SGleb Smirnoff break; 30253b3a8eb9SGleb Smirnoff case 'T': 30263b3a8eb9SGleb Smirnoff tblcmdopt = pfctl_lookup_option(optarg, tblcmdopt_list); 30273b3a8eb9SGleb Smirnoff if (tblcmdopt == NULL) { 30283b3a8eb9SGleb Smirnoff warnx("Unknown table command '%s'", optarg); 30293b3a8eb9SGleb Smirnoff usage(); 30303b3a8eb9SGleb Smirnoff } 30313b3a8eb9SGleb Smirnoff break; 30323b3a8eb9SGleb Smirnoff case 'v': 30333b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) 30343b3a8eb9SGleb Smirnoff opts |= PF_OPT_VERBOSE2; 30353b3a8eb9SGleb Smirnoff opts |= PF_OPT_VERBOSE; 30363b3a8eb9SGleb Smirnoff break; 30373b3a8eb9SGleb Smirnoff case 'x': 30383b3a8eb9SGleb Smirnoff debugopt = pfctl_lookup_option(optarg, debugopt_list); 30393b3a8eb9SGleb Smirnoff if (debugopt == NULL) { 30403b3a8eb9SGleb Smirnoff warnx("Unknown debug level '%s'", optarg); 30413b3a8eb9SGleb Smirnoff usage(); 30423b3a8eb9SGleb Smirnoff } 30433b3a8eb9SGleb Smirnoff mode = O_RDWR; 30443b3a8eb9SGleb Smirnoff break; 30453b3a8eb9SGleb Smirnoff case 'z': 30463b3a8eb9SGleb Smirnoff opts |= PF_OPT_CLRRULECTRS; 30473b3a8eb9SGleb Smirnoff mode = O_RDWR; 30483b3a8eb9SGleb Smirnoff break; 30493b3a8eb9SGleb Smirnoff case 'h': 30503b3a8eb9SGleb Smirnoff /* FALLTHROUGH */ 30513b3a8eb9SGleb Smirnoff default: 30523b3a8eb9SGleb Smirnoff usage(); 30533b3a8eb9SGleb Smirnoff /* NOTREACHED */ 30543b3a8eb9SGleb Smirnoff } 30553b3a8eb9SGleb Smirnoff } 30563b3a8eb9SGleb Smirnoff 30573b3a8eb9SGleb Smirnoff if (tblcmdopt != NULL) { 30583b3a8eb9SGleb Smirnoff argc -= optind; 30593b3a8eb9SGleb Smirnoff argv += optind; 30603b3a8eb9SGleb Smirnoff ch = *tblcmdopt; 30613b3a8eb9SGleb Smirnoff if (ch == 'l') { 30623b3a8eb9SGleb Smirnoff loadopt |= PFCTL_FLAG_TABLE; 30633b3a8eb9SGleb Smirnoff tblcmdopt = NULL; 30643b3a8eb9SGleb Smirnoff } else 30653b3a8eb9SGleb Smirnoff mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY; 30663b3a8eb9SGleb Smirnoff } else if (argc != optind) { 30673b3a8eb9SGleb Smirnoff warnx("unknown command line argument: %s ...", argv[optind]); 30683b3a8eb9SGleb Smirnoff usage(); 30693b3a8eb9SGleb Smirnoff /* NOTREACHED */ 30703b3a8eb9SGleb Smirnoff } 30713b3a8eb9SGleb Smirnoff if (loadopt == 0) 30723b3a8eb9SGleb Smirnoff loadopt = ~0; 30733b3a8eb9SGleb Smirnoff 30743b3a8eb9SGleb Smirnoff if ((path = calloc(1, MAXPATHLEN)) == NULL) 30753b3a8eb9SGleb Smirnoff errx(1, "pfctl: calloc"); 30763b3a8eb9SGleb Smirnoff memset(anchorname, 0, sizeof(anchorname)); 30773b3a8eb9SGleb Smirnoff if (anchoropt != NULL) { 30783b3a8eb9SGleb Smirnoff int len = strlen(anchoropt); 30793b3a8eb9SGleb Smirnoff 308029866385SJessica Clarke if (len >= 1 && anchoropt[len - 1] == '*') { 30813b3a8eb9SGleb Smirnoff if (len >= 2 && anchoropt[len - 2] == '/') 30823b3a8eb9SGleb Smirnoff anchoropt[len - 2] = '\0'; 30833b3a8eb9SGleb Smirnoff else 30843b3a8eb9SGleb Smirnoff anchoropt[len - 1] = '\0'; 30853b3a8eb9SGleb Smirnoff opts |= PF_OPT_RECURSE; 30863b3a8eb9SGleb Smirnoff } 30873b3a8eb9SGleb Smirnoff if (strlcpy(anchorname, anchoropt, 30883b3a8eb9SGleb Smirnoff sizeof(anchorname)) >= sizeof(anchorname)) 30893b3a8eb9SGleb Smirnoff errx(1, "anchor name '%s' too long", 30903b3a8eb9SGleb Smirnoff anchoropt); 3091c5131afeSKristof Provost loadopt &= PFCTL_FLAG_FILTER|PFCTL_FLAG_NAT|PFCTL_FLAG_TABLE|PFCTL_FLAG_ETH; 30923b3a8eb9SGleb Smirnoff } 30933b3a8eb9SGleb Smirnoff 30943b3a8eb9SGleb Smirnoff if ((opts & PF_OPT_NOACTION) == 0) { 30953b3a8eb9SGleb Smirnoff dev = open(pf_device, mode); 30963b3a8eb9SGleb Smirnoff if (dev == -1) 30973b3a8eb9SGleb Smirnoff err(1, "%s", pf_device); 30983b3a8eb9SGleb Smirnoff altqsupport = pfctl_test_altqsupport(dev, opts); 30993b3a8eb9SGleb Smirnoff } else { 31003b3a8eb9SGleb Smirnoff dev = open(pf_device, O_RDONLY); 31013b3a8eb9SGleb Smirnoff if (dev >= 0) 31023b3a8eb9SGleb Smirnoff opts |= PF_OPT_DUMMYACTION; 31033b3a8eb9SGleb Smirnoff /* turn off options */ 31043b3a8eb9SGleb Smirnoff opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE); 31053b3a8eb9SGleb Smirnoff clearopt = showopt = debugopt = NULL; 3106116e43f0SGleb Smirnoff #if !defined(ENABLE_ALTQ) 31073b3a8eb9SGleb Smirnoff altqsupport = 0; 31083b3a8eb9SGleb Smirnoff #else 31093b3a8eb9SGleb Smirnoff altqsupport = 1; 31103b3a8eb9SGleb Smirnoff #endif 31113b3a8eb9SGleb Smirnoff } 311266cacc14SKristof Provost pfh = pfctl_open(pf_device); 311366cacc14SKristof Provost if (pfh == NULL) 311466cacc14SKristof Provost err(1, "Failed to open netlink"); 31153b3a8eb9SGleb Smirnoff 31163b3a8eb9SGleb Smirnoff if (opts & PF_OPT_DISABLE) 31173b3a8eb9SGleb Smirnoff if (pfctl_disable(dev, opts)) 31183b3a8eb9SGleb Smirnoff error = 1; 31193b3a8eb9SGleb Smirnoff 31203b3a8eb9SGleb Smirnoff if (showopt != NULL) { 31213b3a8eb9SGleb Smirnoff switch (*showopt) { 31223b3a8eb9SGleb Smirnoff case 'A': 31233b3a8eb9SGleb Smirnoff pfctl_show_anchors(dev, opts, anchorname); 3124f8b4f9aaSKristof Provost if (opts & PF_OPT_VERBOSE2) 3125f8b4f9aaSKristof Provost printf("Ethernet:\n"); 31269bb06778SKristof Provost pfctl_show_eth_anchors(dev, opts, anchorname); 31273b3a8eb9SGleb Smirnoff break; 31283b3a8eb9SGleb Smirnoff case 'r': 31293b3a8eb9SGleb Smirnoff pfctl_load_fingerprints(dev, opts); 31303b3a8eb9SGleb Smirnoff pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES, 3131585a5ed0SKristof Provost anchorname, 0, 0); 31323b3a8eb9SGleb Smirnoff break; 31333b3a8eb9SGleb Smirnoff case 'l': 31343b3a8eb9SGleb Smirnoff pfctl_load_fingerprints(dev, opts); 31353b3a8eb9SGleb Smirnoff pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS, 3136585a5ed0SKristof Provost anchorname, 0, 0); 31373b3a8eb9SGleb Smirnoff break; 31383b3a8eb9SGleb Smirnoff case 'n': 31393b3a8eb9SGleb Smirnoff pfctl_load_fingerprints(dev, opts); 31408ddd0359SKristof Provost pfctl_show_nat(dev, path, opts, anchorname, 0, 0); 31413b3a8eb9SGleb Smirnoff break; 31423b3a8eb9SGleb Smirnoff case 'q': 31433b3a8eb9SGleb Smirnoff pfctl_show_altq(dev, ifaceopt, opts, 31443b3a8eb9SGleb Smirnoff opts & PF_OPT_VERBOSE2); 31453b3a8eb9SGleb Smirnoff break; 31463b3a8eb9SGleb Smirnoff case 's': 31473b3a8eb9SGleb Smirnoff pfctl_show_states(dev, ifaceopt, opts); 31483b3a8eb9SGleb Smirnoff break; 31493b3a8eb9SGleb Smirnoff case 'S': 31503b3a8eb9SGleb Smirnoff pfctl_show_src_nodes(dev, opts); 31513b3a8eb9SGleb Smirnoff break; 31523b3a8eb9SGleb Smirnoff case 'i': 31533b3a8eb9SGleb Smirnoff pfctl_show_status(dev, opts); 31543b3a8eb9SGleb Smirnoff break; 3155fa1d4439SKristof Provost case 'R': 3156fa1d4439SKristof Provost error = pfctl_show_running(dev); 3157fa1d4439SKristof Provost break; 31583b3a8eb9SGleb Smirnoff case 't': 31593b3a8eb9SGleb Smirnoff pfctl_show_timeouts(dev, opts); 31603b3a8eb9SGleb Smirnoff break; 31613b3a8eb9SGleb Smirnoff case 'm': 31623b3a8eb9SGleb Smirnoff pfctl_show_limits(dev, opts); 31633b3a8eb9SGleb Smirnoff break; 31642b29ceb8SKristof Provost case 'e': 3165cfa1a130SKristof Provost pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0, 3166cfa1a130SKristof Provost 0); 31672b29ceb8SKristof Provost break; 31683b3a8eb9SGleb Smirnoff case 'a': 31693b3a8eb9SGleb Smirnoff opts |= PF_OPT_SHOWALL; 31703b3a8eb9SGleb Smirnoff pfctl_load_fingerprints(dev, opts); 31713b3a8eb9SGleb Smirnoff 3172cfa1a130SKristof Provost pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0, 3173cfa1a130SKristof Provost 0); 31742b29ceb8SKristof Provost 31758ddd0359SKristof Provost pfctl_show_nat(dev, path, opts, anchorname, 0, 0); 3176585a5ed0SKristof Provost pfctl_show_rules(dev, path, opts, 0, anchorname, 0, 0); 31773b3a8eb9SGleb Smirnoff pfctl_show_altq(dev, ifaceopt, opts, 0); 31783b3a8eb9SGleb Smirnoff pfctl_show_states(dev, ifaceopt, opts); 31793b3a8eb9SGleb Smirnoff pfctl_show_src_nodes(dev, opts); 31803b3a8eb9SGleb Smirnoff pfctl_show_status(dev, opts); 3181585a5ed0SKristof Provost pfctl_show_rules(dev, path, opts, 1, anchorname, 0, 0); 31823b3a8eb9SGleb Smirnoff pfctl_show_timeouts(dev, opts); 31833b3a8eb9SGleb Smirnoff pfctl_show_limits(dev, opts); 31843b3a8eb9SGleb Smirnoff pfctl_show_tables(anchorname, opts); 31853b3a8eb9SGleb Smirnoff pfctl_show_fingerprints(opts); 31863b3a8eb9SGleb Smirnoff break; 31873b3a8eb9SGleb Smirnoff case 'T': 31883b3a8eb9SGleb Smirnoff pfctl_show_tables(anchorname, opts); 31893b3a8eb9SGleb Smirnoff break; 31903b3a8eb9SGleb Smirnoff case 'o': 31913b3a8eb9SGleb Smirnoff pfctl_load_fingerprints(dev, opts); 31923b3a8eb9SGleb Smirnoff pfctl_show_fingerprints(opts); 31933b3a8eb9SGleb Smirnoff break; 31943b3a8eb9SGleb Smirnoff case 'I': 31953b3a8eb9SGleb Smirnoff pfctl_show_ifaces(ifaceopt, opts); 31963b3a8eb9SGleb Smirnoff break; 3197a7191e5dSKristof Provost case 'c': 3198a7191e5dSKristof Provost pfctl_show_creators(opts); 3199a7191e5dSKristof Provost break; 32003b3a8eb9SGleb Smirnoff } 32013b3a8eb9SGleb Smirnoff } 32023b3a8eb9SGleb Smirnoff 320330087aa2SKristof Provost if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) { 3204c5131afeSKristof Provost pfctl_show_eth_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 3205cfa1a130SKristof Provost anchorname, 0, 0); 32063b3a8eb9SGleb Smirnoff pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING, 3207585a5ed0SKristof Provost anchorname, 0, 0); 320830087aa2SKristof Provost } 32093b3a8eb9SGleb Smirnoff 32103b3a8eb9SGleb Smirnoff if (clearopt != NULL) { 32113b3a8eb9SGleb Smirnoff if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 32123b3a8eb9SGleb Smirnoff errx(1, "anchor names beginning with '_' cannot " 32133b3a8eb9SGleb Smirnoff "be modified from the command line"); 32143b3a8eb9SGleb Smirnoff 32153b3a8eb9SGleb Smirnoff switch (*clearopt) { 32166ea1c3cfSKristof Provost case 'e': 3217f0c334e4SKristof Provost pfctl_flush_eth_rules(dev, opts, anchorname); 32186ea1c3cfSKristof Provost break; 32193b3a8eb9SGleb Smirnoff case 'r': 3220f0c334e4SKristof Provost pfctl_flush_rules(dev, opts, anchorname); 32213b3a8eb9SGleb Smirnoff break; 32223b3a8eb9SGleb Smirnoff case 'n': 3223f0c334e4SKristof Provost pfctl_flush_nat(dev, opts, anchorname); 32243b3a8eb9SGleb Smirnoff break; 32253b3a8eb9SGleb Smirnoff case 'q': 32263b3a8eb9SGleb Smirnoff pfctl_clear_altq(dev, opts); 32273b3a8eb9SGleb Smirnoff break; 32283b3a8eb9SGleb Smirnoff case 's': 322953714a58SKristof Provost pfctl_clear_iface_states(dev, ifaceopt, opts); 32303b3a8eb9SGleb Smirnoff break; 32313b3a8eb9SGleb Smirnoff case 'S': 32323b3a8eb9SGleb Smirnoff pfctl_clear_src_nodes(dev, opts); 32333b3a8eb9SGleb Smirnoff break; 32343b3a8eb9SGleb Smirnoff case 'i': 32359dbbe68bSKristof Provost pfctl_clear_stats(pfh, opts); 32363b3a8eb9SGleb Smirnoff break; 32373b3a8eb9SGleb Smirnoff case 'a': 3238f0c334e4SKristof Provost pfctl_flush_eth_rules(dev, opts, anchorname); 3239f0c334e4SKristof Provost pfctl_flush_rules(dev, opts, anchorname); 3240f0c334e4SKristof Provost pfctl_flush_nat(dev, opts, anchorname); 3241441d4894SKristof Provost pfctl_do_clear_tables(anchorname, opts); 32423b3a8eb9SGleb Smirnoff if (!*anchorname) { 32433b3a8eb9SGleb Smirnoff pfctl_clear_altq(dev, opts); 324453714a58SKristof Provost pfctl_clear_iface_states(dev, ifaceopt, opts); 32453b3a8eb9SGleb Smirnoff pfctl_clear_src_nodes(dev, opts); 32469dbbe68bSKristof Provost pfctl_clear_stats(pfh, opts); 32473b3a8eb9SGleb Smirnoff pfctl_clear_fingerprints(dev, opts); 32483b3a8eb9SGleb Smirnoff pfctl_clear_interface_flags(dev, opts); 32493b3a8eb9SGleb Smirnoff } 32503b3a8eb9SGleb Smirnoff break; 32513b3a8eb9SGleb Smirnoff case 'o': 32523b3a8eb9SGleb Smirnoff pfctl_clear_fingerprints(dev, opts); 32533b3a8eb9SGleb Smirnoff break; 32543b3a8eb9SGleb Smirnoff case 'T': 3255441d4894SKristof Provost pfctl_do_clear_tables(anchorname, opts); 32563b3a8eb9SGleb Smirnoff break; 32573b3a8eb9SGleb Smirnoff } 32583b3a8eb9SGleb Smirnoff } 32593b3a8eb9SGleb Smirnoff if (state_killers) { 32603b3a8eb9SGleb Smirnoff if (!strcmp(state_kill[0], "label")) 32613b3a8eb9SGleb Smirnoff pfctl_label_kill_states(dev, ifaceopt, opts); 32623b3a8eb9SGleb Smirnoff else if (!strcmp(state_kill[0], "id")) 32633b3a8eb9SGleb Smirnoff pfctl_id_kill_states(dev, ifaceopt, opts); 3264abbcba9cSKristof Provost else if (!strcmp(state_kill[0], "gateway")) 3265abbcba9cSKristof Provost pfctl_gateway_kill_states(dev, ifaceopt, opts); 32663b3a8eb9SGleb Smirnoff else 32673b3a8eb9SGleb Smirnoff pfctl_net_kill_states(dev, ifaceopt, opts); 32683b3a8eb9SGleb Smirnoff } 32693b3a8eb9SGleb Smirnoff 32703b3a8eb9SGleb Smirnoff if (src_node_killers) 32713b3a8eb9SGleb Smirnoff pfctl_kill_src_nodes(dev, ifaceopt, opts); 32723b3a8eb9SGleb Smirnoff 32733b3a8eb9SGleb Smirnoff if (tblcmdopt != NULL) { 32743b3a8eb9SGleb Smirnoff error = pfctl_command_tables(argc, argv, tableopt, 32753b3a8eb9SGleb Smirnoff tblcmdopt, rulesopt, anchorname, opts); 32763b3a8eb9SGleb Smirnoff rulesopt = NULL; 32773b3a8eb9SGleb Smirnoff } 32783b3a8eb9SGleb Smirnoff if (optiopt != NULL) { 32793b3a8eb9SGleb Smirnoff switch (*optiopt) { 32803b3a8eb9SGleb Smirnoff case 'n': 32813b3a8eb9SGleb Smirnoff optimize = 0; 32823b3a8eb9SGleb Smirnoff break; 32833b3a8eb9SGleb Smirnoff case 'b': 32843b3a8eb9SGleb Smirnoff optimize |= PF_OPTIMIZE_BASIC; 32853b3a8eb9SGleb Smirnoff break; 32863b3a8eb9SGleb Smirnoff case 'o': 32873b3a8eb9SGleb Smirnoff case 'p': 32883b3a8eb9SGleb Smirnoff optimize |= PF_OPTIMIZE_PROFILE; 32893b3a8eb9SGleb Smirnoff break; 32903b3a8eb9SGleb Smirnoff } 32913b3a8eb9SGleb Smirnoff } 32923b3a8eb9SGleb Smirnoff 32933b3a8eb9SGleb Smirnoff if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) && 32947a2bf4c5SKristof Provost !anchorname[0] && !(opts & PF_OPT_NOACTION)) 3295c5e10565SKristof Provost if (pfctl_get_skip_ifaces()) 32963b3a8eb9SGleb Smirnoff error = 1; 32973b3a8eb9SGleb Smirnoff 32983b3a8eb9SGleb Smirnoff if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) && 32993b3a8eb9SGleb Smirnoff !anchorname[0] && (loadopt & PFCTL_FLAG_OPTION)) 33003b3a8eb9SGleb Smirnoff if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE)) 33013b3a8eb9SGleb Smirnoff error = 1; 33023b3a8eb9SGleb Smirnoff 33033b3a8eb9SGleb Smirnoff if (rulesopt != NULL) { 33043b3a8eb9SGleb Smirnoff if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL) 33053b3a8eb9SGleb Smirnoff errx(1, "anchor names beginning with '_' cannot " 33063b3a8eb9SGleb Smirnoff "be modified from the command line"); 33073b3a8eb9SGleb Smirnoff if (pfctl_rules(dev, rulesopt, opts, optimize, 33083b3a8eb9SGleb Smirnoff anchorname, NULL)) 33093b3a8eb9SGleb Smirnoff error = 1; 33103b3a8eb9SGleb Smirnoff else if (!(opts & PF_OPT_NOACTION) && 33113b3a8eb9SGleb Smirnoff (loadopt & PFCTL_FLAG_TABLE)) 33123b3a8eb9SGleb Smirnoff warn_namespace_collision(NULL); 33133b3a8eb9SGleb Smirnoff } 33143b3a8eb9SGleb Smirnoff 33153b3a8eb9SGleb Smirnoff if (opts & PF_OPT_ENABLE) 33163b3a8eb9SGleb Smirnoff if (pfctl_enable(dev, opts)) 33173b3a8eb9SGleb Smirnoff error = 1; 33183b3a8eb9SGleb Smirnoff 33193b3a8eb9SGleb Smirnoff if (debugopt != NULL) { 33203b3a8eb9SGleb Smirnoff switch (*debugopt) { 33213b3a8eb9SGleb Smirnoff case 'n': 33223b3a8eb9SGleb Smirnoff pfctl_debug(dev, PF_DEBUG_NONE, opts); 33233b3a8eb9SGleb Smirnoff break; 33243b3a8eb9SGleb Smirnoff case 'u': 33253b3a8eb9SGleb Smirnoff pfctl_debug(dev, PF_DEBUG_URGENT, opts); 33263b3a8eb9SGleb Smirnoff break; 33273b3a8eb9SGleb Smirnoff case 'm': 33283b3a8eb9SGleb Smirnoff pfctl_debug(dev, PF_DEBUG_MISC, opts); 33293b3a8eb9SGleb Smirnoff break; 33303b3a8eb9SGleb Smirnoff case 'l': 33313b3a8eb9SGleb Smirnoff pfctl_debug(dev, PF_DEBUG_NOISY, opts); 33323b3a8eb9SGleb Smirnoff break; 33333b3a8eb9SGleb Smirnoff } 33343b3a8eb9SGleb Smirnoff } 33353b3a8eb9SGleb Smirnoff 33363b3a8eb9SGleb Smirnoff exit(error); 33373b3a8eb9SGleb Smirnoff } 3338