13b3a8eb9SGleb Smirnoff /* $OpenBSD: pfctl_parser.c,v 1.240 2008/06/10 20:55:02 mcbride 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> 373b3a8eb9SGleb Smirnoff __FBSDID("$FreeBSD$"); 383b3a8eb9SGleb Smirnoff 393b3a8eb9SGleb Smirnoff #include <sys/types.h> 403b3a8eb9SGleb Smirnoff #include <sys/ioctl.h> 413b3a8eb9SGleb Smirnoff #include <sys/socket.h> 423b3a8eb9SGleb Smirnoff #include <sys/param.h> 433b3a8eb9SGleb Smirnoff #include <sys/proc.h> 443b3a8eb9SGleb Smirnoff #include <net/if.h> 453b3a8eb9SGleb Smirnoff #include <netinet/in.h> 463b3a8eb9SGleb Smirnoff #include <netinet/in_systm.h> 473b3a8eb9SGleb Smirnoff #include <netinet/ip.h> 483b3a8eb9SGleb Smirnoff #include <netinet/ip_icmp.h> 493b3a8eb9SGleb Smirnoff #include <netinet/icmp6.h> 503b3a8eb9SGleb Smirnoff #include <net/pfvar.h> 513b3a8eb9SGleb Smirnoff #include <arpa/inet.h> 523b3a8eb9SGleb Smirnoff 535062afffSKristof Provost #include <assert.h> 541d34c9daSPatrick Kelsey #include <search.h> 553b3a8eb9SGleb Smirnoff #include <stdio.h> 563b3a8eb9SGleb Smirnoff #include <stdlib.h> 573b3a8eb9SGleb Smirnoff #include <string.h> 583b3a8eb9SGleb Smirnoff #include <ctype.h> 593b3a8eb9SGleb Smirnoff #include <netdb.h> 603b3a8eb9SGleb Smirnoff #include <stdarg.h> 613b3a8eb9SGleb Smirnoff #include <errno.h> 623b3a8eb9SGleb Smirnoff #include <err.h> 633b3a8eb9SGleb Smirnoff #include <ifaddrs.h> 643b3a8eb9SGleb Smirnoff #include <unistd.h> 653b3a8eb9SGleb Smirnoff 663b3a8eb9SGleb Smirnoff #include "pfctl_parser.h" 673b3a8eb9SGleb Smirnoff #include "pfctl.h" 683b3a8eb9SGleb Smirnoff 693b3a8eb9SGleb Smirnoff void print_op (u_int8_t, const char *, const char *); 703b3a8eb9SGleb Smirnoff void print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int); 713b3a8eb9SGleb Smirnoff void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned); 723b3a8eb9SGleb Smirnoff void print_flags (u_int8_t); 733b3a8eb9SGleb Smirnoff void print_fromto(struct pf_rule_addr *, pf_osfp_t, 74dbce131bSKristof Provost struct pf_rule_addr *, sa_family_t, u_int8_t, int, int); 753b3a8eb9SGleb Smirnoff int ifa_skip_if(const char *filter, struct node_host *p); 763b3a8eb9SGleb Smirnoff 7728b64169SFranco Fichtner struct node_host *host_if(const char *, int, int *); 783b3a8eb9SGleb Smirnoff struct node_host *host_v4(const char *, int); 793b3a8eb9SGleb Smirnoff struct node_host *host_v6(const char *, int); 803b3a8eb9SGleb Smirnoff struct node_host *host_dns(const char *, int, int); 813b3a8eb9SGleb Smirnoff 8272a3cf0fSKristof Provost const char * const tcpflags = "FSRPAUEW"; 833b3a8eb9SGleb Smirnoff 843b3a8eb9SGleb Smirnoff static const struct icmptypeent icmp_type[] = { 853b3a8eb9SGleb Smirnoff { "echoreq", ICMP_ECHO }, 863b3a8eb9SGleb Smirnoff { "echorep", ICMP_ECHOREPLY }, 873b3a8eb9SGleb Smirnoff { "unreach", ICMP_UNREACH }, 883b3a8eb9SGleb Smirnoff { "squench", ICMP_SOURCEQUENCH }, 893b3a8eb9SGleb Smirnoff { "redir", ICMP_REDIRECT }, 903b3a8eb9SGleb Smirnoff { "althost", ICMP_ALTHOSTADDR }, 913b3a8eb9SGleb Smirnoff { "routeradv", ICMP_ROUTERADVERT }, 923b3a8eb9SGleb Smirnoff { "routersol", ICMP_ROUTERSOLICIT }, 933b3a8eb9SGleb Smirnoff { "timex", ICMP_TIMXCEED }, 943b3a8eb9SGleb Smirnoff { "paramprob", ICMP_PARAMPROB }, 953b3a8eb9SGleb Smirnoff { "timereq", ICMP_TSTAMP }, 963b3a8eb9SGleb Smirnoff { "timerep", ICMP_TSTAMPREPLY }, 973b3a8eb9SGleb Smirnoff { "inforeq", ICMP_IREQ }, 983b3a8eb9SGleb Smirnoff { "inforep", ICMP_IREQREPLY }, 993b3a8eb9SGleb Smirnoff { "maskreq", ICMP_MASKREQ }, 1003b3a8eb9SGleb Smirnoff { "maskrep", ICMP_MASKREPLY }, 1013b3a8eb9SGleb Smirnoff { "trace", ICMP_TRACEROUTE }, 1023b3a8eb9SGleb Smirnoff { "dataconv", ICMP_DATACONVERR }, 1033b3a8eb9SGleb Smirnoff { "mobredir", ICMP_MOBILE_REDIRECT }, 1043b3a8eb9SGleb Smirnoff { "ipv6-where", ICMP_IPV6_WHEREAREYOU }, 1053b3a8eb9SGleb Smirnoff { "ipv6-here", ICMP_IPV6_IAMHERE }, 1063b3a8eb9SGleb Smirnoff { "mobregreq", ICMP_MOBILE_REGREQUEST }, 1073b3a8eb9SGleb Smirnoff { "mobregrep", ICMP_MOBILE_REGREPLY }, 1083b3a8eb9SGleb Smirnoff { "skip", ICMP_SKIP }, 1093b3a8eb9SGleb Smirnoff { "photuris", ICMP_PHOTURIS } 1103b3a8eb9SGleb Smirnoff }; 1113b3a8eb9SGleb Smirnoff 1123b3a8eb9SGleb Smirnoff static const struct icmptypeent icmp6_type[] = { 1133b3a8eb9SGleb Smirnoff { "unreach", ICMP6_DST_UNREACH }, 1143b3a8eb9SGleb Smirnoff { "toobig", ICMP6_PACKET_TOO_BIG }, 1153b3a8eb9SGleb Smirnoff { "timex", ICMP6_TIME_EXCEEDED }, 1163b3a8eb9SGleb Smirnoff { "paramprob", ICMP6_PARAM_PROB }, 1173b3a8eb9SGleb Smirnoff { "echoreq", ICMP6_ECHO_REQUEST }, 1183b3a8eb9SGleb Smirnoff { "echorep", ICMP6_ECHO_REPLY }, 1193b3a8eb9SGleb Smirnoff { "groupqry", ICMP6_MEMBERSHIP_QUERY }, 1203b3a8eb9SGleb Smirnoff { "listqry", MLD_LISTENER_QUERY }, 1213b3a8eb9SGleb Smirnoff { "grouprep", ICMP6_MEMBERSHIP_REPORT }, 1223b3a8eb9SGleb Smirnoff { "listenrep", MLD_LISTENER_REPORT }, 1233b3a8eb9SGleb Smirnoff { "groupterm", ICMP6_MEMBERSHIP_REDUCTION }, 1243b3a8eb9SGleb Smirnoff { "listendone", MLD_LISTENER_DONE }, 1253b3a8eb9SGleb Smirnoff { "routersol", ND_ROUTER_SOLICIT }, 1263b3a8eb9SGleb Smirnoff { "routeradv", ND_ROUTER_ADVERT }, 1273b3a8eb9SGleb Smirnoff { "neighbrsol", ND_NEIGHBOR_SOLICIT }, 1283b3a8eb9SGleb Smirnoff { "neighbradv", ND_NEIGHBOR_ADVERT }, 1293b3a8eb9SGleb Smirnoff { "redir", ND_REDIRECT }, 1303b3a8eb9SGleb Smirnoff { "routrrenum", ICMP6_ROUTER_RENUMBERING }, 1313b3a8eb9SGleb Smirnoff { "wrureq", ICMP6_WRUREQUEST }, 1323b3a8eb9SGleb Smirnoff { "wrurep", ICMP6_WRUREPLY }, 1333b3a8eb9SGleb Smirnoff { "fqdnreq", ICMP6_FQDN_QUERY }, 1343b3a8eb9SGleb Smirnoff { "fqdnrep", ICMP6_FQDN_REPLY }, 1353b3a8eb9SGleb Smirnoff { "niqry", ICMP6_NI_QUERY }, 1363b3a8eb9SGleb Smirnoff { "nirep", ICMP6_NI_REPLY }, 1373b3a8eb9SGleb Smirnoff { "mtraceresp", MLD_MTRACE_RESP }, 1383b3a8eb9SGleb Smirnoff { "mtrace", MLD_MTRACE } 1393b3a8eb9SGleb Smirnoff }; 1403b3a8eb9SGleb Smirnoff 1413b3a8eb9SGleb Smirnoff static const struct icmpcodeent icmp_code[] = { 1423b3a8eb9SGleb Smirnoff { "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET }, 1433b3a8eb9SGleb Smirnoff { "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST }, 1443b3a8eb9SGleb Smirnoff { "proto-unr", ICMP_UNREACH, ICMP_UNREACH_PROTOCOL }, 1453b3a8eb9SGleb Smirnoff { "port-unr", ICMP_UNREACH, ICMP_UNREACH_PORT }, 1463b3a8eb9SGleb Smirnoff { "needfrag", ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG }, 1473b3a8eb9SGleb Smirnoff { "srcfail", ICMP_UNREACH, ICMP_UNREACH_SRCFAIL }, 1483b3a8eb9SGleb Smirnoff { "net-unk", ICMP_UNREACH, ICMP_UNREACH_NET_UNKNOWN }, 1493b3a8eb9SGleb Smirnoff { "host-unk", ICMP_UNREACH, ICMP_UNREACH_HOST_UNKNOWN }, 1503b3a8eb9SGleb Smirnoff { "isolate", ICMP_UNREACH, ICMP_UNREACH_ISOLATED }, 1513b3a8eb9SGleb Smirnoff { "net-prohib", ICMP_UNREACH, ICMP_UNREACH_NET_PROHIB }, 1523b3a8eb9SGleb Smirnoff { "host-prohib", ICMP_UNREACH, ICMP_UNREACH_HOST_PROHIB }, 1533b3a8eb9SGleb Smirnoff { "net-tos", ICMP_UNREACH, ICMP_UNREACH_TOSNET }, 1543b3a8eb9SGleb Smirnoff { "host-tos", ICMP_UNREACH, ICMP_UNREACH_TOSHOST }, 1553b3a8eb9SGleb Smirnoff { "filter-prohib", ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB }, 1563b3a8eb9SGleb Smirnoff { "host-preced", ICMP_UNREACH, ICMP_UNREACH_HOST_PRECEDENCE }, 1573b3a8eb9SGleb Smirnoff { "cutoff-preced", ICMP_UNREACH, ICMP_UNREACH_PRECEDENCE_CUTOFF }, 1583b3a8eb9SGleb Smirnoff { "redir-net", ICMP_REDIRECT, ICMP_REDIRECT_NET }, 1593b3a8eb9SGleb Smirnoff { "redir-host", ICMP_REDIRECT, ICMP_REDIRECT_HOST }, 1603b3a8eb9SGleb Smirnoff { "redir-tos-net", ICMP_REDIRECT, ICMP_REDIRECT_TOSNET }, 1613b3a8eb9SGleb Smirnoff { "redir-tos-host", ICMP_REDIRECT, ICMP_REDIRECT_TOSHOST }, 1623b3a8eb9SGleb Smirnoff { "normal-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL }, 1633b3a8eb9SGleb Smirnoff { "common-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON }, 1643b3a8eb9SGleb Smirnoff { "transit", ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS }, 1653b3a8eb9SGleb Smirnoff { "reassemb", ICMP_TIMXCEED, ICMP_TIMXCEED_REASS }, 1663b3a8eb9SGleb Smirnoff { "badhead", ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR }, 1673b3a8eb9SGleb Smirnoff { "optmiss", ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT }, 1683b3a8eb9SGleb Smirnoff { "badlen", ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH }, 1693b3a8eb9SGleb Smirnoff { "unknown-ind", ICMP_PHOTURIS, ICMP_PHOTURIS_UNKNOWN_INDEX }, 1703b3a8eb9SGleb Smirnoff { "auth-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_AUTH_FAILED }, 1713b3a8eb9SGleb Smirnoff { "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED } 1723b3a8eb9SGleb Smirnoff }; 1733b3a8eb9SGleb Smirnoff 1743b3a8eb9SGleb Smirnoff static const struct icmpcodeent icmp6_code[] = { 1753b3a8eb9SGleb Smirnoff { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN }, 1763b3a8eb9SGleb Smirnoff { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE }, 1773b3a8eb9SGleb Smirnoff { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR }, 1783b3a8eb9SGleb Smirnoff { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE }, 1793b3a8eb9SGleb Smirnoff { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR }, 1803b3a8eb9SGleb Smirnoff { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT }, 1813b3a8eb9SGleb Smirnoff { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT }, 1823b3a8eb9SGleb Smirnoff { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY }, 1833b3a8eb9SGleb Smirnoff { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER }, 1843b3a8eb9SGleb Smirnoff { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER }, 1853b3a8eb9SGleb Smirnoff { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK }, 1863b3a8eb9SGleb Smirnoff { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER } 1873b3a8eb9SGleb Smirnoff }; 1883b3a8eb9SGleb Smirnoff 1893b3a8eb9SGleb Smirnoff const struct pf_timeout pf_timeouts[] = { 1903b3a8eb9SGleb Smirnoff { "tcp.first", PFTM_TCP_FIRST_PACKET }, 1913b3a8eb9SGleb Smirnoff { "tcp.opening", PFTM_TCP_OPENING }, 1923b3a8eb9SGleb Smirnoff { "tcp.established", PFTM_TCP_ESTABLISHED }, 1933b3a8eb9SGleb Smirnoff { "tcp.closing", PFTM_TCP_CLOSING }, 1943b3a8eb9SGleb Smirnoff { "tcp.finwait", PFTM_TCP_FIN_WAIT }, 1953b3a8eb9SGleb Smirnoff { "tcp.closed", PFTM_TCP_CLOSED }, 1963b3a8eb9SGleb Smirnoff { "tcp.tsdiff", PFTM_TS_DIFF }, 1973b3a8eb9SGleb Smirnoff { "udp.first", PFTM_UDP_FIRST_PACKET }, 1983b3a8eb9SGleb Smirnoff { "udp.single", PFTM_UDP_SINGLE }, 1993b3a8eb9SGleb Smirnoff { "udp.multiple", PFTM_UDP_MULTIPLE }, 2003b3a8eb9SGleb Smirnoff { "icmp.first", PFTM_ICMP_FIRST_PACKET }, 2013b3a8eb9SGleb Smirnoff { "icmp.error", PFTM_ICMP_ERROR_REPLY }, 2023b3a8eb9SGleb Smirnoff { "other.first", PFTM_OTHER_FIRST_PACKET }, 2033b3a8eb9SGleb Smirnoff { "other.single", PFTM_OTHER_SINGLE }, 2043b3a8eb9SGleb Smirnoff { "other.multiple", PFTM_OTHER_MULTIPLE }, 2053b3a8eb9SGleb Smirnoff { "frag", PFTM_FRAG }, 2063b3a8eb9SGleb Smirnoff { "interval", PFTM_INTERVAL }, 2073b3a8eb9SGleb Smirnoff { "adaptive.start", PFTM_ADAPTIVE_START }, 2083b3a8eb9SGleb Smirnoff { "adaptive.end", PFTM_ADAPTIVE_END }, 2093b3a8eb9SGleb Smirnoff { "src.track", PFTM_SRC_NODE }, 2103b3a8eb9SGleb Smirnoff { NULL, 0 } 2113b3a8eb9SGleb Smirnoff }; 2123b3a8eb9SGleb Smirnoff 2131d34c9daSPatrick Kelsey static struct hsearch_data isgroup_map; 2141d34c9daSPatrick Kelsey 2151d34c9daSPatrick Kelsey static __attribute__((constructor)) void 2161d34c9daSPatrick Kelsey pfctl_parser_init(void) 2171d34c9daSPatrick Kelsey { 2181d34c9daSPatrick Kelsey /* 2191d34c9daSPatrick Kelsey * As hdestroy() will never be called on these tables, it will be 2201d34c9daSPatrick Kelsey * safe to use references into the stored data as keys. 2211d34c9daSPatrick Kelsey */ 2221d34c9daSPatrick Kelsey if (hcreate_r(0, &isgroup_map) == 0) 2231d34c9daSPatrick Kelsey err(1, "Failed to create interface group query response map"); 2241d34c9daSPatrick Kelsey } 2251d34c9daSPatrick Kelsey 2263b3a8eb9SGleb Smirnoff const struct icmptypeent * 2273b3a8eb9SGleb Smirnoff geticmptypebynumber(u_int8_t type, sa_family_t af) 2283b3a8eb9SGleb Smirnoff { 2293b3a8eb9SGleb Smirnoff unsigned int i; 2303b3a8eb9SGleb Smirnoff 2313b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 232c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_type); i++) { 2333b3a8eb9SGleb Smirnoff if (type == icmp_type[i].type) 2343b3a8eb9SGleb Smirnoff return (&icmp_type[i]); 2353b3a8eb9SGleb Smirnoff } 2363b3a8eb9SGleb Smirnoff } else { 237c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_type); i++) { 2383b3a8eb9SGleb Smirnoff if (type == icmp6_type[i].type) 2393b3a8eb9SGleb Smirnoff return (&icmp6_type[i]); 2403b3a8eb9SGleb Smirnoff } 2413b3a8eb9SGleb Smirnoff } 2423b3a8eb9SGleb Smirnoff return (NULL); 2433b3a8eb9SGleb Smirnoff } 2443b3a8eb9SGleb Smirnoff 2453b3a8eb9SGleb Smirnoff const struct icmptypeent * 2463b3a8eb9SGleb Smirnoff geticmptypebyname(char *w, sa_family_t af) 2473b3a8eb9SGleb Smirnoff { 2483b3a8eb9SGleb Smirnoff unsigned int i; 2493b3a8eb9SGleb Smirnoff 2503b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 251c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_type); i++) { 2523b3a8eb9SGleb Smirnoff if (!strcmp(w, icmp_type[i].name)) 2533b3a8eb9SGleb Smirnoff return (&icmp_type[i]); 2543b3a8eb9SGleb Smirnoff } 2553b3a8eb9SGleb Smirnoff } else { 256c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_type); i++) { 2573b3a8eb9SGleb Smirnoff if (!strcmp(w, icmp6_type[i].name)) 2583b3a8eb9SGleb Smirnoff return (&icmp6_type[i]); 2593b3a8eb9SGleb Smirnoff } 2603b3a8eb9SGleb Smirnoff } 2613b3a8eb9SGleb Smirnoff return (NULL); 2623b3a8eb9SGleb Smirnoff } 2633b3a8eb9SGleb Smirnoff 2643b3a8eb9SGleb Smirnoff const struct icmpcodeent * 2653b3a8eb9SGleb Smirnoff geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af) 2663b3a8eb9SGleb Smirnoff { 2673b3a8eb9SGleb Smirnoff unsigned int i; 2683b3a8eb9SGleb Smirnoff 2693b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 270c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_code); i++) { 2713b3a8eb9SGleb Smirnoff if (type == icmp_code[i].type && 2723b3a8eb9SGleb Smirnoff code == icmp_code[i].code) 2733b3a8eb9SGleb Smirnoff return (&icmp_code[i]); 2743b3a8eb9SGleb Smirnoff } 2753b3a8eb9SGleb Smirnoff } else { 276c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_code); i++) { 2773b3a8eb9SGleb Smirnoff if (type == icmp6_code[i].type && 2783b3a8eb9SGleb Smirnoff code == icmp6_code[i].code) 2793b3a8eb9SGleb Smirnoff return (&icmp6_code[i]); 2803b3a8eb9SGleb Smirnoff } 2813b3a8eb9SGleb Smirnoff } 2823b3a8eb9SGleb Smirnoff return (NULL); 2833b3a8eb9SGleb Smirnoff } 2843b3a8eb9SGleb Smirnoff 2853b3a8eb9SGleb Smirnoff const struct icmpcodeent * 2863b3a8eb9SGleb Smirnoff geticmpcodebyname(u_long type, char *w, sa_family_t af) 2873b3a8eb9SGleb Smirnoff { 2883b3a8eb9SGleb Smirnoff unsigned int i; 2893b3a8eb9SGleb Smirnoff 2903b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 291c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_code); i++) { 2923b3a8eb9SGleb Smirnoff if (type == icmp_code[i].type && 2933b3a8eb9SGleb Smirnoff !strcmp(w, icmp_code[i].name)) 2943b3a8eb9SGleb Smirnoff return (&icmp_code[i]); 2953b3a8eb9SGleb Smirnoff } 2963b3a8eb9SGleb Smirnoff } else { 297c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_code); i++) { 2983b3a8eb9SGleb Smirnoff if (type == icmp6_code[i].type && 2993b3a8eb9SGleb Smirnoff !strcmp(w, icmp6_code[i].name)) 3003b3a8eb9SGleb Smirnoff return (&icmp6_code[i]); 3013b3a8eb9SGleb Smirnoff } 3023b3a8eb9SGleb Smirnoff } 3033b3a8eb9SGleb Smirnoff return (NULL); 3043b3a8eb9SGleb Smirnoff } 3053b3a8eb9SGleb Smirnoff 3063b3a8eb9SGleb Smirnoff void 3073b3a8eb9SGleb Smirnoff print_op(u_int8_t op, const char *a1, const char *a2) 3083b3a8eb9SGleb Smirnoff { 3093b3a8eb9SGleb Smirnoff if (op == PF_OP_IRG) 3103b3a8eb9SGleb Smirnoff printf(" %s >< %s", a1, a2); 3113b3a8eb9SGleb Smirnoff else if (op == PF_OP_XRG) 3123b3a8eb9SGleb Smirnoff printf(" %s <> %s", a1, a2); 3133b3a8eb9SGleb Smirnoff else if (op == PF_OP_EQ) 3143b3a8eb9SGleb Smirnoff printf(" = %s", a1); 3153b3a8eb9SGleb Smirnoff else if (op == PF_OP_NE) 3163b3a8eb9SGleb Smirnoff printf(" != %s", a1); 3173b3a8eb9SGleb Smirnoff else if (op == PF_OP_LT) 3183b3a8eb9SGleb Smirnoff printf(" < %s", a1); 3193b3a8eb9SGleb Smirnoff else if (op == PF_OP_LE) 3203b3a8eb9SGleb Smirnoff printf(" <= %s", a1); 3213b3a8eb9SGleb Smirnoff else if (op == PF_OP_GT) 3223b3a8eb9SGleb Smirnoff printf(" > %s", a1); 3233b3a8eb9SGleb Smirnoff else if (op == PF_OP_GE) 3243b3a8eb9SGleb Smirnoff printf(" >= %s", a1); 3253b3a8eb9SGleb Smirnoff else if (op == PF_OP_RRG) 3263b3a8eb9SGleb Smirnoff printf(" %s:%s", a1, a2); 3273b3a8eb9SGleb Smirnoff } 3283b3a8eb9SGleb Smirnoff 3293b3a8eb9SGleb Smirnoff void 3303b3a8eb9SGleb Smirnoff print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int numeric) 3313b3a8eb9SGleb Smirnoff { 3323b3a8eb9SGleb Smirnoff char a1[6], a2[6]; 3333b3a8eb9SGleb Smirnoff struct servent *s; 3343b3a8eb9SGleb Smirnoff 3353b3a8eb9SGleb Smirnoff if (!numeric) 3363b3a8eb9SGleb Smirnoff s = getservbyport(p1, proto); 3373b3a8eb9SGleb Smirnoff else 3383b3a8eb9SGleb Smirnoff s = NULL; 3393b3a8eb9SGleb Smirnoff p1 = ntohs(p1); 3403b3a8eb9SGleb Smirnoff p2 = ntohs(p2); 3413b3a8eb9SGleb Smirnoff snprintf(a1, sizeof(a1), "%u", p1); 3423b3a8eb9SGleb Smirnoff snprintf(a2, sizeof(a2), "%u", p2); 3433b3a8eb9SGleb Smirnoff printf(" port"); 3443b3a8eb9SGleb Smirnoff if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE)) 3453b3a8eb9SGleb Smirnoff print_op(op, s->s_name, a2); 3463b3a8eb9SGleb Smirnoff else 3473b3a8eb9SGleb Smirnoff print_op(op, a1, a2); 3483b3a8eb9SGleb Smirnoff } 3493b3a8eb9SGleb Smirnoff 3503b3a8eb9SGleb Smirnoff void 3513b3a8eb9SGleb Smirnoff print_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax) 3523b3a8eb9SGleb Smirnoff { 3533b3a8eb9SGleb Smirnoff char a1[11], a2[11]; 3543b3a8eb9SGleb Smirnoff 3553b3a8eb9SGleb Smirnoff snprintf(a1, sizeof(a1), "%u", u1); 3563b3a8eb9SGleb Smirnoff snprintf(a2, sizeof(a2), "%u", u2); 3573b3a8eb9SGleb Smirnoff printf(" %s", t); 3583b3a8eb9SGleb Smirnoff if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE)) 3593b3a8eb9SGleb Smirnoff print_op(op, "unknown", a2); 3603b3a8eb9SGleb Smirnoff else 3613b3a8eb9SGleb Smirnoff print_op(op, a1, a2); 3623b3a8eb9SGleb Smirnoff } 3633b3a8eb9SGleb Smirnoff 3643b3a8eb9SGleb Smirnoff void 3653b3a8eb9SGleb Smirnoff print_flags(u_int8_t f) 3663b3a8eb9SGleb Smirnoff { 3673b3a8eb9SGleb Smirnoff int i; 3683b3a8eb9SGleb Smirnoff 3693b3a8eb9SGleb Smirnoff for (i = 0; tcpflags[i]; ++i) 3703b3a8eb9SGleb Smirnoff if (f & (1 << i)) 3713b3a8eb9SGleb Smirnoff printf("%c", tcpflags[i]); 3723b3a8eb9SGleb Smirnoff } 3733b3a8eb9SGleb Smirnoff 3743b3a8eb9SGleb Smirnoff void 3753b3a8eb9SGleb Smirnoff print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, 3763b3a8eb9SGleb Smirnoff sa_family_t af, u_int8_t proto, int verbose, int numeric) 3773b3a8eb9SGleb Smirnoff { 3783b3a8eb9SGleb Smirnoff char buf[PF_OSFP_LEN*3]; 3793b3a8eb9SGleb Smirnoff if (src->addr.type == PF_ADDR_ADDRMASK && 3803b3a8eb9SGleb Smirnoff dst->addr.type == PF_ADDR_ADDRMASK && 3813b3a8eb9SGleb Smirnoff PF_AZERO(&src->addr.v.a.addr, AF_INET6) && 3823b3a8eb9SGleb Smirnoff PF_AZERO(&src->addr.v.a.mask, AF_INET6) && 3833b3a8eb9SGleb Smirnoff PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && 3843b3a8eb9SGleb Smirnoff PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && 3853b3a8eb9SGleb Smirnoff !src->neg && !dst->neg && 3863b3a8eb9SGleb Smirnoff !src->port_op && !dst->port_op && 3873b3a8eb9SGleb Smirnoff osfp == PF_OSFP_ANY) 3883b3a8eb9SGleb Smirnoff printf(" all"); 3893b3a8eb9SGleb Smirnoff else { 3903b3a8eb9SGleb Smirnoff printf(" from "); 3913b3a8eb9SGleb Smirnoff if (src->neg) 3923b3a8eb9SGleb Smirnoff printf("! "); 3933b3a8eb9SGleb Smirnoff print_addr(&src->addr, af, verbose); 3943b3a8eb9SGleb Smirnoff if (src->port_op) 3953b3a8eb9SGleb Smirnoff print_port(src->port_op, src->port[0], 3963b3a8eb9SGleb Smirnoff src->port[1], 3973b3a8eb9SGleb Smirnoff proto == IPPROTO_TCP ? "tcp" : "udp", 3983b3a8eb9SGleb Smirnoff numeric); 3993b3a8eb9SGleb Smirnoff if (osfp != PF_OSFP_ANY) 4003b3a8eb9SGleb Smirnoff printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf, 4013b3a8eb9SGleb Smirnoff sizeof(buf))); 4023b3a8eb9SGleb Smirnoff 4033b3a8eb9SGleb Smirnoff printf(" to "); 4043b3a8eb9SGleb Smirnoff if (dst->neg) 4053b3a8eb9SGleb Smirnoff printf("! "); 4063b3a8eb9SGleb Smirnoff print_addr(&dst->addr, af, verbose); 4073b3a8eb9SGleb Smirnoff if (dst->port_op) 4083b3a8eb9SGleb Smirnoff print_port(dst->port_op, dst->port[0], 4093b3a8eb9SGleb Smirnoff dst->port[1], 4103b3a8eb9SGleb Smirnoff proto == IPPROTO_TCP ? "tcp" : "udp", 4113b3a8eb9SGleb Smirnoff numeric); 4123b3a8eb9SGleb Smirnoff } 4133b3a8eb9SGleb Smirnoff } 4143b3a8eb9SGleb Smirnoff 4153b3a8eb9SGleb Smirnoff void 416600bd6ceSKurosawa Takahiro print_pool(struct pfctl_pool *pool, u_int16_t p1, u_int16_t p2, 4173b3a8eb9SGleb Smirnoff sa_family_t af, int id) 4183b3a8eb9SGleb Smirnoff { 4193b3a8eb9SGleb Smirnoff struct pf_pooladdr *pooladdr; 4203b3a8eb9SGleb Smirnoff 4213b3a8eb9SGleb Smirnoff if ((TAILQ_FIRST(&pool->list) != NULL) && 4223b3a8eb9SGleb Smirnoff TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4233b3a8eb9SGleb Smirnoff printf("{ "); 4243b3a8eb9SGleb Smirnoff TAILQ_FOREACH(pooladdr, &pool->list, entries){ 4253b3a8eb9SGleb Smirnoff switch (id) { 4263b3a8eb9SGleb Smirnoff case PF_NAT: 4273b3a8eb9SGleb Smirnoff case PF_RDR: 4283b3a8eb9SGleb Smirnoff case PF_BINAT: 4293b3a8eb9SGleb Smirnoff print_addr(&pooladdr->addr, af, 0); 4303b3a8eb9SGleb Smirnoff break; 4313b3a8eb9SGleb Smirnoff case PF_PASS: 43239282ef3SKajetan Staszkiewicz case PF_MATCH: 4333b3a8eb9SGleb Smirnoff if (PF_AZERO(&pooladdr->addr.v.a.addr, af)) 4343b3a8eb9SGleb Smirnoff printf("%s", pooladdr->ifname); 4353b3a8eb9SGleb Smirnoff else { 4363b3a8eb9SGleb Smirnoff printf("(%s ", pooladdr->ifname); 4373b3a8eb9SGleb Smirnoff print_addr(&pooladdr->addr, af, 0); 4383b3a8eb9SGleb Smirnoff printf(")"); 4393b3a8eb9SGleb Smirnoff } 4403b3a8eb9SGleb Smirnoff break; 4413b3a8eb9SGleb Smirnoff default: 4423b3a8eb9SGleb Smirnoff break; 4433b3a8eb9SGleb Smirnoff } 4443b3a8eb9SGleb Smirnoff if (TAILQ_NEXT(pooladdr, entries) != NULL) 4453b3a8eb9SGleb Smirnoff printf(", "); 4463b3a8eb9SGleb Smirnoff else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4473b3a8eb9SGleb Smirnoff printf(" }"); 4483b3a8eb9SGleb Smirnoff } 4493b3a8eb9SGleb Smirnoff switch (id) { 4503b3a8eb9SGleb Smirnoff case PF_NAT: 4513b3a8eb9SGleb Smirnoff if ((p1 != PF_NAT_PROXY_PORT_LOW || 4523b3a8eb9SGleb Smirnoff p2 != PF_NAT_PROXY_PORT_HIGH) && (p1 != 0 || p2 != 0)) { 4533b3a8eb9SGleb Smirnoff if (p1 == p2) 4543b3a8eb9SGleb Smirnoff printf(" port %u", p1); 4553b3a8eb9SGleb Smirnoff else 4563b3a8eb9SGleb Smirnoff printf(" port %u:%u", p1, p2); 4573b3a8eb9SGleb Smirnoff } 4583b3a8eb9SGleb Smirnoff break; 4593b3a8eb9SGleb Smirnoff case PF_RDR: 4603b3a8eb9SGleb Smirnoff if (p1) { 4613b3a8eb9SGleb Smirnoff printf(" port %u", p1); 4623b3a8eb9SGleb Smirnoff if (p2 && (p2 != p1)) 4633b3a8eb9SGleb Smirnoff printf(":%u", p2); 4643b3a8eb9SGleb Smirnoff } 4653b3a8eb9SGleb Smirnoff break; 4663b3a8eb9SGleb Smirnoff default: 4673b3a8eb9SGleb Smirnoff break; 4683b3a8eb9SGleb Smirnoff } 4693b3a8eb9SGleb Smirnoff switch (pool->opts & PF_POOL_TYPEMASK) { 4703b3a8eb9SGleb Smirnoff case PF_POOL_NONE: 4713b3a8eb9SGleb Smirnoff break; 4723b3a8eb9SGleb Smirnoff case PF_POOL_BITMASK: 4733b3a8eb9SGleb Smirnoff printf(" bitmask"); 4743b3a8eb9SGleb Smirnoff break; 4753b3a8eb9SGleb Smirnoff case PF_POOL_RANDOM: 4763b3a8eb9SGleb Smirnoff printf(" random"); 4773b3a8eb9SGleb Smirnoff break; 4783b3a8eb9SGleb Smirnoff case PF_POOL_SRCHASH: 4793b3a8eb9SGleb Smirnoff printf(" source-hash 0x%08x%08x%08x%08x", 4803b3a8eb9SGleb Smirnoff pool->key.key32[0], pool->key.key32[1], 4813b3a8eb9SGleb Smirnoff pool->key.key32[2], pool->key.key32[3]); 4823b3a8eb9SGleb Smirnoff break; 4833b3a8eb9SGleb Smirnoff case PF_POOL_ROUNDROBIN: 4843b3a8eb9SGleb Smirnoff printf(" round-robin"); 4853b3a8eb9SGleb Smirnoff break; 4863b3a8eb9SGleb Smirnoff } 4873b3a8eb9SGleb Smirnoff if (pool->opts & PF_POOL_STICKYADDR) 4883b3a8eb9SGleb Smirnoff printf(" sticky-address"); 4893b3a8eb9SGleb Smirnoff if (id == PF_NAT && p1 == 0 && p2 == 0) 4903b3a8eb9SGleb Smirnoff printf(" static-port"); 4912aa21096SKurosawa Takahiro if (pool->mape.offset > 0) 4922aa21096SKurosawa Takahiro printf(" map-e-portset %u/%u/%u", 4932aa21096SKurosawa Takahiro pool->mape.offset, pool->mape.psidlen, pool->mape.psid); 4943b3a8eb9SGleb Smirnoff } 4953b3a8eb9SGleb Smirnoff 49672a3cf0fSKristof Provost const char * const pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 49772a3cf0fSKristof Provost const char * const pf_lcounters[LCNT_MAX+1] = LCNT_NAMES; 49872a3cf0fSKristof Provost const char * const pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 49972a3cf0fSKristof Provost const char * const pf_scounters[FCNT_MAX+1] = FCNT_NAMES; 5003b3a8eb9SGleb Smirnoff 5013b3a8eb9SGleb Smirnoff void 50280078d9dSKristof Provost print_status(struct pfctl_status *s, struct pfctl_syncookies *cookies, int opts) 5033b3a8eb9SGleb Smirnoff { 50480078d9dSKristof Provost struct pfctl_status_counter *c; 5053b3a8eb9SGleb Smirnoff char statline[80], *running; 5063b3a8eb9SGleb Smirnoff time_t runtime; 5073b3a8eb9SGleb Smirnoff int i; 5083b3a8eb9SGleb Smirnoff char buf[PF_MD5_DIGEST_LENGTH * 2 + 1]; 5093b3a8eb9SGleb Smirnoff static const char hex[] = "0123456789abcdef"; 5103b3a8eb9SGleb Smirnoff 5113b3a8eb9SGleb Smirnoff runtime = time(NULL) - s->since; 5123b3a8eb9SGleb Smirnoff running = s->running ? "Enabled" : "Disabled"; 5133b3a8eb9SGleb Smirnoff 5143b3a8eb9SGleb Smirnoff if (s->since) { 5153b3a8eb9SGleb Smirnoff unsigned int sec, min, hrs, day = runtime; 5163b3a8eb9SGleb Smirnoff 5173b3a8eb9SGleb Smirnoff sec = day % 60; 5183b3a8eb9SGleb Smirnoff day /= 60; 5193b3a8eb9SGleb Smirnoff min = day % 60; 5203b3a8eb9SGleb Smirnoff day /= 60; 5213b3a8eb9SGleb Smirnoff hrs = day % 24; 5223b3a8eb9SGleb Smirnoff day /= 24; 5233b3a8eb9SGleb Smirnoff snprintf(statline, sizeof(statline), 5243b3a8eb9SGleb Smirnoff "Status: %s for %u days %.2u:%.2u:%.2u", 5253b3a8eb9SGleb Smirnoff running, day, hrs, min, sec); 5263b3a8eb9SGleb Smirnoff } else 5273b3a8eb9SGleb Smirnoff snprintf(statline, sizeof(statline), "Status: %s", running); 5283b3a8eb9SGleb Smirnoff printf("%-44s", statline); 5293b3a8eb9SGleb Smirnoff switch (s->debug) { 5303b3a8eb9SGleb Smirnoff case PF_DEBUG_NONE: 5313b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: None"); 5323b3a8eb9SGleb Smirnoff break; 5333b3a8eb9SGleb Smirnoff case PF_DEBUG_URGENT: 5343b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Urgent"); 5353b3a8eb9SGleb Smirnoff break; 5363b3a8eb9SGleb Smirnoff case PF_DEBUG_MISC: 5373b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Misc"); 5383b3a8eb9SGleb Smirnoff break; 5393b3a8eb9SGleb Smirnoff case PF_DEBUG_NOISY: 5403b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Loud"); 5413b3a8eb9SGleb Smirnoff break; 5423b3a8eb9SGleb Smirnoff } 5433b3a8eb9SGleb Smirnoff 5443b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 545735748f3SKristof Provost printf("Hostid: 0x%08x\n", s->hostid); 5463b3a8eb9SGleb Smirnoff 5473b3a8eb9SGleb Smirnoff for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) { 5483b3a8eb9SGleb Smirnoff buf[i + i] = hex[s->pf_chksum[i] >> 4]; 5493b3a8eb9SGleb Smirnoff buf[i + i + 1] = hex[s->pf_chksum[i] & 0x0f]; 5503b3a8eb9SGleb Smirnoff } 5513b3a8eb9SGleb Smirnoff buf[i + i] = '\0'; 5523b3a8eb9SGleb Smirnoff printf("Checksum: 0x%s\n\n", buf); 5533b3a8eb9SGleb Smirnoff } 5543b3a8eb9SGleb Smirnoff 5553b3a8eb9SGleb Smirnoff if (s->ifname[0] != 0) { 5563b3a8eb9SGleb Smirnoff printf("Interface Stats for %-16s %5s %16s\n", 5573b3a8eb9SGleb Smirnoff s->ifname, "IPv4", "IPv6"); 5583b3a8eb9SGleb Smirnoff printf(" %-25s %14llu %16llu\n", "Bytes In", 5593b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[0][0], 5603b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[1][0]); 5613b3a8eb9SGleb Smirnoff printf(" %-25s %14llu %16llu\n", "Bytes Out", 5623b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[0][1], 5633b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[1][1]); 5643b3a8eb9SGleb Smirnoff printf(" Packets In\n"); 5653b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Passed", 5663b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][0][PF_PASS], 5673b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][0][PF_PASS]); 5683b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Blocked", 5693b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][0][PF_DROP], 5703b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][0][PF_DROP]); 5713b3a8eb9SGleb Smirnoff printf(" Packets Out\n"); 5723b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Passed", 5733b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][1][PF_PASS], 5743b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][1][PF_PASS]); 5753b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n\n", "Blocked", 5763b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][1][PF_DROP], 5773b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][1][PF_DROP]); 5783b3a8eb9SGleb Smirnoff } 5793b3a8eb9SGleb Smirnoff printf("%-27s %14s %16s\n", "State Table", "Total", "Rate"); 580846a6e8fSKristof Provost printf(" %-25s %14ju %14s\n", "current entries", s->states, ""); 58180078d9dSKristof Provost TAILQ_FOREACH(c, &s->fcounters, entry) { 582846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 5833b3a8eb9SGleb Smirnoff if (runtime > 0) 5843b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 58580078d9dSKristof Provost (double)c->counter / (double)runtime); 5863b3a8eb9SGleb Smirnoff else 5873b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 5883b3a8eb9SGleb Smirnoff } 5893b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 5903b3a8eb9SGleb Smirnoff printf("Source Tracking Table\n"); 591846a6e8fSKristof Provost printf(" %-25s %14ju %14s\n", "current entries", 5923b3a8eb9SGleb Smirnoff s->src_nodes, ""); 59380078d9dSKristof Provost TAILQ_FOREACH(c, &s->scounters, entry) { 594846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 5953b3a8eb9SGleb Smirnoff if (runtime > 0) 5963b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 59780078d9dSKristof Provost (double)c->counter / (double)runtime); 5983b3a8eb9SGleb Smirnoff else 5993b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6003b3a8eb9SGleb Smirnoff } 6013b3a8eb9SGleb Smirnoff } 6023b3a8eb9SGleb Smirnoff printf("Counters\n"); 60380078d9dSKristof Provost TAILQ_FOREACH(c, &s->counters, entry) { 604846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 6053b3a8eb9SGleb Smirnoff if (runtime > 0) 6063b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 60780078d9dSKristof Provost (double)c->counter / (double)runtime); 6083b3a8eb9SGleb Smirnoff else 6093b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6103b3a8eb9SGleb Smirnoff } 6113b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 6123b3a8eb9SGleb Smirnoff printf("Limit Counters\n"); 61380078d9dSKristof Provost TAILQ_FOREACH(c, &s->lcounters, entry) { 614846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 6153b3a8eb9SGleb Smirnoff if (runtime > 0) 6163b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 61780078d9dSKristof Provost (double)c->counter / (double)runtime); 6183b3a8eb9SGleb Smirnoff else 6193b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6203b3a8eb9SGleb Smirnoff } 621c69121c4SKristof Provost 622c69121c4SKristof Provost printf("Syncookies\n"); 6235062afffSKristof Provost assert(cookies->mode <= PFCTL_SYNCOOKIES_ADAPTIVE); 624c69121c4SKristof Provost printf(" %-25s %s\n", "mode", 6255062afffSKristof Provost PFCTL_SYNCOOKIES_MODE_NAMES[cookies->mode]); 626444a77caSKristof Provost printf(" %-25s %s\n", "active", 627444a77caSKristof Provost s->syncookies_active ? "active" : "inactive"); 62839282ef3SKajetan Staszkiewicz printf("Reassemble %24s %s\n", 62939282ef3SKajetan Staszkiewicz s->reass & PF_REASS_ENABLED ? "yes" : "no", 63039282ef3SKajetan Staszkiewicz s->reass & PF_REASS_NODF ? "no-df" : "" 63139282ef3SKajetan Staszkiewicz ); 6323b3a8eb9SGleb Smirnoff } 6333b3a8eb9SGleb Smirnoff } 6343b3a8eb9SGleb Smirnoff 6353b3a8eb9SGleb Smirnoff void 63680078d9dSKristof Provost print_running(struct pfctl_status *status) 637fa1d4439SKristof Provost { 638fa1d4439SKristof Provost printf("%s\n", status->running ? "Enabled" : "Disabled"); 639fa1d4439SKristof Provost } 640fa1d4439SKristof Provost 641fa1d4439SKristof Provost void 6423b3a8eb9SGleb Smirnoff print_src_node(struct pf_src_node *sn, int opts) 6433b3a8eb9SGleb Smirnoff { 6443b3a8eb9SGleb Smirnoff struct pf_addr_wrap aw; 6453b3a8eb9SGleb Smirnoff int min, sec; 6463b3a8eb9SGleb Smirnoff 6473b3a8eb9SGleb Smirnoff memset(&aw, 0, sizeof(aw)); 6483b3a8eb9SGleb Smirnoff if (sn->af == AF_INET) 6493b3a8eb9SGleb Smirnoff aw.v.a.mask.addr32[0] = 0xffffffff; 6503b3a8eb9SGleb Smirnoff else 6513b3a8eb9SGleb Smirnoff memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask)); 6523b3a8eb9SGleb Smirnoff 6533b3a8eb9SGleb Smirnoff aw.v.a.addr = sn->addr; 6543b3a8eb9SGleb Smirnoff print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); 6553b3a8eb9SGleb Smirnoff printf(" -> "); 6563b3a8eb9SGleb Smirnoff aw.v.a.addr = sn->raddr; 6573b3a8eb9SGleb Smirnoff print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); 6583b3a8eb9SGleb Smirnoff printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states, 6593b3a8eb9SGleb Smirnoff sn->conn, sn->conn_rate.count / 1000, 6603b3a8eb9SGleb Smirnoff (sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds); 6613b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 6623b3a8eb9SGleb Smirnoff sec = sn->creation % 60; 6633b3a8eb9SGleb Smirnoff sn->creation /= 60; 6643b3a8eb9SGleb Smirnoff min = sn->creation % 60; 6653b3a8eb9SGleb Smirnoff sn->creation /= 60; 6663b3a8eb9SGleb Smirnoff printf(" age %.2u:%.2u:%.2u", sn->creation, min, sec); 6673b3a8eb9SGleb Smirnoff if (sn->states == 0) { 6683b3a8eb9SGleb Smirnoff sec = sn->expire % 60; 6693b3a8eb9SGleb Smirnoff sn->expire /= 60; 6703b3a8eb9SGleb Smirnoff min = sn->expire % 60; 6713b3a8eb9SGleb Smirnoff sn->expire /= 60; 6723b3a8eb9SGleb Smirnoff printf(", expires in %.2u:%.2u:%.2u", 6733b3a8eb9SGleb Smirnoff sn->expire, min, sec); 6743b3a8eb9SGleb Smirnoff } 6753b3a8eb9SGleb Smirnoff printf(", %llu pkts, %llu bytes", 6763b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 6773b3a8eb9SGleb Smirnoff (unsigned long long)(sn->packets[0] + sn->packets[1]), 6783b3a8eb9SGleb Smirnoff (unsigned long long)(sn->bytes[0] + sn->bytes[1])); 6793b3a8eb9SGleb Smirnoff #else 6803b3a8eb9SGleb Smirnoff sn->packets[0] + sn->packets[1], 6813b3a8eb9SGleb Smirnoff sn->bytes[0] + sn->bytes[1]); 6823b3a8eb9SGleb Smirnoff #endif 6833b3a8eb9SGleb Smirnoff switch (sn->ruletype) { 6843b3a8eb9SGleb Smirnoff case PF_NAT: 6853b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 6863b3a8eb9SGleb Smirnoff printf(", nat rule %u", sn->rule.nr); 6873b3a8eb9SGleb Smirnoff break; 6883b3a8eb9SGleb Smirnoff case PF_RDR: 6893b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 6903b3a8eb9SGleb Smirnoff printf(", rdr rule %u", sn->rule.nr); 6913b3a8eb9SGleb Smirnoff break; 6923b3a8eb9SGleb Smirnoff case PF_PASS: 69339282ef3SKajetan Staszkiewicz case PF_MATCH: 6943b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 6953b3a8eb9SGleb Smirnoff printf(", filter rule %u", sn->rule.nr); 6963b3a8eb9SGleb Smirnoff break; 6973b3a8eb9SGleb Smirnoff } 6983b3a8eb9SGleb Smirnoff printf("\n"); 6993b3a8eb9SGleb Smirnoff } 7003b3a8eb9SGleb Smirnoff } 7013b3a8eb9SGleb Smirnoff 7022b29ceb8SKristof Provost static void 7032b29ceb8SKristof Provost print_eth_addr(const struct pfctl_eth_addr *a) 7042b29ceb8SKristof Provost { 705b590f17aSKristof Provost int i, masklen = ETHER_ADDR_LEN * 8; 706b590f17aSKristof Provost bool seen_unset = false; 707b590f17aSKristof Provost 708c696d5c7SKristof Provost for (i = 0; i < ETHER_ADDR_LEN; i++) { 709c696d5c7SKristof Provost if (a->addr[i] != 0) 710c696d5c7SKristof Provost break; 711c696d5c7SKristof Provost } 712c696d5c7SKristof Provost 713c696d5c7SKristof Provost /* Unset, so don't print anything. */ 714c696d5c7SKristof Provost if (i == ETHER_ADDR_LEN) 715c696d5c7SKristof Provost return; 716c696d5c7SKristof Provost 7172b29ceb8SKristof Provost printf("%s%02x:%02x:%02x:%02x:%02x:%02x", a->neg ? "! " : "", 7182b29ceb8SKristof Provost a->addr[0], a->addr[1], a->addr[2], a->addr[3], a->addr[4], 7192b29ceb8SKristof Provost a->addr[5]); 720b590f17aSKristof Provost 721b590f17aSKristof Provost for (i = 0; i < (ETHER_ADDR_LEN * 8); i++) { 722b590f17aSKristof Provost bool isset = a->mask[i / 8] & (1 << i % 8); 723b590f17aSKristof Provost 724b590f17aSKristof Provost if (! seen_unset) { 725b590f17aSKristof Provost if (isset) 726b590f17aSKristof Provost continue; 727b590f17aSKristof Provost seen_unset = true; 728b590f17aSKristof Provost masklen = i; 729b590f17aSKristof Provost } else { 730b590f17aSKristof Provost /* Not actually a continuous mask, so print the whole 731b590f17aSKristof Provost * thing. */ 732b590f17aSKristof Provost if (isset) 733b590f17aSKristof Provost break; 734b590f17aSKristof Provost continue; 735b590f17aSKristof Provost } 736b590f17aSKristof Provost } 737b590f17aSKristof Provost 738b590f17aSKristof Provost if (masklen == (ETHER_ADDR_LEN * 8)) 739b590f17aSKristof Provost return; 740b590f17aSKristof Provost 741b590f17aSKristof Provost if (i == (ETHER_ADDR_LEN * 8)) { 742b590f17aSKristof Provost printf("/%d", masklen); 743b590f17aSKristof Provost return; 744b590f17aSKristof Provost } 745b590f17aSKristof Provost 746b590f17aSKristof Provost printf("&%02x:%02x:%02x:%02x:%02x:%02x", 747b590f17aSKristof Provost a->mask[0], a->mask[1], a->mask[2], a->mask[3], a->mask[4], 748b590f17aSKristof Provost a->mask[5]); 7492b29ceb8SKristof Provost } 7502b29ceb8SKristof Provost 7512b29ceb8SKristof Provost void 752c5131afeSKristof Provost print_eth_rule(struct pfctl_eth_rule *r, const char *anchor_call, 753c5131afeSKristof Provost int rule_numbers) 7542b29ceb8SKristof Provost { 755d27c9f5bSKristof Provost static const char *actiontypes[] = { "pass", "block", "", "", "", "", 756d27c9f5bSKristof Provost "", "", "", "", "", "", "match" }; 7572b29ceb8SKristof Provost 758*ef661d4aSChristian McDonald int i; 759*ef661d4aSChristian McDonald 7602b29ceb8SKristof Provost if (rule_numbers) 7612b29ceb8SKristof Provost printf("@%u ", r->nr); 7622b29ceb8SKristof Provost 763c5131afeSKristof Provost printf("ether "); 764c5131afeSKristof Provost if (anchor_call[0]) { 765c5131afeSKristof Provost if (anchor_call[0] == '_') { 766c5131afeSKristof Provost printf("anchor"); 767c5131afeSKristof Provost } else 768c5131afeSKristof Provost printf("anchor \"%s\"", anchor_call); 769c5131afeSKristof Provost } else { 770c5131afeSKristof Provost printf("%s", actiontypes[r->action]); 771c5131afeSKristof Provost } 7722b29ceb8SKristof Provost if (r->direction == PF_IN) 7732b29ceb8SKristof Provost printf(" in"); 7742b29ceb8SKristof Provost else if (r->direction == PF_OUT) 7752b29ceb8SKristof Provost printf(" out"); 7762b29ceb8SKristof Provost 7772b29ceb8SKristof Provost if (r->quick) 7782b29ceb8SKristof Provost printf(" quick"); 7792b29ceb8SKristof Provost if (r->ifname[0]) { 7802b29ceb8SKristof Provost if (r->ifnot) 7812b29ceb8SKristof Provost printf(" on ! %s", r->ifname); 7822b29ceb8SKristof Provost else 7832b29ceb8SKristof Provost printf(" on %s", r->ifname); 7842b29ceb8SKristof Provost } 7858a8af942SKristof Provost if (r->bridge_to[0]) 7868a8af942SKristof Provost printf(" bridge-to %s", r->bridge_to); 7872b29ceb8SKristof Provost if (r->proto) 7882b29ceb8SKristof Provost printf(" proto 0x%04x", r->proto); 7892b29ceb8SKristof Provost 790c696d5c7SKristof Provost if (r->src.isset) { 7912b29ceb8SKristof Provost printf(" from "); 7922b29ceb8SKristof Provost print_eth_addr(&r->src); 793c696d5c7SKristof Provost } 794c696d5c7SKristof Provost if (r->dst.isset) { 7952b29ceb8SKristof Provost printf(" to "); 7962b29ceb8SKristof Provost print_eth_addr(&r->dst); 797c696d5c7SKristof Provost } 7988a42005dSKristof Provost printf(" l3"); 7998a42005dSKristof Provost print_fromto(&r->ipsrc, PF_OSFP_ANY, &r->ipdst, 8008a42005dSKristof Provost r->proto == ETHERTYPE_IP ? AF_INET : AF_INET6, 0, 8018a42005dSKristof Provost 0, 0); 802*ef661d4aSChristian McDonald 803*ef661d4aSChristian McDonald i = 0; 804*ef661d4aSChristian McDonald while (r->label[i][0]) 805*ef661d4aSChristian McDonald printf(" label \"%s\"", r->label[i++]); 806*ef661d4aSChristian McDonald if (r->ridentifier) 807*ef661d4aSChristian McDonald printf(" ridentifier %u", r->ridentifier); 808*ef661d4aSChristian McDonald 8092b29ceb8SKristof Provost if (r->qname[0]) 8102b29ceb8SKristof Provost printf(" queue %s", r->qname); 8112b29ceb8SKristof Provost if (r->tagname[0]) 8122b29ceb8SKristof Provost printf(" tag %s", r->tagname); 8131f61367fSKristof Provost if (r->match_tagname[0]) { 8141f61367fSKristof Provost if (r->match_tag_not) 8151f61367fSKristof Provost printf(" !"); 8161f61367fSKristof Provost printf(" tagged %s", r->match_tagname); 8171f61367fSKristof Provost } 818fb330f39SKristof Provost if (r->dnpipe) 819fb330f39SKristof Provost printf(" %s %d", 820fb330f39SKristof Provost r->dnflags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", 821fb330f39SKristof Provost r->dnpipe); 8222b29ceb8SKristof Provost } 8232b29ceb8SKristof Provost 8243b3a8eb9SGleb Smirnoff void 825e9eb0941SKristof Provost print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numeric) 8263b3a8eb9SGleb Smirnoff { 8273b3a8eb9SGleb Smirnoff static const char *actiontypes[] = { "pass", "block", "scrub", 82839282ef3SKajetan Staszkiewicz "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr", 82939282ef3SKajetan Staszkiewicz "", "", "match"}; 8303b3a8eb9SGleb Smirnoff static const char *anchortypes[] = { "anchor", "anchor", "anchor", 8313b3a8eb9SGleb Smirnoff "anchor", "nat-anchor", "nat-anchor", "binat-anchor", 8323b3a8eb9SGleb Smirnoff "binat-anchor", "rdr-anchor", "rdr-anchor" }; 8333b3a8eb9SGleb Smirnoff int i, opts; 834585a5ed0SKristof Provost char *p; 8353b3a8eb9SGleb Smirnoff 8363b3a8eb9SGleb Smirnoff if (verbose) 8373b3a8eb9SGleb Smirnoff printf("@%d ", r->nr); 838ef950daaSKristof Provost if (r->action == PF_MATCH) 839ef950daaSKristof Provost printf("match"); 840ef950daaSKristof Provost else if (r->action > PF_NORDR) 8413b3a8eb9SGleb Smirnoff printf("action(%d)", r->action); 8423b3a8eb9SGleb Smirnoff else if (anchor_call[0]) { 843585a5ed0SKristof Provost p = strrchr(anchor_call, '/'); 844585a5ed0SKristof Provost if (p ? p[1] == '_' : anchor_call[0] == '_') 8453b3a8eb9SGleb Smirnoff printf("%s", anchortypes[r->action]); 846585a5ed0SKristof Provost else 8473b3a8eb9SGleb Smirnoff printf("%s \"%s\"", anchortypes[r->action], 8483b3a8eb9SGleb Smirnoff anchor_call); 8493b3a8eb9SGleb Smirnoff } else { 8503b3a8eb9SGleb Smirnoff printf("%s", actiontypes[r->action]); 8513b3a8eb9SGleb Smirnoff if (r->natpass) 8523b3a8eb9SGleb Smirnoff printf(" pass"); 8533b3a8eb9SGleb Smirnoff } 8543b3a8eb9SGleb Smirnoff if (r->action == PF_DROP) { 8553b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RETURN) 8563b3a8eb9SGleb Smirnoff printf(" return"); 8573b3a8eb9SGleb Smirnoff else if (r->rule_flag & PFRULE_RETURNRST) { 8583b3a8eb9SGleb Smirnoff if (!r->return_ttl) 8593b3a8eb9SGleb Smirnoff printf(" return-rst"); 8603b3a8eb9SGleb Smirnoff else 8613b3a8eb9SGleb Smirnoff printf(" return-rst(ttl %d)", r->return_ttl); 8623b3a8eb9SGleb Smirnoff } else if (r->rule_flag & PFRULE_RETURNICMP) { 8633b3a8eb9SGleb Smirnoff const struct icmpcodeent *ic, *ic6; 8643b3a8eb9SGleb Smirnoff 8653b3a8eb9SGleb Smirnoff ic = geticmpcodebynumber(r->return_icmp >> 8, 8663b3a8eb9SGleb Smirnoff r->return_icmp & 255, AF_INET); 8673b3a8eb9SGleb Smirnoff ic6 = geticmpcodebynumber(r->return_icmp6 >> 8, 8683b3a8eb9SGleb Smirnoff r->return_icmp6 & 255, AF_INET6); 8693b3a8eb9SGleb Smirnoff 8703b3a8eb9SGleb Smirnoff switch (r->af) { 8713b3a8eb9SGleb Smirnoff case AF_INET: 8723b3a8eb9SGleb Smirnoff printf(" return-icmp"); 8733b3a8eb9SGleb Smirnoff if (ic == NULL) 8743b3a8eb9SGleb Smirnoff printf("(%u)", r->return_icmp & 255); 8753b3a8eb9SGleb Smirnoff else 8763b3a8eb9SGleb Smirnoff printf("(%s)", ic->name); 8773b3a8eb9SGleb Smirnoff break; 8783b3a8eb9SGleb Smirnoff case AF_INET6: 8793b3a8eb9SGleb Smirnoff printf(" return-icmp6"); 8803b3a8eb9SGleb Smirnoff if (ic6 == NULL) 8813b3a8eb9SGleb Smirnoff printf("(%u)", r->return_icmp6 & 255); 8823b3a8eb9SGleb Smirnoff else 8833b3a8eb9SGleb Smirnoff printf("(%s)", ic6->name); 8843b3a8eb9SGleb Smirnoff break; 8853b3a8eb9SGleb Smirnoff default: 8863b3a8eb9SGleb Smirnoff printf(" return-icmp"); 8873b3a8eb9SGleb Smirnoff if (ic == NULL) 8883b3a8eb9SGleb Smirnoff printf("(%u, ", r->return_icmp & 255); 8893b3a8eb9SGleb Smirnoff else 8903b3a8eb9SGleb Smirnoff printf("(%s, ", ic->name); 8913b3a8eb9SGleb Smirnoff if (ic6 == NULL) 8923b3a8eb9SGleb Smirnoff printf("%u)", r->return_icmp6 & 255); 8933b3a8eb9SGleb Smirnoff else 8943b3a8eb9SGleb Smirnoff printf("%s)", ic6->name); 8953b3a8eb9SGleb Smirnoff break; 8963b3a8eb9SGleb Smirnoff } 8973b3a8eb9SGleb Smirnoff } else 8983b3a8eb9SGleb Smirnoff printf(" drop"); 8993b3a8eb9SGleb Smirnoff } 9003b3a8eb9SGleb Smirnoff if (r->direction == PF_IN) 9013b3a8eb9SGleb Smirnoff printf(" in"); 9023b3a8eb9SGleb Smirnoff else if (r->direction == PF_OUT) 9033b3a8eb9SGleb Smirnoff printf(" out"); 9043b3a8eb9SGleb Smirnoff if (r->log) { 9053b3a8eb9SGleb Smirnoff printf(" log"); 9063b3a8eb9SGleb Smirnoff if (r->log & ~PF_LOG || r->logif) { 9073b3a8eb9SGleb Smirnoff int count = 0; 9083b3a8eb9SGleb Smirnoff 9093b3a8eb9SGleb Smirnoff printf(" ("); 9103b3a8eb9SGleb Smirnoff if (r->log & PF_LOG_ALL) 9113b3a8eb9SGleb Smirnoff printf("%sall", count++ ? ", " : ""); 9123b3a8eb9SGleb Smirnoff if (r->log & PF_LOG_SOCKET_LOOKUP) 9133b3a8eb9SGleb Smirnoff printf("%suser", count++ ? ", " : ""); 9143b3a8eb9SGleb Smirnoff if (r->logif) 9153b3a8eb9SGleb Smirnoff printf("%sto pflog%u", count++ ? ", " : "", 9163b3a8eb9SGleb Smirnoff r->logif); 9173b3a8eb9SGleb Smirnoff printf(")"); 9183b3a8eb9SGleb Smirnoff } 9193b3a8eb9SGleb Smirnoff } 9203b3a8eb9SGleb Smirnoff if (r->quick) 9213b3a8eb9SGleb Smirnoff printf(" quick"); 9223b3a8eb9SGleb Smirnoff if (r->ifname[0]) { 9233b3a8eb9SGleb Smirnoff if (r->ifnot) 9243b3a8eb9SGleb Smirnoff printf(" on ! %s", r->ifname); 9253b3a8eb9SGleb Smirnoff else 9263b3a8eb9SGleb Smirnoff printf(" on %s", r->ifname); 9273b3a8eb9SGleb Smirnoff } 9283b3a8eb9SGleb Smirnoff if (r->rt) { 9293b3a8eb9SGleb Smirnoff if (r->rt == PF_ROUTETO) 9303b3a8eb9SGleb Smirnoff printf(" route-to"); 9313b3a8eb9SGleb Smirnoff else if (r->rt == PF_REPLYTO) 9323b3a8eb9SGleb Smirnoff printf(" reply-to"); 9333b3a8eb9SGleb Smirnoff else if (r->rt == PF_DUPTO) 9343b3a8eb9SGleb Smirnoff printf(" dup-to"); 9353b3a8eb9SGleb Smirnoff printf(" "); 9363b3a8eb9SGleb Smirnoff print_pool(&r->rpool, 0, 0, r->af, PF_PASS); 9373b3a8eb9SGleb Smirnoff } 9383b3a8eb9SGleb Smirnoff if (r->af) { 9393b3a8eb9SGleb Smirnoff if (r->af == AF_INET) 9403b3a8eb9SGleb Smirnoff printf(" inet"); 9413b3a8eb9SGleb Smirnoff else 9423b3a8eb9SGleb Smirnoff printf(" inet6"); 9433b3a8eb9SGleb Smirnoff } 9443b3a8eb9SGleb Smirnoff if (r->proto) { 945858937beSMateusz Guzik const char *protoname; 9463b3a8eb9SGleb Smirnoff 947858937beSMateusz Guzik if ((protoname = pfctl_proto2name(r->proto)) != NULL) 948858937beSMateusz Guzik printf(" proto %s", protoname); 9493b3a8eb9SGleb Smirnoff else 9503b3a8eb9SGleb Smirnoff printf(" proto %u", r->proto); 9513b3a8eb9SGleb Smirnoff } 9523b3a8eb9SGleb Smirnoff print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto, 9533b3a8eb9SGleb Smirnoff verbose, numeric); 9543b3a8eb9SGleb Smirnoff if (r->uid.op) 9553b3a8eb9SGleb Smirnoff print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user", 9563b3a8eb9SGleb Smirnoff UID_MAX); 9573b3a8eb9SGleb Smirnoff if (r->gid.op) 9583b3a8eb9SGleb Smirnoff print_ugid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group", 9593b3a8eb9SGleb Smirnoff GID_MAX); 9603b3a8eb9SGleb Smirnoff if (r->flags || r->flagset) { 9613b3a8eb9SGleb Smirnoff printf(" flags "); 9623b3a8eb9SGleb Smirnoff print_flags(r->flags); 9633b3a8eb9SGleb Smirnoff printf("/"); 9643b3a8eb9SGleb Smirnoff print_flags(r->flagset); 96539282ef3SKajetan Staszkiewicz } else if ((r->action == PF_PASS || r->action == PF_MATCH) && 9663b3a8eb9SGleb Smirnoff (!r->proto || r->proto == IPPROTO_TCP) && 9673b3a8eb9SGleb Smirnoff !(r->rule_flag & PFRULE_FRAGMENT) && 9683b3a8eb9SGleb Smirnoff !anchor_call[0] && r->keep_state) 9693b3a8eb9SGleb Smirnoff printf(" flags any"); 9703b3a8eb9SGleb Smirnoff if (r->type) { 9713b3a8eb9SGleb Smirnoff const struct icmptypeent *it; 9723b3a8eb9SGleb Smirnoff 9733b3a8eb9SGleb Smirnoff it = geticmptypebynumber(r->type-1, r->af); 9743b3a8eb9SGleb Smirnoff if (r->af != AF_INET6) 9753b3a8eb9SGleb Smirnoff printf(" icmp-type"); 9763b3a8eb9SGleb Smirnoff else 9773b3a8eb9SGleb Smirnoff printf(" icmp6-type"); 9783b3a8eb9SGleb Smirnoff if (it != NULL) 9793b3a8eb9SGleb Smirnoff printf(" %s", it->name); 9803b3a8eb9SGleb Smirnoff else 9813b3a8eb9SGleb Smirnoff printf(" %u", r->type-1); 9823b3a8eb9SGleb Smirnoff if (r->code) { 9833b3a8eb9SGleb Smirnoff const struct icmpcodeent *ic; 9843b3a8eb9SGleb Smirnoff 9853b3a8eb9SGleb Smirnoff ic = geticmpcodebynumber(r->type-1, r->code-1, r->af); 9863b3a8eb9SGleb Smirnoff if (ic != NULL) 9873b3a8eb9SGleb Smirnoff printf(" code %s", ic->name); 9883b3a8eb9SGleb Smirnoff else 9893b3a8eb9SGleb Smirnoff printf(" code %u", r->code-1); 9903b3a8eb9SGleb Smirnoff } 9913b3a8eb9SGleb Smirnoff } 9923b3a8eb9SGleb Smirnoff if (r->tos) 9933b3a8eb9SGleb Smirnoff printf(" tos 0x%2.2x", r->tos); 9943e248e0fSKristof Provost if (r->prio) 9953e248e0fSKristof Provost printf(" prio %u", r->prio == PF_PRIO_ZERO ? 0 : r->prio); 9963e248e0fSKristof Provost if (r->scrub_flags & PFSTATE_SETMASK) { 9973e248e0fSKristof Provost char *comma = ""; 9983e248e0fSKristof Provost printf(" set ("); 9993e248e0fSKristof Provost if (r->scrub_flags & PFSTATE_SETPRIO) { 10003e248e0fSKristof Provost if (r->set_prio[0] == r->set_prio[1]) 10013e248e0fSKristof Provost printf("%s prio %u", comma, r->set_prio[0]); 10023e248e0fSKristof Provost else 10033e248e0fSKristof Provost printf("%s prio(%u, %u)", comma, r->set_prio[0], 10043e248e0fSKristof Provost r->set_prio[1]); 10053e248e0fSKristof Provost comma = ","; 10063e248e0fSKristof Provost } 100739282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_SETTOS) { 100839282ef3SKajetan Staszkiewicz printf("%s tos 0x%2.2x", comma, r->set_tos); 100939282ef3SKajetan Staszkiewicz comma = ","; 101039282ef3SKajetan Staszkiewicz } 10113e248e0fSKristof Provost printf(" )"); 10123e248e0fSKristof Provost } 10133b3a8eb9SGleb Smirnoff if (!r->keep_state && r->action == PF_PASS && !anchor_call[0]) 10143b3a8eb9SGleb Smirnoff printf(" no state"); 10153b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_NORMAL) 10163b3a8eb9SGleb Smirnoff printf(" keep state"); 10173b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_MODULATE) 10183b3a8eb9SGleb Smirnoff printf(" modulate state"); 10193b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_SYNPROXY) 10203b3a8eb9SGleb Smirnoff printf(" synproxy state"); 10213b3a8eb9SGleb Smirnoff if (r->prob) { 10223b3a8eb9SGleb Smirnoff char buf[20]; 10233b3a8eb9SGleb Smirnoff 10243b3a8eb9SGleb Smirnoff snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0)); 10253b3a8eb9SGleb Smirnoff for (i = strlen(buf)-1; i > 0; i--) { 10263b3a8eb9SGleb Smirnoff if (buf[i] == '0') 10273b3a8eb9SGleb Smirnoff buf[i] = '\0'; 10283b3a8eb9SGleb Smirnoff else { 10293b3a8eb9SGleb Smirnoff if (buf[i] == '.') 10303b3a8eb9SGleb Smirnoff buf[i] = '\0'; 10313b3a8eb9SGleb Smirnoff break; 10323b3a8eb9SGleb Smirnoff } 10333b3a8eb9SGleb Smirnoff } 10343b3a8eb9SGleb Smirnoff printf(" probability %s%%", buf); 10353b3a8eb9SGleb Smirnoff } 10363b3a8eb9SGleb Smirnoff opts = 0; 10373b3a8eb9SGleb Smirnoff if (r->max_states || r->max_src_nodes || r->max_src_states) 10383b3a8eb9SGleb Smirnoff opts = 1; 10393b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NOSYNC) 10403b3a8eb9SGleb Smirnoff opts = 1; 10413b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SRCTRACK) 10423b3a8eb9SGleb Smirnoff opts = 1; 10433b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_IFBOUND) 10443b3a8eb9SGleb Smirnoff opts = 1; 10453b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY) 10463b3a8eb9SGleb Smirnoff opts = 1; 10473b3a8eb9SGleb Smirnoff for (i = 0; !opts && i < PFTM_MAX; ++i) 10483b3a8eb9SGleb Smirnoff if (r->timeout[i]) 10493b3a8eb9SGleb Smirnoff opts = 1; 10503b3a8eb9SGleb Smirnoff if (opts) { 10513b3a8eb9SGleb Smirnoff printf(" ("); 10523b3a8eb9SGleb Smirnoff if (r->max_states) { 10533b3a8eb9SGleb Smirnoff printf("max %u", r->max_states); 10543b3a8eb9SGleb Smirnoff opts = 0; 10553b3a8eb9SGleb Smirnoff } 10563b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NOSYNC) { 10573b3a8eb9SGleb Smirnoff if (!opts) 10583b3a8eb9SGleb Smirnoff printf(", "); 10593b3a8eb9SGleb Smirnoff printf("no-sync"); 10603b3a8eb9SGleb Smirnoff opts = 0; 10613b3a8eb9SGleb Smirnoff } 10623b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SRCTRACK) { 10633b3a8eb9SGleb Smirnoff if (!opts) 10643b3a8eb9SGleb Smirnoff printf(", "); 10653b3a8eb9SGleb Smirnoff printf("source-track"); 10663b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RULESRCTRACK) 10673b3a8eb9SGleb Smirnoff printf(" rule"); 10683b3a8eb9SGleb Smirnoff else 10693b3a8eb9SGleb Smirnoff printf(" global"); 10703b3a8eb9SGleb Smirnoff opts = 0; 10713b3a8eb9SGleb Smirnoff } 10723b3a8eb9SGleb Smirnoff if (r->max_src_states) { 10733b3a8eb9SGleb Smirnoff if (!opts) 10743b3a8eb9SGleb Smirnoff printf(", "); 10753b3a8eb9SGleb Smirnoff printf("max-src-states %u", r->max_src_states); 10763b3a8eb9SGleb Smirnoff opts = 0; 10773b3a8eb9SGleb Smirnoff } 10783b3a8eb9SGleb Smirnoff if (r->max_src_conn) { 10793b3a8eb9SGleb Smirnoff if (!opts) 10803b3a8eb9SGleb Smirnoff printf(", "); 10813b3a8eb9SGleb Smirnoff printf("max-src-conn %u", r->max_src_conn); 10823b3a8eb9SGleb Smirnoff opts = 0; 10833b3a8eb9SGleb Smirnoff } 10843b3a8eb9SGleb Smirnoff if (r->max_src_conn_rate.limit) { 10853b3a8eb9SGleb Smirnoff if (!opts) 10863b3a8eb9SGleb Smirnoff printf(", "); 10873b3a8eb9SGleb Smirnoff printf("max-src-conn-rate %u/%u", 10883b3a8eb9SGleb Smirnoff r->max_src_conn_rate.limit, 10893b3a8eb9SGleb Smirnoff r->max_src_conn_rate.seconds); 10903b3a8eb9SGleb Smirnoff opts = 0; 10913b3a8eb9SGleb Smirnoff } 10923b3a8eb9SGleb Smirnoff if (r->max_src_nodes) { 10933b3a8eb9SGleb Smirnoff if (!opts) 10943b3a8eb9SGleb Smirnoff printf(", "); 10953b3a8eb9SGleb Smirnoff printf("max-src-nodes %u", r->max_src_nodes); 10963b3a8eb9SGleb Smirnoff opts = 0; 10973b3a8eb9SGleb Smirnoff } 10983b3a8eb9SGleb Smirnoff if (r->overload_tblname[0]) { 10993b3a8eb9SGleb Smirnoff if (!opts) 11003b3a8eb9SGleb Smirnoff printf(", "); 11013b3a8eb9SGleb Smirnoff printf("overload <%s>", r->overload_tblname); 11023b3a8eb9SGleb Smirnoff if (r->flush) 11033b3a8eb9SGleb Smirnoff printf(" flush"); 11043b3a8eb9SGleb Smirnoff if (r->flush & PF_FLUSH_GLOBAL) 11053b3a8eb9SGleb Smirnoff printf(" global"); 11063b3a8eb9SGleb Smirnoff } 11073b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_IFBOUND) { 11083b3a8eb9SGleb Smirnoff if (!opts) 11093b3a8eb9SGleb Smirnoff printf(", "); 11103b3a8eb9SGleb Smirnoff printf("if-bound"); 11113b3a8eb9SGleb Smirnoff opts = 0; 11123b3a8eb9SGleb Smirnoff } 11133b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY) { 11143b3a8eb9SGleb Smirnoff if (!opts) 11153b3a8eb9SGleb Smirnoff printf(", "); 11163b3a8eb9SGleb Smirnoff printf("sloppy"); 11173b3a8eb9SGleb Smirnoff opts = 0; 11183b3a8eb9SGleb Smirnoff } 11193b3a8eb9SGleb Smirnoff for (i = 0; i < PFTM_MAX; ++i) 11203b3a8eb9SGleb Smirnoff if (r->timeout[i]) { 11213b3a8eb9SGleb Smirnoff int j; 11223b3a8eb9SGleb Smirnoff 11233b3a8eb9SGleb Smirnoff if (!opts) 11243b3a8eb9SGleb Smirnoff printf(", "); 11253b3a8eb9SGleb Smirnoff opts = 0; 11263b3a8eb9SGleb Smirnoff for (j = 0; pf_timeouts[j].name != NULL; 11273b3a8eb9SGleb Smirnoff ++j) 11283b3a8eb9SGleb Smirnoff if (pf_timeouts[j].timeout == i) 11293b3a8eb9SGleb Smirnoff break; 11303b3a8eb9SGleb Smirnoff printf("%s %u", pf_timeouts[j].name == NULL ? 11313b3a8eb9SGleb Smirnoff "inv.timeout" : pf_timeouts[j].name, 11323b3a8eb9SGleb Smirnoff r->timeout[i]); 11333b3a8eb9SGleb Smirnoff } 11343b3a8eb9SGleb Smirnoff printf(")"); 11353b3a8eb9SGleb Smirnoff } 113639282ef3SKajetan Staszkiewicz if (r->allow_opts) 113739282ef3SKajetan Staszkiewicz printf(" allow-opts"); 11383b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_FRAGMENT) 11393b3a8eb9SGleb Smirnoff printf(" fragment"); 114039282ef3SKajetan Staszkiewicz if (r->action == PF_SCRUB) { 114139282ef3SKajetan Staszkiewicz /* Scrub flags for old-style scrub. */ 11423b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NODF) 11433b3a8eb9SGleb Smirnoff printf(" no-df"); 11443b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RANDOMID) 11453b3a8eb9SGleb Smirnoff printf(" random-id"); 11463b3a8eb9SGleb Smirnoff if (r->min_ttl) 11473b3a8eb9SGleb Smirnoff printf(" min-ttl %d", r->min_ttl); 11483b3a8eb9SGleb Smirnoff if (r->max_mss) 11493b3a8eb9SGleb Smirnoff printf(" max-mss %d", r->max_mss); 11503b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SET_TOS) 11513b3a8eb9SGleb Smirnoff printf(" set-tos 0x%2.2x", r->set_tos); 11523b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_REASSEMBLE_TCP) 11533b3a8eb9SGleb Smirnoff printf(" reassemble tcp"); 115439282ef3SKajetan Staszkiewicz /* The PFRULE_FRAGMENT_NOREASS is set on all rules by default! */ 115557e047e5SKristof Provost printf(" fragment %sreassemble", 115657e047e5SKristof Provost r->rule_flag & PFRULE_FRAGMENT_NOREASS ? "no " : ""); 115739282ef3SKajetan Staszkiewicz } else if (r->scrub_flags & PFSTATE_SCRUBMASK || r->min_ttl || r->max_mss) { 115839282ef3SKajetan Staszkiewicz /* Scrub actions on normal rules. */ 115939282ef3SKajetan Staszkiewicz printf(" scrub("); 116039282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_NODF) 116139282ef3SKajetan Staszkiewicz printf(" no-df"); 116239282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_RANDOMID) 116339282ef3SKajetan Staszkiewicz printf(" random-id"); 116439282ef3SKajetan Staszkiewicz if (r->min_ttl) 116539282ef3SKajetan Staszkiewicz printf(" min-ttl %d", r->min_ttl); 116639282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_SETTOS) 116739282ef3SKajetan Staszkiewicz printf(" set-tos 0x%2.2x", r->set_tos); 116839282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_SCRUB_TCP) 116939282ef3SKajetan Staszkiewicz printf(" reassemble tcp"); 117039282ef3SKajetan Staszkiewicz if (r->max_mss) 117139282ef3SKajetan Staszkiewicz printf(" max-mss %d", r->max_mss); 117239282ef3SKajetan Staszkiewicz printf(")"); 11733b3a8eb9SGleb Smirnoff } 11746fcc8e04SKristof Provost i = 0; 11756fcc8e04SKristof Provost while (r->label[i][0]) 11766fcc8e04SKristof Provost printf(" label \"%s\"", r->label[i++]); 117776c5eeccSKristof Provost if (r->ridentifier) 117876c5eeccSKristof Provost printf(" ridentifier %u", r->ridentifier); 117963b3c1c7SKristof Provost /* Only dnrpipe as we might do (0, 42) to only queue return traffic. */ 118063b3c1c7SKristof Provost if (r->dnrpipe) 118163b3c1c7SKristof Provost printf(" %s(%d, %d)", 118263b3c1c7SKristof Provost r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", 118363b3c1c7SKristof Provost r->dnpipe, r->dnrpipe); 118463b3c1c7SKristof Provost else if (r->dnpipe) 118563b3c1c7SKristof Provost printf(" %s %d", 118663b3c1c7SKristof Provost r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", 118763b3c1c7SKristof Provost r->dnpipe); 11883b3a8eb9SGleb Smirnoff if (r->qname[0] && r->pqname[0]) 11893b3a8eb9SGleb Smirnoff printf(" queue(%s, %s)", r->qname, r->pqname); 11903b3a8eb9SGleb Smirnoff else if (r->qname[0]) 11913b3a8eb9SGleb Smirnoff printf(" queue %s", r->qname); 11923b3a8eb9SGleb Smirnoff if (r->tagname[0]) 11933b3a8eb9SGleb Smirnoff printf(" tag %s", r->tagname); 11943b3a8eb9SGleb Smirnoff if (r->match_tagname[0]) { 11953b3a8eb9SGleb Smirnoff if (r->match_tag_not) 11963b3a8eb9SGleb Smirnoff printf(" !"); 11973b3a8eb9SGleb Smirnoff printf(" tagged %s", r->match_tagname); 11983b3a8eb9SGleb Smirnoff } 11993b3a8eb9SGleb Smirnoff if (r->rtableid != -1) 12003b3a8eb9SGleb Smirnoff printf(" rtable %u", r->rtableid); 12013b3a8eb9SGleb Smirnoff if (r->divert.port) { 12023b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 12033b3a8eb9SGleb Smirnoff printf(" divert-to %u", ntohs(r->divert.port)); 12043b3a8eb9SGleb Smirnoff #else 12053b3a8eb9SGleb Smirnoff if (PF_AZERO(&r->divert.addr, r->af)) { 12063b3a8eb9SGleb Smirnoff printf(" divert-reply"); 12073b3a8eb9SGleb Smirnoff } else { 12083b3a8eb9SGleb Smirnoff /* XXX cut&paste from print_addr */ 12093b3a8eb9SGleb Smirnoff char buf[48]; 12103b3a8eb9SGleb Smirnoff 12113b3a8eb9SGleb Smirnoff printf(" divert-to "); 12123b3a8eb9SGleb Smirnoff if (inet_ntop(r->af, &r->divert.addr, buf, 12133b3a8eb9SGleb Smirnoff sizeof(buf)) == NULL) 12143b3a8eb9SGleb Smirnoff printf("?"); 12153b3a8eb9SGleb Smirnoff else 12163b3a8eb9SGleb Smirnoff printf("%s", buf); 12173b3a8eb9SGleb Smirnoff printf(" port %u", ntohs(r->divert.port)); 12183b3a8eb9SGleb Smirnoff } 12193b3a8eb9SGleb Smirnoff #endif 12203b3a8eb9SGleb Smirnoff } 12213b3a8eb9SGleb Smirnoff if (!anchor_call[0] && (r->action == PF_NAT || 12223b3a8eb9SGleb Smirnoff r->action == PF_BINAT || r->action == PF_RDR)) { 12233b3a8eb9SGleb Smirnoff printf(" -> "); 12243b3a8eb9SGleb Smirnoff print_pool(&r->rpool, r->rpool.proxy_port[0], 12253b3a8eb9SGleb Smirnoff r->rpool.proxy_port[1], r->af, r->action); 12263b3a8eb9SGleb Smirnoff } 12273b3a8eb9SGleb Smirnoff } 12283b3a8eb9SGleb Smirnoff 12293b3a8eb9SGleb Smirnoff void 12303b3a8eb9SGleb Smirnoff print_tabledef(const char *name, int flags, int addrs, 12313b3a8eb9SGleb Smirnoff struct node_tinithead *nodes) 12323b3a8eb9SGleb Smirnoff { 12333b3a8eb9SGleb Smirnoff struct node_tinit *ti, *nti; 12343b3a8eb9SGleb Smirnoff struct node_host *h; 12353b3a8eb9SGleb Smirnoff 12363b3a8eb9SGleb Smirnoff printf("table <%s>", name); 12373b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_CONST) 12383b3a8eb9SGleb Smirnoff printf(" const"); 12393b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_PERSIST) 12403b3a8eb9SGleb Smirnoff printf(" persist"); 12413b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_COUNTERS) 12423b3a8eb9SGleb Smirnoff printf(" counters"); 12433b3a8eb9SGleb Smirnoff SIMPLEQ_FOREACH(ti, nodes, entries) { 12443b3a8eb9SGleb Smirnoff if (ti->file) { 12453b3a8eb9SGleb Smirnoff printf(" file \"%s\"", ti->file); 12463b3a8eb9SGleb Smirnoff continue; 12473b3a8eb9SGleb Smirnoff } 12483b3a8eb9SGleb Smirnoff printf(" {"); 12493b3a8eb9SGleb Smirnoff for (;;) { 12503b3a8eb9SGleb Smirnoff for (h = ti->host; h != NULL; h = h->next) { 12513b3a8eb9SGleb Smirnoff printf(h->not ? " !" : " "); 12523b3a8eb9SGleb Smirnoff print_addr(&h->addr, h->af, 0); 12533b3a8eb9SGleb Smirnoff } 12543b3a8eb9SGleb Smirnoff nti = SIMPLEQ_NEXT(ti, entries); 12553b3a8eb9SGleb Smirnoff if (nti != NULL && nti->file == NULL) 12563b3a8eb9SGleb Smirnoff ti = nti; /* merge lists */ 12573b3a8eb9SGleb Smirnoff else 12583b3a8eb9SGleb Smirnoff break; 12593b3a8eb9SGleb Smirnoff } 12603b3a8eb9SGleb Smirnoff printf(" }"); 12613b3a8eb9SGleb Smirnoff } 12623b3a8eb9SGleb Smirnoff if (addrs && SIMPLEQ_EMPTY(nodes)) 12633b3a8eb9SGleb Smirnoff printf(" { }"); 12643b3a8eb9SGleb Smirnoff printf("\n"); 12653b3a8eb9SGleb Smirnoff } 12663b3a8eb9SGleb Smirnoff 12673b3a8eb9SGleb Smirnoff int 12683b3a8eb9SGleb Smirnoff parse_flags(char *s) 12693b3a8eb9SGleb Smirnoff { 12703b3a8eb9SGleb Smirnoff char *p, *q; 12713b3a8eb9SGleb Smirnoff u_int8_t f = 0; 12723b3a8eb9SGleb Smirnoff 12733b3a8eb9SGleb Smirnoff for (p = s; *p; p++) { 12743b3a8eb9SGleb Smirnoff if ((q = strchr(tcpflags, *p)) == NULL) 12753b3a8eb9SGleb Smirnoff return -1; 12763b3a8eb9SGleb Smirnoff else 12773b3a8eb9SGleb Smirnoff f |= 1 << (q - tcpflags); 12783b3a8eb9SGleb Smirnoff } 12793b3a8eb9SGleb Smirnoff return (f ? f : PF_TH_ALL); 12803b3a8eb9SGleb Smirnoff } 12813b3a8eb9SGleb Smirnoff 12823b3a8eb9SGleb Smirnoff void 12833b3a8eb9SGleb Smirnoff set_ipmask(struct node_host *h, u_int8_t b) 12843b3a8eb9SGleb Smirnoff { 12853b3a8eb9SGleb Smirnoff struct pf_addr *m, *n; 12863b3a8eb9SGleb Smirnoff int i, j = 0; 12873b3a8eb9SGleb Smirnoff 12883b3a8eb9SGleb Smirnoff m = &h->addr.v.a.mask; 12893b3a8eb9SGleb Smirnoff memset(m, 0, sizeof(*m)); 12903b3a8eb9SGleb Smirnoff 12913b3a8eb9SGleb Smirnoff while (b >= 32) { 12923b3a8eb9SGleb Smirnoff m->addr32[j++] = 0xffffffff; 12933b3a8eb9SGleb Smirnoff b -= 32; 12943b3a8eb9SGleb Smirnoff } 12953b3a8eb9SGleb Smirnoff for (i = 31; i > 31-b; --i) 12963b3a8eb9SGleb Smirnoff m->addr32[j] |= (1 << i); 12973b3a8eb9SGleb Smirnoff if (b) 12983b3a8eb9SGleb Smirnoff m->addr32[j] = htonl(m->addr32[j]); 12993b3a8eb9SGleb Smirnoff 13003b3a8eb9SGleb Smirnoff /* Mask off bits of the address that will never be used. */ 13013b3a8eb9SGleb Smirnoff n = &h->addr.v.a.addr; 13023b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_ADDRMASK) 13033b3a8eb9SGleb Smirnoff for (i = 0; i < 4; i++) 13043b3a8eb9SGleb Smirnoff n->addr32[i] = n->addr32[i] & m->addr32[i]; 13053b3a8eb9SGleb Smirnoff } 13063b3a8eb9SGleb Smirnoff 13073b3a8eb9SGleb Smirnoff int 13083b3a8eb9SGleb Smirnoff check_netmask(struct node_host *h, sa_family_t af) 13093b3a8eb9SGleb Smirnoff { 13103b3a8eb9SGleb Smirnoff struct node_host *n = NULL; 13113b3a8eb9SGleb Smirnoff struct pf_addr *m; 13123b3a8eb9SGleb Smirnoff 13133b3a8eb9SGleb Smirnoff for (n = h; n != NULL; n = n->next) { 13143b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_TABLE) 13153b3a8eb9SGleb Smirnoff continue; 13163b3a8eb9SGleb Smirnoff m = &h->addr.v.a.mask; 13173b3a8eb9SGleb Smirnoff /* fix up netmask for dynaddr */ 13183b3a8eb9SGleb Smirnoff if (af == AF_INET && h->addr.type == PF_ADDR_DYNIFTL && 13193b3a8eb9SGleb Smirnoff unmask(m, AF_INET6) > 32) 13203b3a8eb9SGleb Smirnoff set_ipmask(n, 32); 13213b3a8eb9SGleb Smirnoff /* netmasks > 32 bit are invalid on v4 */ 13223b3a8eb9SGleb Smirnoff if (af == AF_INET && 13233b3a8eb9SGleb Smirnoff (m->addr32[1] || m->addr32[2] || m->addr32[3])) { 13243b3a8eb9SGleb Smirnoff fprintf(stderr, "netmask %u invalid for IPv4 address\n", 13253b3a8eb9SGleb Smirnoff unmask(m, AF_INET6)); 13263b3a8eb9SGleb Smirnoff return (1); 13273b3a8eb9SGleb Smirnoff } 13283b3a8eb9SGleb Smirnoff } 13293b3a8eb9SGleb Smirnoff return (0); 13303b3a8eb9SGleb Smirnoff } 13313b3a8eb9SGleb Smirnoff 13323b3a8eb9SGleb Smirnoff /* interface lookup routines */ 13333b3a8eb9SGleb Smirnoff 133413cfafabSKristof Provost static struct node_host *iftab; 13353b3a8eb9SGleb Smirnoff 13361d34c9daSPatrick Kelsey /* 13371d34c9daSPatrick Kelsey * Retrieve the list of groups this interface is a member of and make sure 13381d34c9daSPatrick Kelsey * each group is in the group map. 13391d34c9daSPatrick Kelsey */ 13401d34c9daSPatrick Kelsey static void 13411d34c9daSPatrick Kelsey ifa_add_groups_to_map(char *ifa_name) 13421d34c9daSPatrick Kelsey { 13431d34c9daSPatrick Kelsey int s, len; 13441d34c9daSPatrick Kelsey struct ifgroupreq ifgr; 13451d34c9daSPatrick Kelsey struct ifg_req *ifg; 13461d34c9daSPatrick Kelsey 13471d34c9daSPatrick Kelsey s = get_query_socket(); 13481d34c9daSPatrick Kelsey 13491d34c9daSPatrick Kelsey /* Get size of group list for this interface */ 13501d34c9daSPatrick Kelsey memset(&ifgr, 0, sizeof(ifgr)); 13511d34c9daSPatrick Kelsey strlcpy(ifgr.ifgr_name, ifa_name, IFNAMSIZ); 13521d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 13531d34c9daSPatrick Kelsey err(1, "SIOCGIFGROUP"); 13541d34c9daSPatrick Kelsey 13551d34c9daSPatrick Kelsey /* Retrieve group list for this interface */ 13561d34c9daSPatrick Kelsey len = ifgr.ifgr_len; 13571d34c9daSPatrick Kelsey ifgr.ifgr_groups = 13581d34c9daSPatrick Kelsey (struct ifg_req *)calloc(len / sizeof(struct ifg_req), 13591d34c9daSPatrick Kelsey sizeof(struct ifg_req)); 13601d34c9daSPatrick Kelsey if (ifgr.ifgr_groups == NULL) 13611d34c9daSPatrick Kelsey err(1, "calloc"); 13621d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 13631d34c9daSPatrick Kelsey err(1, "SIOCGIFGROUP"); 13641d34c9daSPatrick Kelsey 13651d34c9daSPatrick Kelsey ifg = ifgr.ifgr_groups; 13661d34c9daSPatrick Kelsey for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 13671d34c9daSPatrick Kelsey len -= sizeof(struct ifg_req); 13681d34c9daSPatrick Kelsey if (strcmp(ifg->ifgrq_group, "all")) { 13691d34c9daSPatrick Kelsey ENTRY item; 13701d34c9daSPatrick Kelsey ENTRY *ret_item; 13711d34c9daSPatrick Kelsey int *answer; 13721d34c9daSPatrick Kelsey 13731d34c9daSPatrick Kelsey item.key = ifg->ifgrq_group; 13741d34c9daSPatrick Kelsey if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) { 13751d34c9daSPatrick Kelsey struct ifgroupreq ifgr2; 13761d34c9daSPatrick Kelsey 13771d34c9daSPatrick Kelsey /* Don't know the answer yet */ 13781d34c9daSPatrick Kelsey if ((answer = malloc(sizeof(int))) == NULL) 13791d34c9daSPatrick Kelsey err(1, "malloc"); 13801d34c9daSPatrick Kelsey 13811d34c9daSPatrick Kelsey bzero(&ifgr2, sizeof(ifgr2)); 13821d34c9daSPatrick Kelsey strlcpy(ifgr2.ifgr_name, ifg->ifgrq_group, 13831d34c9daSPatrick Kelsey sizeof(ifgr2.ifgr_name)); 13841d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr2) == 0) 13851d34c9daSPatrick Kelsey *answer = ifgr2.ifgr_len; 13861d34c9daSPatrick Kelsey else 13871d34c9daSPatrick Kelsey *answer = 0; 13881d34c9daSPatrick Kelsey 13891d34c9daSPatrick Kelsey item.key = strdup(ifg->ifgrq_group); 13901d34c9daSPatrick Kelsey item.data = answer; 13911d34c9daSPatrick Kelsey if (hsearch_r(item, ENTER, &ret_item, 13921d34c9daSPatrick Kelsey &isgroup_map) == 0) 13931d34c9daSPatrick Kelsey err(1, "interface group query response" 13941d34c9daSPatrick Kelsey " map insert"); 13951d34c9daSPatrick Kelsey } 13961d34c9daSPatrick Kelsey } 13971d34c9daSPatrick Kelsey } 13981d34c9daSPatrick Kelsey free(ifgr.ifgr_groups); 13991d34c9daSPatrick Kelsey } 14001d34c9daSPatrick Kelsey 14013b3a8eb9SGleb Smirnoff void 14023b3a8eb9SGleb Smirnoff ifa_load(void) 14033b3a8eb9SGleb Smirnoff { 14043b3a8eb9SGleb Smirnoff struct ifaddrs *ifap, *ifa; 14053b3a8eb9SGleb Smirnoff struct node_host *n = NULL, *h = NULL; 14063b3a8eb9SGleb Smirnoff 14073b3a8eb9SGleb Smirnoff if (getifaddrs(&ifap) < 0) 14083b3a8eb9SGleb Smirnoff err(1, "getifaddrs"); 14093b3a8eb9SGleb Smirnoff 14103b3a8eb9SGleb Smirnoff for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 14113b3a8eb9SGleb Smirnoff if (!(ifa->ifa_addr->sa_family == AF_INET || 14123b3a8eb9SGleb Smirnoff ifa->ifa_addr->sa_family == AF_INET6 || 14133b3a8eb9SGleb Smirnoff ifa->ifa_addr->sa_family == AF_LINK)) 14143b3a8eb9SGleb Smirnoff continue; 14153b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 14163b3a8eb9SGleb Smirnoff if (n == NULL) 14173b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 14183b3a8eb9SGleb Smirnoff n->af = ifa->ifa_addr->sa_family; 14193b3a8eb9SGleb Smirnoff n->ifa_flags = ifa->ifa_flags; 14203b3a8eb9SGleb Smirnoff #ifdef __KAME__ 14213b3a8eb9SGleb Smirnoff if (n->af == AF_INET6 && 14223b3a8eb9SGleb Smirnoff IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) 14233b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_addr) && 14243b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 14253b3a8eb9SGleb Smirnoff 0) { 14263b3a8eb9SGleb Smirnoff struct sockaddr_in6 *sin6; 14273b3a8eb9SGleb Smirnoff 14283b3a8eb9SGleb Smirnoff sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 14293b3a8eb9SGleb Smirnoff sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | 14303b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[3]; 14313b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[2] = 0; 14323b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[3] = 0; 14333b3a8eb9SGleb Smirnoff } 14343b3a8eb9SGleb Smirnoff #endif 14353b3a8eb9SGleb Smirnoff n->ifindex = 0; 14363b3a8eb9SGleb Smirnoff if (n->af == AF_INET) { 14373b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) 14383b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin_addr.s_addr, 14393b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 14403b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) 14413b3a8eb9SGleb Smirnoff ifa->ifa_netmask)->sin_addr.s_addr, 14423b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 14433b3a8eb9SGleb Smirnoff if (ifa->ifa_broadaddr != NULL) 14443b3a8eb9SGleb Smirnoff memcpy(&n->bcast, &((struct sockaddr_in *) 14453b3a8eb9SGleb Smirnoff ifa->ifa_broadaddr)->sin_addr.s_addr, 14463b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 14473b3a8eb9SGleb Smirnoff if (ifa->ifa_dstaddr != NULL) 14483b3a8eb9SGleb Smirnoff memcpy(&n->peer, &((struct sockaddr_in *) 14493b3a8eb9SGleb Smirnoff ifa->ifa_dstaddr)->sin_addr.s_addr, 14503b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 14513b3a8eb9SGleb Smirnoff } else if (n->af == AF_INET6) { 14523b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) 14533b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_addr.s6_addr, 14543b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 14553b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) 14563b3a8eb9SGleb Smirnoff ifa->ifa_netmask)->sin6_addr.s6_addr, 14573b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 14583b3a8eb9SGleb Smirnoff if (ifa->ifa_broadaddr != NULL) 14593b3a8eb9SGleb Smirnoff memcpy(&n->bcast, &((struct sockaddr_in6 *) 14603b3a8eb9SGleb Smirnoff ifa->ifa_broadaddr)->sin6_addr.s6_addr, 14613b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 14623b3a8eb9SGleb Smirnoff if (ifa->ifa_dstaddr != NULL) 14633b3a8eb9SGleb Smirnoff memcpy(&n->peer, &((struct sockaddr_in6 *) 14643b3a8eb9SGleb Smirnoff ifa->ifa_dstaddr)->sin6_addr.s6_addr, 14653b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 14663b3a8eb9SGleb Smirnoff n->ifindex = ((struct sockaddr_in6 *) 14673b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_scope_id; 14681d34c9daSPatrick Kelsey } else if (n->af == AF_LINK) { 14691d34c9daSPatrick Kelsey ifa_add_groups_to_map(ifa->ifa_name); 14703b3a8eb9SGleb Smirnoff } 14713b3a8eb9SGleb Smirnoff if ((n->ifname = strdup(ifa->ifa_name)) == NULL) 14723b3a8eb9SGleb Smirnoff err(1, "ifa_load: strdup"); 14733b3a8eb9SGleb Smirnoff n->next = NULL; 14743b3a8eb9SGleb Smirnoff n->tail = n; 14753b3a8eb9SGleb Smirnoff if (h == NULL) 14763b3a8eb9SGleb Smirnoff h = n; 14773b3a8eb9SGleb Smirnoff else { 14783b3a8eb9SGleb Smirnoff h->tail->next = n; 14793b3a8eb9SGleb Smirnoff h->tail = n; 14803b3a8eb9SGleb Smirnoff } 14813b3a8eb9SGleb Smirnoff } 14823b3a8eb9SGleb Smirnoff 14833b3a8eb9SGleb Smirnoff iftab = h; 14843b3a8eb9SGleb Smirnoff freeifaddrs(ifap); 14853b3a8eb9SGleb Smirnoff } 14863b3a8eb9SGleb Smirnoff 14871d34c9daSPatrick Kelsey static int 1488f870cb7fSBjoern A. Zeeb get_socket_domain(void) 1489f870cb7fSBjoern A. Zeeb { 1490f870cb7fSBjoern A. Zeeb int sdom; 1491f870cb7fSBjoern A. Zeeb 1492f870cb7fSBjoern A. Zeeb sdom = AF_UNSPEC; 1493f870cb7fSBjoern A. Zeeb #ifdef WITH_INET6 1494f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC && feature_present("inet6")) 1495f870cb7fSBjoern A. Zeeb sdom = AF_INET6; 1496f870cb7fSBjoern A. Zeeb #endif 1497f870cb7fSBjoern A. Zeeb #ifdef WITH_INET 1498f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC && feature_present("inet")) 1499f870cb7fSBjoern A. Zeeb sdom = AF_INET; 1500f870cb7fSBjoern A. Zeeb #endif 1501f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC) 1502f870cb7fSBjoern A. Zeeb sdom = AF_LINK; 1503f870cb7fSBjoern A. Zeeb 1504f870cb7fSBjoern A. Zeeb return (sdom); 1505f870cb7fSBjoern A. Zeeb } 1506f870cb7fSBjoern A. Zeeb 15071d34c9daSPatrick Kelsey int 15081d34c9daSPatrick Kelsey get_query_socket(void) 15091d34c9daSPatrick Kelsey { 15101d34c9daSPatrick Kelsey static int s = -1; 15111d34c9daSPatrick Kelsey 15121d34c9daSPatrick Kelsey if (s == -1) { 15131d34c9daSPatrick Kelsey if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) 15141d34c9daSPatrick Kelsey err(1, "socket"); 15151d34c9daSPatrick Kelsey } 15161d34c9daSPatrick Kelsey 15171d34c9daSPatrick Kelsey return (s); 15181d34c9daSPatrick Kelsey } 15191d34c9daSPatrick Kelsey 15201d34c9daSPatrick Kelsey /* 15211d34c9daSPatrick Kelsey * Returns the response len if the name is a group, otherwise returns 0. 15221d34c9daSPatrick Kelsey */ 15231d34c9daSPatrick Kelsey static int 15241d34c9daSPatrick Kelsey is_a_group(char *name) 15251d34c9daSPatrick Kelsey { 15261d34c9daSPatrick Kelsey ENTRY item; 15271d34c9daSPatrick Kelsey ENTRY *ret_item; 15281d34c9daSPatrick Kelsey 15291d34c9daSPatrick Kelsey item.key = name; 15301d34c9daSPatrick Kelsey if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) 15311d34c9daSPatrick Kelsey return (0); 15321d34c9daSPatrick Kelsey 15331d34c9daSPatrick Kelsey return (*(int *)ret_item->data); 15341d34c9daSPatrick Kelsey } 15351d34c9daSPatrick Kelsey 15363b3a8eb9SGleb Smirnoff struct node_host * 15371d34c9daSPatrick Kelsey ifa_exists(char *ifa_name) 15383b3a8eb9SGleb Smirnoff { 15393b3a8eb9SGleb Smirnoff struct node_host *n; 15403b3a8eb9SGleb Smirnoff 15413b3a8eb9SGleb Smirnoff if (iftab == NULL) 15423b3a8eb9SGleb Smirnoff ifa_load(); 15433b3a8eb9SGleb Smirnoff 15441d34c9daSPatrick Kelsey /* check whether this is a group */ 15451d34c9daSPatrick Kelsey if (is_a_group(ifa_name)) { 15463b3a8eb9SGleb Smirnoff /* fake a node_host */ 15473b3a8eb9SGleb Smirnoff if ((n = calloc(1, sizeof(*n))) == NULL) 15483b3a8eb9SGleb Smirnoff err(1, "calloc"); 15493b3a8eb9SGleb Smirnoff if ((n->ifname = strdup(ifa_name)) == NULL) 15503b3a8eb9SGleb Smirnoff err(1, "strdup"); 15513b3a8eb9SGleb Smirnoff return (n); 15523b3a8eb9SGleb Smirnoff } 15533b3a8eb9SGleb Smirnoff 15543b3a8eb9SGleb Smirnoff for (n = iftab; n; n = n->next) { 15553b3a8eb9SGleb Smirnoff if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) 15563b3a8eb9SGleb Smirnoff return (n); 15573b3a8eb9SGleb Smirnoff } 15583b3a8eb9SGleb Smirnoff 15593b3a8eb9SGleb Smirnoff return (NULL); 15603b3a8eb9SGleb Smirnoff } 15613b3a8eb9SGleb Smirnoff 15623b3a8eb9SGleb Smirnoff struct node_host * 15631d34c9daSPatrick Kelsey ifa_grouplookup(char *ifa_name, int flags) 15643b3a8eb9SGleb Smirnoff { 15653b3a8eb9SGleb Smirnoff struct ifg_req *ifg; 15663b3a8eb9SGleb Smirnoff struct ifgroupreq ifgr; 15673b3a8eb9SGleb Smirnoff int s, len; 15683b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 15693b3a8eb9SGleb Smirnoff 15701d34c9daSPatrick Kelsey s = get_query_socket(); 15711d34c9daSPatrick Kelsey len = is_a_group(ifa_name); 15721d34c9daSPatrick Kelsey if (len == 0) 15731d34c9daSPatrick Kelsey return (NULL); 15743b3a8eb9SGleb Smirnoff bzero(&ifgr, sizeof(ifgr)); 15753b3a8eb9SGleb Smirnoff strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); 15764c8fb952SKristof Provost ifgr.ifgr_len = len; 15773b3a8eb9SGleb Smirnoff if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 15783b3a8eb9SGleb Smirnoff err(1, "calloc"); 15793b3a8eb9SGleb Smirnoff if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 15803b3a8eb9SGleb Smirnoff err(1, "SIOCGIFGMEMB"); 15813b3a8eb9SGleb Smirnoff 15823b3a8eb9SGleb Smirnoff for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req); 15833b3a8eb9SGleb Smirnoff ifg++) { 15843b3a8eb9SGleb Smirnoff len -= sizeof(struct ifg_req); 1585d5b08e13SKristof Provost if ((n = ifa_lookup(ifg->ifgrq_member, flags)) == NULL) 15863b3a8eb9SGleb Smirnoff continue; 15873b3a8eb9SGleb Smirnoff if (h == NULL) 15883b3a8eb9SGleb Smirnoff h = n; 15893b3a8eb9SGleb Smirnoff else { 15903b3a8eb9SGleb Smirnoff h->tail->next = n; 15913b3a8eb9SGleb Smirnoff h->tail = n->tail; 15923b3a8eb9SGleb Smirnoff } 15933b3a8eb9SGleb Smirnoff } 15943b3a8eb9SGleb Smirnoff free(ifgr.ifgr_groups); 15953b3a8eb9SGleb Smirnoff 15963b3a8eb9SGleb Smirnoff return (h); 15973b3a8eb9SGleb Smirnoff } 15983b3a8eb9SGleb Smirnoff 15993b3a8eb9SGleb Smirnoff struct node_host * 16001d34c9daSPatrick Kelsey ifa_lookup(char *ifa_name, int flags) 16013b3a8eb9SGleb Smirnoff { 16023b3a8eb9SGleb Smirnoff struct node_host *p = NULL, *h = NULL, *n = NULL; 16033b3a8eb9SGleb Smirnoff int got4 = 0, got6 = 0; 16043b3a8eb9SGleb Smirnoff const char *last_if = NULL; 16053b3a8eb9SGleb Smirnoff 16068fd675d8SKristof Provost /* first load iftab and isgroup_map */ 16078fd675d8SKristof Provost if (iftab == NULL) 16088fd675d8SKristof Provost ifa_load(); 16098fd675d8SKristof Provost 16103b3a8eb9SGleb Smirnoff if ((h = ifa_grouplookup(ifa_name, flags)) != NULL) 16113b3a8eb9SGleb Smirnoff return (h); 16123b3a8eb9SGleb Smirnoff 16133b3a8eb9SGleb Smirnoff if (!strncmp(ifa_name, "self", IFNAMSIZ)) 16143b3a8eb9SGleb Smirnoff ifa_name = NULL; 16153b3a8eb9SGleb Smirnoff 16163b3a8eb9SGleb Smirnoff for (p = iftab; p; p = p->next) { 16173b3a8eb9SGleb Smirnoff if (ifa_skip_if(ifa_name, p)) 16183b3a8eb9SGleb Smirnoff continue; 16193b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET) 16203b3a8eb9SGleb Smirnoff continue; 16213b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_BROADCAST) && 16223b3a8eb9SGleb Smirnoff !(p->ifa_flags & IFF_BROADCAST)) 16233b3a8eb9SGleb Smirnoff continue; 16243b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_PEER) && 16253b3a8eb9SGleb Smirnoff !(p->ifa_flags & IFF_POINTOPOINT)) 16263b3a8eb9SGleb Smirnoff continue; 16273b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NETWORK) && p->ifindex > 0) 16283b3a8eb9SGleb Smirnoff continue; 16293b3a8eb9SGleb Smirnoff if (last_if == NULL || strcmp(last_if, p->ifname)) 16303b3a8eb9SGleb Smirnoff got4 = got6 = 0; 16313b3a8eb9SGleb Smirnoff last_if = p->ifname; 16323b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET && got4) 16333b3a8eb9SGleb Smirnoff continue; 163499eb0055SKristof Provost if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && 163599eb0055SKristof Provost IN6_IS_ADDR_LINKLOCAL(&p->addr.v.a.addr.v6)) 163699eb0055SKristof Provost continue; 16373b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && got6) 16383b3a8eb9SGleb Smirnoff continue; 16393b3a8eb9SGleb Smirnoff if (p->af == AF_INET) 16403b3a8eb9SGleb Smirnoff got4 = 1; 16413b3a8eb9SGleb Smirnoff else 16423b3a8eb9SGleb Smirnoff got6 = 1; 16433b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 16443b3a8eb9SGleb Smirnoff if (n == NULL) 16453b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 16463b3a8eb9SGleb Smirnoff n->af = p->af; 16473b3a8eb9SGleb Smirnoff if (flags & PFI_AFLAG_BROADCAST) 16483b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->bcast, 16493b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 16503b3a8eb9SGleb Smirnoff else if (flags & PFI_AFLAG_PEER) 16513b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->peer, 16523b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 16533b3a8eb9SGleb Smirnoff else 16543b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, 16553b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 16563b3a8eb9SGleb Smirnoff if (flags & PFI_AFLAG_NETWORK) 16573b3a8eb9SGleb Smirnoff set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); 16583b3a8eb9SGleb Smirnoff else { 16593b3a8eb9SGleb Smirnoff if (n->af == AF_INET) { 16603b3a8eb9SGleb Smirnoff if (p->ifa_flags & IFF_LOOPBACK && 16613b3a8eb9SGleb Smirnoff p->ifa_flags & IFF_LINK1) 16623b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, 16633b3a8eb9SGleb Smirnoff &p->addr.v.a.mask, 16643b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 16653b3a8eb9SGleb Smirnoff else 16663b3a8eb9SGleb Smirnoff set_ipmask(n, 32); 16673b3a8eb9SGleb Smirnoff } else 16683b3a8eb9SGleb Smirnoff set_ipmask(n, 128); 16693b3a8eb9SGleb Smirnoff } 16703b3a8eb9SGleb Smirnoff n->ifindex = p->ifindex; 16710f9e47a9SKristof Provost n->ifname = strdup(p->ifname); 16723b3a8eb9SGleb Smirnoff 16733b3a8eb9SGleb Smirnoff n->next = NULL; 16743b3a8eb9SGleb Smirnoff n->tail = n; 16753b3a8eb9SGleb Smirnoff if (h == NULL) 16763b3a8eb9SGleb Smirnoff h = n; 16773b3a8eb9SGleb Smirnoff else { 16783b3a8eb9SGleb Smirnoff h->tail->next = n; 16793b3a8eb9SGleb Smirnoff h->tail = n; 16803b3a8eb9SGleb Smirnoff } 16813b3a8eb9SGleb Smirnoff } 16823b3a8eb9SGleb Smirnoff return (h); 16833b3a8eb9SGleb Smirnoff } 16843b3a8eb9SGleb Smirnoff 16853b3a8eb9SGleb Smirnoff int 16863b3a8eb9SGleb Smirnoff ifa_skip_if(const char *filter, struct node_host *p) 16873b3a8eb9SGleb Smirnoff { 16883b3a8eb9SGleb Smirnoff int n; 16893b3a8eb9SGleb Smirnoff 16903b3a8eb9SGleb Smirnoff if (p->af != AF_INET && p->af != AF_INET6) 16913b3a8eb9SGleb Smirnoff return (1); 16923b3a8eb9SGleb Smirnoff if (filter == NULL || !*filter) 16933b3a8eb9SGleb Smirnoff return (0); 16943b3a8eb9SGleb Smirnoff if (!strcmp(p->ifname, filter)) 16953b3a8eb9SGleb Smirnoff return (0); /* exact match */ 16963b3a8eb9SGleb Smirnoff n = strlen(filter); 16973b3a8eb9SGleb Smirnoff if (n < 1 || n >= IFNAMSIZ) 16983b3a8eb9SGleb Smirnoff return (1); /* sanity check */ 16993b3a8eb9SGleb Smirnoff if (filter[n-1] >= '0' && filter[n-1] <= '9') 17003b3a8eb9SGleb Smirnoff return (1); /* only do exact match in that case */ 17013b3a8eb9SGleb Smirnoff if (strncmp(p->ifname, filter, n)) 17023b3a8eb9SGleb Smirnoff return (1); /* prefix doesn't match */ 17033b3a8eb9SGleb Smirnoff return (p->ifname[n] < '0' || p->ifname[n] > '9'); 17043b3a8eb9SGleb Smirnoff } 17053b3a8eb9SGleb Smirnoff 17063b3a8eb9SGleb Smirnoff 17073b3a8eb9SGleb Smirnoff struct node_host * 17083b3a8eb9SGleb Smirnoff host(const char *s) 17093b3a8eb9SGleb Smirnoff { 17103b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 17113b3a8eb9SGleb Smirnoff int mask, v4mask, v6mask, cont = 1; 17123b3a8eb9SGleb Smirnoff char *p, *q, *ps; 17133b3a8eb9SGleb Smirnoff 17143b3a8eb9SGleb Smirnoff if ((p = strrchr(s, '/')) != NULL) { 17153b3a8eb9SGleb Smirnoff mask = strtol(p+1, &q, 0); 17163b3a8eb9SGleb Smirnoff if (!q || *q || mask > 128 || q == (p+1)) { 17173b3a8eb9SGleb Smirnoff fprintf(stderr, "invalid netmask '%s'\n", p); 17183b3a8eb9SGleb Smirnoff return (NULL); 17193b3a8eb9SGleb Smirnoff } 17203b3a8eb9SGleb Smirnoff if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 17213b3a8eb9SGleb Smirnoff err(1, "host: malloc"); 17223b3a8eb9SGleb Smirnoff strlcpy(ps, s, strlen(s) - strlen(p) + 1); 17233b3a8eb9SGleb Smirnoff v4mask = v6mask = mask; 17243b3a8eb9SGleb Smirnoff } else { 17253b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 17263b3a8eb9SGleb Smirnoff err(1, "host: strdup"); 17273b3a8eb9SGleb Smirnoff v4mask = 32; 17283b3a8eb9SGleb Smirnoff v6mask = 128; 17293b3a8eb9SGleb Smirnoff mask = -1; 17303b3a8eb9SGleb Smirnoff } 17313b3a8eb9SGleb Smirnoff 17323b3a8eb9SGleb Smirnoff /* IPv4 address? */ 17333b3a8eb9SGleb Smirnoff if (cont && (h = host_v4(s, mask)) != NULL) 17343b3a8eb9SGleb Smirnoff cont = 0; 17353b3a8eb9SGleb Smirnoff 17363b3a8eb9SGleb Smirnoff /* IPv6 address? */ 17373b3a8eb9SGleb Smirnoff if (cont && (h = host_v6(ps, v6mask)) != NULL) 17383b3a8eb9SGleb Smirnoff cont = 0; 17393b3a8eb9SGleb Smirnoff 1740d2568b02SKristof Provost /* interface with this name exists? */ 1741d2568b02SKristof Provost /* expensive with thousands of interfaces - prioritze IPv4/6 check */ 174228b64169SFranco Fichtner if (cont && (h = host_if(ps, mask, &cont)) != NULL) 1743d2568b02SKristof Provost cont = 0; 1744d2568b02SKristof Provost 17453b3a8eb9SGleb Smirnoff /* dns lookup */ 17463b3a8eb9SGleb Smirnoff if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL) 17473b3a8eb9SGleb Smirnoff cont = 0; 17483b3a8eb9SGleb Smirnoff free(ps); 17493b3a8eb9SGleb Smirnoff 17503b3a8eb9SGleb Smirnoff if (h == NULL || cont == 1) { 17513b3a8eb9SGleb Smirnoff fprintf(stderr, "no IP address found for %s\n", s); 17523b3a8eb9SGleb Smirnoff return (NULL); 17533b3a8eb9SGleb Smirnoff } 17543b3a8eb9SGleb Smirnoff return (h); 17553b3a8eb9SGleb Smirnoff } 17563b3a8eb9SGleb Smirnoff 17573b3a8eb9SGleb Smirnoff struct node_host * 175828b64169SFranco Fichtner host_if(const char *s, int mask, int *cont) 17593b3a8eb9SGleb Smirnoff { 17603b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 17613b3a8eb9SGleb Smirnoff char *p, *ps; 17623b3a8eb9SGleb Smirnoff int flags = 0; 17633b3a8eb9SGleb Smirnoff 17643b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 17653b3a8eb9SGleb Smirnoff err(1, "host_if: strdup"); 17663b3a8eb9SGleb Smirnoff while ((p = strrchr(ps, ':')) != NULL) { 17673b3a8eb9SGleb Smirnoff if (!strcmp(p+1, "network")) 17683b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NETWORK; 17693b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "broadcast")) 17703b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_BROADCAST; 17713b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "peer")) 17723b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_PEER; 17733b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "0")) 17743b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NOALIAS; 17753b3a8eb9SGleb Smirnoff else { 17763b3a8eb9SGleb Smirnoff free(ps); 17773b3a8eb9SGleb Smirnoff return (NULL); 17783b3a8eb9SGleb Smirnoff } 17793b3a8eb9SGleb Smirnoff *p = '\0'; 178028b64169SFranco Fichtner *cont = 0; 17813b3a8eb9SGleb Smirnoff } 17823b3a8eb9SGleb Smirnoff if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */ 17833b3a8eb9SGleb Smirnoff fprintf(stderr, "illegal combination of interface modifiers\n"); 17843b3a8eb9SGleb Smirnoff free(ps); 17853b3a8eb9SGleb Smirnoff return (NULL); 17863b3a8eb9SGleb Smirnoff } 17873b3a8eb9SGleb Smirnoff if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) { 17883b3a8eb9SGleb Smirnoff fprintf(stderr, "network or broadcast lookup, but " 17893b3a8eb9SGleb Smirnoff "extra netmask given\n"); 17903b3a8eb9SGleb Smirnoff free(ps); 17913b3a8eb9SGleb Smirnoff return (NULL); 17923b3a8eb9SGleb Smirnoff } 17933b3a8eb9SGleb Smirnoff if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) { 17943b3a8eb9SGleb Smirnoff /* interface with this name exists */ 17953b3a8eb9SGleb Smirnoff h = ifa_lookup(ps, flags); 17963b3a8eb9SGleb Smirnoff for (n = h; n != NULL && mask > -1; n = n->next) 17973b3a8eb9SGleb Smirnoff set_ipmask(n, mask); 17983b3a8eb9SGleb Smirnoff } 17993b3a8eb9SGleb Smirnoff 18003b3a8eb9SGleb Smirnoff free(ps); 18013b3a8eb9SGleb Smirnoff return (h); 18023b3a8eb9SGleb Smirnoff } 18033b3a8eb9SGleb Smirnoff 18043b3a8eb9SGleb Smirnoff struct node_host * 18053b3a8eb9SGleb Smirnoff host_v4(const char *s, int mask) 18063b3a8eb9SGleb Smirnoff { 18073b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 18083b3a8eb9SGleb Smirnoff struct in_addr ina; 18093b3a8eb9SGleb Smirnoff int bits = 32; 18103b3a8eb9SGleb Smirnoff 18113b3a8eb9SGleb Smirnoff memset(&ina, 0, sizeof(struct in_addr)); 18123b3a8eb9SGleb Smirnoff if (strrchr(s, '/') != NULL) { 18133b3a8eb9SGleb Smirnoff if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 18143b3a8eb9SGleb Smirnoff return (NULL); 18153b3a8eb9SGleb Smirnoff } else { 18163b3a8eb9SGleb Smirnoff if (inet_pton(AF_INET, s, &ina) != 1) 18173b3a8eb9SGleb Smirnoff return (NULL); 18183b3a8eb9SGleb Smirnoff } 18193b3a8eb9SGleb Smirnoff 18203b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(struct node_host)); 18213b3a8eb9SGleb Smirnoff if (h == NULL) 18223b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 18233b3a8eb9SGleb Smirnoff h->ifname = NULL; 18243b3a8eb9SGleb Smirnoff h->af = AF_INET; 18253b3a8eb9SGleb Smirnoff h->addr.v.a.addr.addr32[0] = ina.s_addr; 18263b3a8eb9SGleb Smirnoff set_ipmask(h, bits); 18273b3a8eb9SGleb Smirnoff h->next = NULL; 18283b3a8eb9SGleb Smirnoff h->tail = h; 18293b3a8eb9SGleb Smirnoff 18303b3a8eb9SGleb Smirnoff return (h); 18313b3a8eb9SGleb Smirnoff } 18323b3a8eb9SGleb Smirnoff 18333b3a8eb9SGleb Smirnoff struct node_host * 18343b3a8eb9SGleb Smirnoff host_v6(const char *s, int mask) 18353b3a8eb9SGleb Smirnoff { 18363b3a8eb9SGleb Smirnoff struct addrinfo hints, *res; 18373b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 18383b3a8eb9SGleb Smirnoff 18393b3a8eb9SGleb Smirnoff memset(&hints, 0, sizeof(hints)); 18403b3a8eb9SGleb Smirnoff hints.ai_family = AF_INET6; 18413b3a8eb9SGleb Smirnoff hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 18423b3a8eb9SGleb Smirnoff hints.ai_flags = AI_NUMERICHOST; 18433b3a8eb9SGleb Smirnoff if (getaddrinfo(s, "0", &hints, &res) == 0) { 18443b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(struct node_host)); 18453b3a8eb9SGleb Smirnoff if (h == NULL) 18463b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 18473b3a8eb9SGleb Smirnoff h->ifname = NULL; 18483b3a8eb9SGleb Smirnoff h->af = AF_INET6; 18493b3a8eb9SGleb Smirnoff memcpy(&h->addr.v.a.addr, 18503b3a8eb9SGleb Smirnoff &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 18513b3a8eb9SGleb Smirnoff sizeof(h->addr.v.a.addr)); 18523b3a8eb9SGleb Smirnoff h->ifindex = 18533b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 18543b3a8eb9SGleb Smirnoff set_ipmask(h, mask); 18553b3a8eb9SGleb Smirnoff freeaddrinfo(res); 18563b3a8eb9SGleb Smirnoff h->next = NULL; 18573b3a8eb9SGleb Smirnoff h->tail = h; 18583b3a8eb9SGleb Smirnoff } 18593b3a8eb9SGleb Smirnoff 18603b3a8eb9SGleb Smirnoff return (h); 18613b3a8eb9SGleb Smirnoff } 18623b3a8eb9SGleb Smirnoff 18633b3a8eb9SGleb Smirnoff struct node_host * 18643b3a8eb9SGleb Smirnoff host_dns(const char *s, int v4mask, int v6mask) 18653b3a8eb9SGleb Smirnoff { 18663b3a8eb9SGleb Smirnoff struct addrinfo hints, *res0, *res; 18673b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 18683b3a8eb9SGleb Smirnoff int error, noalias = 0; 18693b3a8eb9SGleb Smirnoff int got4 = 0, got6 = 0; 18703b3a8eb9SGleb Smirnoff char *p, *ps; 18713b3a8eb9SGleb Smirnoff 18723b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 18733b3a8eb9SGleb Smirnoff err(1, "host_dns: strdup"); 18743b3a8eb9SGleb Smirnoff if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) { 18753b3a8eb9SGleb Smirnoff noalias = 1; 18763b3a8eb9SGleb Smirnoff *p = '\0'; 18773b3a8eb9SGleb Smirnoff } 18783b3a8eb9SGleb Smirnoff memset(&hints, 0, sizeof(hints)); 18793b3a8eb9SGleb Smirnoff hints.ai_family = PF_UNSPEC; 18803b3a8eb9SGleb Smirnoff hints.ai_socktype = SOCK_STREAM; /* DUMMY */ 18813b3a8eb9SGleb Smirnoff error = getaddrinfo(ps, NULL, &hints, &res0); 18823b3a8eb9SGleb Smirnoff if (error) { 18833b3a8eb9SGleb Smirnoff free(ps); 18843b3a8eb9SGleb Smirnoff return (h); 18853b3a8eb9SGleb Smirnoff } 18863b3a8eb9SGleb Smirnoff 18873b3a8eb9SGleb Smirnoff for (res = res0; res; res = res->ai_next) { 18883b3a8eb9SGleb Smirnoff if (res->ai_family != AF_INET && 18893b3a8eb9SGleb Smirnoff res->ai_family != AF_INET6) 18903b3a8eb9SGleb Smirnoff continue; 18913b3a8eb9SGleb Smirnoff if (noalias) { 18923b3a8eb9SGleb Smirnoff if (res->ai_family == AF_INET) { 18933b3a8eb9SGleb Smirnoff if (got4) 18943b3a8eb9SGleb Smirnoff continue; 18953b3a8eb9SGleb Smirnoff got4 = 1; 18963b3a8eb9SGleb Smirnoff } else { 18973b3a8eb9SGleb Smirnoff if (got6) 18983b3a8eb9SGleb Smirnoff continue; 18993b3a8eb9SGleb Smirnoff got6 = 1; 19003b3a8eb9SGleb Smirnoff } 19013b3a8eb9SGleb Smirnoff } 19023b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 19033b3a8eb9SGleb Smirnoff if (n == NULL) 19043b3a8eb9SGleb Smirnoff err(1, "host_dns: calloc"); 19053b3a8eb9SGleb Smirnoff n->ifname = NULL; 19063b3a8eb9SGleb Smirnoff n->af = res->ai_family; 19073b3a8eb9SGleb Smirnoff if (res->ai_family == AF_INET) { 19083b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, 19093b3a8eb9SGleb Smirnoff &((struct sockaddr_in *) 19103b3a8eb9SGleb Smirnoff res->ai_addr)->sin_addr.s_addr, 19113b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 19123b3a8eb9SGleb Smirnoff set_ipmask(n, v4mask); 19133b3a8eb9SGleb Smirnoff } else { 19143b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, 19153b3a8eb9SGleb Smirnoff &((struct sockaddr_in6 *) 19163b3a8eb9SGleb Smirnoff res->ai_addr)->sin6_addr.s6_addr, 19173b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 19183b3a8eb9SGleb Smirnoff n->ifindex = 19193b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *) 19203b3a8eb9SGleb Smirnoff res->ai_addr)->sin6_scope_id; 19213b3a8eb9SGleb Smirnoff set_ipmask(n, v6mask); 19223b3a8eb9SGleb Smirnoff } 19233b3a8eb9SGleb Smirnoff n->next = NULL; 19243b3a8eb9SGleb Smirnoff n->tail = n; 19253b3a8eb9SGleb Smirnoff if (h == NULL) 19263b3a8eb9SGleb Smirnoff h = n; 19273b3a8eb9SGleb Smirnoff else { 19283b3a8eb9SGleb Smirnoff h->tail->next = n; 19293b3a8eb9SGleb Smirnoff h->tail = n; 19303b3a8eb9SGleb Smirnoff } 19313b3a8eb9SGleb Smirnoff } 19323b3a8eb9SGleb Smirnoff freeaddrinfo(res0); 19333b3a8eb9SGleb Smirnoff free(ps); 19343b3a8eb9SGleb Smirnoff 19353b3a8eb9SGleb Smirnoff return (h); 19363b3a8eb9SGleb Smirnoff } 19373b3a8eb9SGleb Smirnoff 19383b3a8eb9SGleb Smirnoff /* 19393b3a8eb9SGleb Smirnoff * convert a hostname to a list of addresses and put them in the given buffer. 19403b3a8eb9SGleb Smirnoff * test: 19413b3a8eb9SGleb Smirnoff * if set to 1, only simple addresses are accepted (no netblock, no "!"). 19423b3a8eb9SGleb Smirnoff */ 19433b3a8eb9SGleb Smirnoff int 19443b3a8eb9SGleb Smirnoff append_addr(struct pfr_buffer *b, char *s, int test) 19453b3a8eb9SGleb Smirnoff { 19463b3a8eb9SGleb Smirnoff char *r; 19473b3a8eb9SGleb Smirnoff struct node_host *h, *n; 19483b3a8eb9SGleb Smirnoff int rv, not = 0; 19493b3a8eb9SGleb Smirnoff 19503b3a8eb9SGleb Smirnoff for (r = s; *r == '!'; r++) 19513b3a8eb9SGleb Smirnoff not = !not; 19523b3a8eb9SGleb Smirnoff if ((n = host(r)) == NULL) { 19533b3a8eb9SGleb Smirnoff errno = 0; 19543b3a8eb9SGleb Smirnoff return (-1); 19553b3a8eb9SGleb Smirnoff } 19563b3a8eb9SGleb Smirnoff rv = append_addr_host(b, n, test, not); 19573b3a8eb9SGleb Smirnoff do { 19583b3a8eb9SGleb Smirnoff h = n; 19593b3a8eb9SGleb Smirnoff n = n->next; 19603b3a8eb9SGleb Smirnoff free(h); 19613b3a8eb9SGleb Smirnoff } while (n != NULL); 19623b3a8eb9SGleb Smirnoff return (rv); 19633b3a8eb9SGleb Smirnoff } 19643b3a8eb9SGleb Smirnoff 19653b3a8eb9SGleb Smirnoff /* 19663b3a8eb9SGleb Smirnoff * same as previous function, but with a pre-parsed input and the ability 19673b3a8eb9SGleb Smirnoff * to "negate" the result. Does not free the node_host list. 19683b3a8eb9SGleb Smirnoff * not: 19693b3a8eb9SGleb Smirnoff * setting it to 1 is equivalent to adding "!" in front of parameter s. 19703b3a8eb9SGleb Smirnoff */ 19713b3a8eb9SGleb Smirnoff int 19723b3a8eb9SGleb Smirnoff append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not) 19733b3a8eb9SGleb Smirnoff { 19743b3a8eb9SGleb Smirnoff int bits; 19753b3a8eb9SGleb Smirnoff struct pfr_addr addr; 19763b3a8eb9SGleb Smirnoff 19773b3a8eb9SGleb Smirnoff do { 19783b3a8eb9SGleb Smirnoff bzero(&addr, sizeof(addr)); 19793b3a8eb9SGleb Smirnoff addr.pfra_not = n->not ^ not; 19803b3a8eb9SGleb Smirnoff addr.pfra_af = n->af; 19813b3a8eb9SGleb Smirnoff addr.pfra_net = unmask(&n->addr.v.a.mask, n->af); 19823b3a8eb9SGleb Smirnoff switch (n->af) { 19833b3a8eb9SGleb Smirnoff case AF_INET: 19843b3a8eb9SGleb Smirnoff addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0]; 19853b3a8eb9SGleb Smirnoff bits = 32; 19863b3a8eb9SGleb Smirnoff break; 19873b3a8eb9SGleb Smirnoff case AF_INET6: 19883b3a8eb9SGleb Smirnoff memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6, 19893b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 19903b3a8eb9SGleb Smirnoff bits = 128; 19913b3a8eb9SGleb Smirnoff break; 19923b3a8eb9SGleb Smirnoff default: 19933b3a8eb9SGleb Smirnoff errno = EINVAL; 19943b3a8eb9SGleb Smirnoff return (-1); 19953b3a8eb9SGleb Smirnoff } 19963b3a8eb9SGleb Smirnoff if ((test && (not || addr.pfra_net != bits)) || 19973b3a8eb9SGleb Smirnoff addr.pfra_net > bits) { 19983b3a8eb9SGleb Smirnoff errno = EINVAL; 19993b3a8eb9SGleb Smirnoff return (-1); 20003b3a8eb9SGleb Smirnoff } 20013b3a8eb9SGleb Smirnoff if (pfr_buf_add(b, &addr)) 20023b3a8eb9SGleb Smirnoff return (-1); 20033b3a8eb9SGleb Smirnoff } while ((n = n->next) != NULL); 20043b3a8eb9SGleb Smirnoff 20053b3a8eb9SGleb Smirnoff return (0); 20063b3a8eb9SGleb Smirnoff } 20073b3a8eb9SGleb Smirnoff 20083b3a8eb9SGleb Smirnoff int 20093b3a8eb9SGleb Smirnoff pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor) 20103b3a8eb9SGleb Smirnoff { 20113b3a8eb9SGleb Smirnoff struct pfioc_trans_e trans; 20123b3a8eb9SGleb Smirnoff 20133b3a8eb9SGleb Smirnoff bzero(&trans, sizeof(trans)); 20143b3a8eb9SGleb Smirnoff trans.rs_num = rs_num; 20153b3a8eb9SGleb Smirnoff if (strlcpy(trans.anchor, anchor, 20163b3a8eb9SGleb Smirnoff sizeof(trans.anchor)) >= sizeof(trans.anchor)) 20173b3a8eb9SGleb Smirnoff errx(1, "pfctl_add_trans: strlcpy"); 20183b3a8eb9SGleb Smirnoff 20193b3a8eb9SGleb Smirnoff return pfr_buf_add(buf, &trans); 20203b3a8eb9SGleb Smirnoff } 20213b3a8eb9SGleb Smirnoff 20223b3a8eb9SGleb Smirnoff u_int32_t 20233b3a8eb9SGleb Smirnoff pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor) 20243b3a8eb9SGleb Smirnoff { 20253b3a8eb9SGleb Smirnoff struct pfioc_trans_e *p; 20263b3a8eb9SGleb Smirnoff 20273b3a8eb9SGleb Smirnoff PFRB_FOREACH(p, buf) 20283b3a8eb9SGleb Smirnoff if (rs_num == p->rs_num && !strcmp(anchor, p->anchor)) 20293b3a8eb9SGleb Smirnoff return (p->ticket); 20303b3a8eb9SGleb Smirnoff errx(1, "pfctl_get_ticket: assertion failed"); 20313b3a8eb9SGleb Smirnoff } 20323b3a8eb9SGleb Smirnoff 20333b3a8eb9SGleb Smirnoff int 20343b3a8eb9SGleb Smirnoff pfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from) 20353b3a8eb9SGleb Smirnoff { 20363b3a8eb9SGleb Smirnoff struct pfioc_trans trans; 20373b3a8eb9SGleb Smirnoff 20383b3a8eb9SGleb Smirnoff bzero(&trans, sizeof(trans)); 20393b3a8eb9SGleb Smirnoff trans.size = buf->pfrb_size - from; 20403b3a8eb9SGleb Smirnoff trans.esize = sizeof(struct pfioc_trans_e); 20413b3a8eb9SGleb Smirnoff trans.array = ((struct pfioc_trans_e *)buf->pfrb_caddr) + from; 20423b3a8eb9SGleb Smirnoff return ioctl(dev, cmd, &trans); 20433b3a8eb9SGleb Smirnoff } 2044