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/types.h> 373b3a8eb9SGleb Smirnoff #include <sys/ioctl.h> 383b3a8eb9SGleb Smirnoff #include <sys/socket.h> 393b3a8eb9SGleb Smirnoff #include <sys/param.h> 403b3a8eb9SGleb Smirnoff #include <sys/proc.h> 413b3a8eb9SGleb Smirnoff #include <net/if.h> 423b3a8eb9SGleb Smirnoff #include <netinet/in.h> 433b3a8eb9SGleb Smirnoff #include <netinet/in_systm.h> 443b3a8eb9SGleb Smirnoff #include <netinet/ip.h> 453b3a8eb9SGleb Smirnoff #include <netinet/ip_icmp.h> 463b3a8eb9SGleb Smirnoff #include <netinet/icmp6.h> 473b3a8eb9SGleb Smirnoff #include <net/pfvar.h> 483b3a8eb9SGleb Smirnoff #include <arpa/inet.h> 493b3a8eb9SGleb Smirnoff 505062afffSKristof Provost #include <assert.h> 511d34c9daSPatrick Kelsey #include <search.h> 523b3a8eb9SGleb Smirnoff #include <stdio.h> 533b3a8eb9SGleb Smirnoff #include <stdlib.h> 543b3a8eb9SGleb Smirnoff #include <string.h> 553b3a8eb9SGleb Smirnoff #include <ctype.h> 563b3a8eb9SGleb Smirnoff #include <netdb.h> 573b3a8eb9SGleb Smirnoff #include <stdarg.h> 583b3a8eb9SGleb Smirnoff #include <errno.h> 593b3a8eb9SGleb Smirnoff #include <err.h> 603b3a8eb9SGleb Smirnoff #include <ifaddrs.h> 613b3a8eb9SGleb Smirnoff #include <unistd.h> 623b3a8eb9SGleb Smirnoff 633b3a8eb9SGleb Smirnoff #include "pfctl_parser.h" 643b3a8eb9SGleb Smirnoff #include "pfctl.h" 653b3a8eb9SGleb Smirnoff 663b3a8eb9SGleb Smirnoff void print_op (u_int8_t, const char *, const char *); 673b3a8eb9SGleb Smirnoff void print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int); 683b3a8eb9SGleb Smirnoff void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned); 693b3a8eb9SGleb Smirnoff void print_flags (u_int8_t); 703b3a8eb9SGleb Smirnoff void print_fromto(struct pf_rule_addr *, pf_osfp_t, 71dbce131bSKristof Provost struct pf_rule_addr *, sa_family_t, u_int8_t, int, int); 723b3a8eb9SGleb Smirnoff int ifa_skip_if(const char *filter, struct node_host *p); 733b3a8eb9SGleb Smirnoff 7428b64169SFranco Fichtner struct node_host *host_if(const char *, int, int *); 753b3a8eb9SGleb Smirnoff struct node_host *host_v4(const char *, int); 763b3a8eb9SGleb Smirnoff struct node_host *host_v6(const char *, int); 773b3a8eb9SGleb Smirnoff struct node_host *host_dns(const char *, int, int); 783b3a8eb9SGleb Smirnoff 7972a3cf0fSKristof Provost const char * const tcpflags = "FSRPAUEW"; 803b3a8eb9SGleb Smirnoff 813b3a8eb9SGleb Smirnoff static const struct icmptypeent icmp_type[] = { 823b3a8eb9SGleb Smirnoff { "echoreq", ICMP_ECHO }, 833b3a8eb9SGleb Smirnoff { "echorep", ICMP_ECHOREPLY }, 843b3a8eb9SGleb Smirnoff { "unreach", ICMP_UNREACH }, 853b3a8eb9SGleb Smirnoff { "squench", ICMP_SOURCEQUENCH }, 863b3a8eb9SGleb Smirnoff { "redir", ICMP_REDIRECT }, 873b3a8eb9SGleb Smirnoff { "althost", ICMP_ALTHOSTADDR }, 883b3a8eb9SGleb Smirnoff { "routeradv", ICMP_ROUTERADVERT }, 893b3a8eb9SGleb Smirnoff { "routersol", ICMP_ROUTERSOLICIT }, 903b3a8eb9SGleb Smirnoff { "timex", ICMP_TIMXCEED }, 913b3a8eb9SGleb Smirnoff { "paramprob", ICMP_PARAMPROB }, 923b3a8eb9SGleb Smirnoff { "timereq", ICMP_TSTAMP }, 933b3a8eb9SGleb Smirnoff { "timerep", ICMP_TSTAMPREPLY }, 943b3a8eb9SGleb Smirnoff { "inforeq", ICMP_IREQ }, 953b3a8eb9SGleb Smirnoff { "inforep", ICMP_IREQREPLY }, 963b3a8eb9SGleb Smirnoff { "maskreq", ICMP_MASKREQ }, 973b3a8eb9SGleb Smirnoff { "maskrep", ICMP_MASKREPLY }, 983b3a8eb9SGleb Smirnoff { "trace", ICMP_TRACEROUTE }, 993b3a8eb9SGleb Smirnoff { "dataconv", ICMP_DATACONVERR }, 1003b3a8eb9SGleb Smirnoff { "mobredir", ICMP_MOBILE_REDIRECT }, 1013b3a8eb9SGleb Smirnoff { "ipv6-where", ICMP_IPV6_WHEREAREYOU }, 1023b3a8eb9SGleb Smirnoff { "ipv6-here", ICMP_IPV6_IAMHERE }, 1033b3a8eb9SGleb Smirnoff { "mobregreq", ICMP_MOBILE_REGREQUEST }, 1043b3a8eb9SGleb Smirnoff { "mobregrep", ICMP_MOBILE_REGREPLY }, 1053b3a8eb9SGleb Smirnoff { "skip", ICMP_SKIP }, 1063b3a8eb9SGleb Smirnoff { "photuris", ICMP_PHOTURIS } 1073b3a8eb9SGleb Smirnoff }; 1083b3a8eb9SGleb Smirnoff 1093b3a8eb9SGleb Smirnoff static const struct icmptypeent icmp6_type[] = { 1103b3a8eb9SGleb Smirnoff { "unreach", ICMP6_DST_UNREACH }, 1113b3a8eb9SGleb Smirnoff { "toobig", ICMP6_PACKET_TOO_BIG }, 1123b3a8eb9SGleb Smirnoff { "timex", ICMP6_TIME_EXCEEDED }, 1133b3a8eb9SGleb Smirnoff { "paramprob", ICMP6_PARAM_PROB }, 1143b3a8eb9SGleb Smirnoff { "echoreq", ICMP6_ECHO_REQUEST }, 1153b3a8eb9SGleb Smirnoff { "echorep", ICMP6_ECHO_REPLY }, 1163b3a8eb9SGleb Smirnoff { "groupqry", ICMP6_MEMBERSHIP_QUERY }, 1173b3a8eb9SGleb Smirnoff { "listqry", MLD_LISTENER_QUERY }, 1183b3a8eb9SGleb Smirnoff { "grouprep", ICMP6_MEMBERSHIP_REPORT }, 1193b3a8eb9SGleb Smirnoff { "listenrep", MLD_LISTENER_REPORT }, 1203b3a8eb9SGleb Smirnoff { "groupterm", ICMP6_MEMBERSHIP_REDUCTION }, 1213b3a8eb9SGleb Smirnoff { "listendone", MLD_LISTENER_DONE }, 1223b3a8eb9SGleb Smirnoff { "routersol", ND_ROUTER_SOLICIT }, 1233b3a8eb9SGleb Smirnoff { "routeradv", ND_ROUTER_ADVERT }, 1243b3a8eb9SGleb Smirnoff { "neighbrsol", ND_NEIGHBOR_SOLICIT }, 1253b3a8eb9SGleb Smirnoff { "neighbradv", ND_NEIGHBOR_ADVERT }, 1263b3a8eb9SGleb Smirnoff { "redir", ND_REDIRECT }, 1273b3a8eb9SGleb Smirnoff { "routrrenum", ICMP6_ROUTER_RENUMBERING }, 1283b3a8eb9SGleb Smirnoff { "wrureq", ICMP6_WRUREQUEST }, 1293b3a8eb9SGleb Smirnoff { "wrurep", ICMP6_WRUREPLY }, 1303b3a8eb9SGleb Smirnoff { "fqdnreq", ICMP6_FQDN_QUERY }, 1313b3a8eb9SGleb Smirnoff { "fqdnrep", ICMP6_FQDN_REPLY }, 1323b3a8eb9SGleb Smirnoff { "niqry", ICMP6_NI_QUERY }, 1333b3a8eb9SGleb Smirnoff { "nirep", ICMP6_NI_REPLY }, 1343b3a8eb9SGleb Smirnoff { "mtraceresp", MLD_MTRACE_RESP }, 1353b3a8eb9SGleb Smirnoff { "mtrace", MLD_MTRACE } 1363b3a8eb9SGleb Smirnoff }; 1373b3a8eb9SGleb Smirnoff 1383b3a8eb9SGleb Smirnoff static const struct icmpcodeent icmp_code[] = { 1393b3a8eb9SGleb Smirnoff { "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET }, 1403b3a8eb9SGleb Smirnoff { "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST }, 1413b3a8eb9SGleb Smirnoff { "proto-unr", ICMP_UNREACH, ICMP_UNREACH_PROTOCOL }, 1423b3a8eb9SGleb Smirnoff { "port-unr", ICMP_UNREACH, ICMP_UNREACH_PORT }, 1433b3a8eb9SGleb Smirnoff { "needfrag", ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG }, 1443b3a8eb9SGleb Smirnoff { "srcfail", ICMP_UNREACH, ICMP_UNREACH_SRCFAIL }, 1453b3a8eb9SGleb Smirnoff { "net-unk", ICMP_UNREACH, ICMP_UNREACH_NET_UNKNOWN }, 1463b3a8eb9SGleb Smirnoff { "host-unk", ICMP_UNREACH, ICMP_UNREACH_HOST_UNKNOWN }, 1473b3a8eb9SGleb Smirnoff { "isolate", ICMP_UNREACH, ICMP_UNREACH_ISOLATED }, 1483b3a8eb9SGleb Smirnoff { "net-prohib", ICMP_UNREACH, ICMP_UNREACH_NET_PROHIB }, 1493b3a8eb9SGleb Smirnoff { "host-prohib", ICMP_UNREACH, ICMP_UNREACH_HOST_PROHIB }, 1503b3a8eb9SGleb Smirnoff { "net-tos", ICMP_UNREACH, ICMP_UNREACH_TOSNET }, 1513b3a8eb9SGleb Smirnoff { "host-tos", ICMP_UNREACH, ICMP_UNREACH_TOSHOST }, 1523b3a8eb9SGleb Smirnoff { "filter-prohib", ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB }, 1533b3a8eb9SGleb Smirnoff { "host-preced", ICMP_UNREACH, ICMP_UNREACH_HOST_PRECEDENCE }, 1543b3a8eb9SGleb Smirnoff { "cutoff-preced", ICMP_UNREACH, ICMP_UNREACH_PRECEDENCE_CUTOFF }, 1553b3a8eb9SGleb Smirnoff { "redir-net", ICMP_REDIRECT, ICMP_REDIRECT_NET }, 1563b3a8eb9SGleb Smirnoff { "redir-host", ICMP_REDIRECT, ICMP_REDIRECT_HOST }, 1573b3a8eb9SGleb Smirnoff { "redir-tos-net", ICMP_REDIRECT, ICMP_REDIRECT_TOSNET }, 1583b3a8eb9SGleb Smirnoff { "redir-tos-host", ICMP_REDIRECT, ICMP_REDIRECT_TOSHOST }, 1593b3a8eb9SGleb Smirnoff { "normal-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL }, 1603b3a8eb9SGleb Smirnoff { "common-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON }, 1613b3a8eb9SGleb Smirnoff { "transit", ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS }, 1623b3a8eb9SGleb Smirnoff { "reassemb", ICMP_TIMXCEED, ICMP_TIMXCEED_REASS }, 1633b3a8eb9SGleb Smirnoff { "badhead", ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR }, 1643b3a8eb9SGleb Smirnoff { "optmiss", ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT }, 1653b3a8eb9SGleb Smirnoff { "badlen", ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH }, 1663b3a8eb9SGleb Smirnoff { "unknown-ind", ICMP_PHOTURIS, ICMP_PHOTURIS_UNKNOWN_INDEX }, 1673b3a8eb9SGleb Smirnoff { "auth-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_AUTH_FAILED }, 1683b3a8eb9SGleb Smirnoff { "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED } 1693b3a8eb9SGleb Smirnoff }; 1703b3a8eb9SGleb Smirnoff 1713b3a8eb9SGleb Smirnoff static const struct icmpcodeent icmp6_code[] = { 1723b3a8eb9SGleb Smirnoff { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN }, 1733b3a8eb9SGleb Smirnoff { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE }, 1743b3a8eb9SGleb Smirnoff { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR }, 1753b3a8eb9SGleb Smirnoff { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE }, 1763b3a8eb9SGleb Smirnoff { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR }, 1773b3a8eb9SGleb Smirnoff { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT }, 1783b3a8eb9SGleb Smirnoff { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT }, 1793b3a8eb9SGleb Smirnoff { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY }, 1803b3a8eb9SGleb Smirnoff { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER }, 1813b3a8eb9SGleb Smirnoff { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER }, 1823b3a8eb9SGleb Smirnoff { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK }, 1833b3a8eb9SGleb Smirnoff { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER } 1843b3a8eb9SGleb Smirnoff }; 1853b3a8eb9SGleb Smirnoff 1863b3a8eb9SGleb Smirnoff const struct pf_timeout pf_timeouts[] = { 1873b3a8eb9SGleb Smirnoff { "tcp.first", PFTM_TCP_FIRST_PACKET }, 1883b3a8eb9SGleb Smirnoff { "tcp.opening", PFTM_TCP_OPENING }, 1893b3a8eb9SGleb Smirnoff { "tcp.established", PFTM_TCP_ESTABLISHED }, 1903b3a8eb9SGleb Smirnoff { "tcp.closing", PFTM_TCP_CLOSING }, 1913b3a8eb9SGleb Smirnoff { "tcp.finwait", PFTM_TCP_FIN_WAIT }, 1923b3a8eb9SGleb Smirnoff { "tcp.closed", PFTM_TCP_CLOSED }, 1933b3a8eb9SGleb Smirnoff { "tcp.tsdiff", PFTM_TS_DIFF }, 194ca9dbde8SKristof Provost { "sctp.first", PFTM_SCTP_FIRST_PACKET }, 195ca9dbde8SKristof Provost { "sctp.opening", PFTM_SCTP_OPENING }, 196ca9dbde8SKristof Provost { "sctp.established", PFTM_SCTP_ESTABLISHED }, 197ca9dbde8SKristof Provost { "sctp.closing", PFTM_SCTP_CLOSING }, 198ca9dbde8SKristof Provost { "sctp.closed", PFTM_SCTP_CLOSED }, 1993b3a8eb9SGleb Smirnoff { "udp.first", PFTM_UDP_FIRST_PACKET }, 2003b3a8eb9SGleb Smirnoff { "udp.single", PFTM_UDP_SINGLE }, 2013b3a8eb9SGleb Smirnoff { "udp.multiple", PFTM_UDP_MULTIPLE }, 2023b3a8eb9SGleb Smirnoff { "icmp.first", PFTM_ICMP_FIRST_PACKET }, 2033b3a8eb9SGleb Smirnoff { "icmp.error", PFTM_ICMP_ERROR_REPLY }, 2043b3a8eb9SGleb Smirnoff { "other.first", PFTM_OTHER_FIRST_PACKET }, 2053b3a8eb9SGleb Smirnoff { "other.single", PFTM_OTHER_SINGLE }, 2063b3a8eb9SGleb Smirnoff { "other.multiple", PFTM_OTHER_MULTIPLE }, 2073b3a8eb9SGleb Smirnoff { "frag", PFTM_FRAG }, 2083b3a8eb9SGleb Smirnoff { "interval", PFTM_INTERVAL }, 2093b3a8eb9SGleb Smirnoff { "adaptive.start", PFTM_ADAPTIVE_START }, 2103b3a8eb9SGleb Smirnoff { "adaptive.end", PFTM_ADAPTIVE_END }, 2113b3a8eb9SGleb Smirnoff { "src.track", PFTM_SRC_NODE }, 2123b3a8eb9SGleb Smirnoff { NULL, 0 } 2133b3a8eb9SGleb Smirnoff }; 2143b3a8eb9SGleb Smirnoff 2151d34c9daSPatrick Kelsey static struct hsearch_data isgroup_map; 2161d34c9daSPatrick Kelsey 2171d34c9daSPatrick Kelsey static __attribute__((constructor)) void 2181d34c9daSPatrick Kelsey pfctl_parser_init(void) 2191d34c9daSPatrick Kelsey { 2201d34c9daSPatrick Kelsey /* 2211d34c9daSPatrick Kelsey * As hdestroy() will never be called on these tables, it will be 2221d34c9daSPatrick Kelsey * safe to use references into the stored data as keys. 2231d34c9daSPatrick Kelsey */ 2241d34c9daSPatrick Kelsey if (hcreate_r(0, &isgroup_map) == 0) 2251d34c9daSPatrick Kelsey err(1, "Failed to create interface group query response map"); 2261d34c9daSPatrick Kelsey } 2271d34c9daSPatrick Kelsey 2283b3a8eb9SGleb Smirnoff const struct icmptypeent * 2293b3a8eb9SGleb Smirnoff geticmptypebynumber(u_int8_t type, sa_family_t af) 2303b3a8eb9SGleb Smirnoff { 2313b3a8eb9SGleb Smirnoff unsigned int i; 2323b3a8eb9SGleb Smirnoff 2333b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 234c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_type); i++) { 2353b3a8eb9SGleb Smirnoff if (type == icmp_type[i].type) 2363b3a8eb9SGleb Smirnoff return (&icmp_type[i]); 2373b3a8eb9SGleb Smirnoff } 2383b3a8eb9SGleb Smirnoff } else { 239c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_type); i++) { 2403b3a8eb9SGleb Smirnoff if (type == icmp6_type[i].type) 2413b3a8eb9SGleb Smirnoff return (&icmp6_type[i]); 2423b3a8eb9SGleb Smirnoff } 2433b3a8eb9SGleb Smirnoff } 2443b3a8eb9SGleb Smirnoff return (NULL); 2453b3a8eb9SGleb Smirnoff } 2463b3a8eb9SGleb Smirnoff 2473b3a8eb9SGleb Smirnoff const struct icmptypeent * 2483b3a8eb9SGleb Smirnoff geticmptypebyname(char *w, sa_family_t af) 2493b3a8eb9SGleb Smirnoff { 2503b3a8eb9SGleb Smirnoff unsigned int i; 2513b3a8eb9SGleb Smirnoff 2523b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 253c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_type); i++) { 2543b3a8eb9SGleb Smirnoff if (!strcmp(w, icmp_type[i].name)) 2553b3a8eb9SGleb Smirnoff return (&icmp_type[i]); 2563b3a8eb9SGleb Smirnoff } 2573b3a8eb9SGleb Smirnoff } else { 258c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_type); i++) { 2593b3a8eb9SGleb Smirnoff if (!strcmp(w, icmp6_type[i].name)) 2603b3a8eb9SGleb Smirnoff return (&icmp6_type[i]); 2613b3a8eb9SGleb Smirnoff } 2623b3a8eb9SGleb Smirnoff } 2633b3a8eb9SGleb Smirnoff return (NULL); 2643b3a8eb9SGleb Smirnoff } 2653b3a8eb9SGleb Smirnoff 2663b3a8eb9SGleb Smirnoff const struct icmpcodeent * 2673b3a8eb9SGleb Smirnoff geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af) 2683b3a8eb9SGleb Smirnoff { 2693b3a8eb9SGleb Smirnoff unsigned int i; 2703b3a8eb9SGleb Smirnoff 2713b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 272c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_code); i++) { 2733b3a8eb9SGleb Smirnoff if (type == icmp_code[i].type && 2743b3a8eb9SGleb Smirnoff code == icmp_code[i].code) 2753b3a8eb9SGleb Smirnoff return (&icmp_code[i]); 2763b3a8eb9SGleb Smirnoff } 2773b3a8eb9SGleb Smirnoff } else { 278c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_code); i++) { 2793b3a8eb9SGleb Smirnoff if (type == icmp6_code[i].type && 2803b3a8eb9SGleb Smirnoff code == icmp6_code[i].code) 2813b3a8eb9SGleb Smirnoff return (&icmp6_code[i]); 2823b3a8eb9SGleb Smirnoff } 2833b3a8eb9SGleb Smirnoff } 2843b3a8eb9SGleb Smirnoff return (NULL); 2853b3a8eb9SGleb Smirnoff } 2863b3a8eb9SGleb Smirnoff 2873b3a8eb9SGleb Smirnoff const struct icmpcodeent * 2883b3a8eb9SGleb Smirnoff geticmpcodebyname(u_long type, char *w, sa_family_t af) 2893b3a8eb9SGleb Smirnoff { 2903b3a8eb9SGleb Smirnoff unsigned int i; 2913b3a8eb9SGleb Smirnoff 2923b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 293c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_code); i++) { 2943b3a8eb9SGleb Smirnoff if (type == icmp_code[i].type && 2953b3a8eb9SGleb Smirnoff !strcmp(w, icmp_code[i].name)) 2963b3a8eb9SGleb Smirnoff return (&icmp_code[i]); 2973b3a8eb9SGleb Smirnoff } 2983b3a8eb9SGleb Smirnoff } else { 299c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_code); i++) { 3003b3a8eb9SGleb Smirnoff if (type == icmp6_code[i].type && 3013b3a8eb9SGleb Smirnoff !strcmp(w, icmp6_code[i].name)) 3023b3a8eb9SGleb Smirnoff return (&icmp6_code[i]); 3033b3a8eb9SGleb Smirnoff } 3043b3a8eb9SGleb Smirnoff } 3053b3a8eb9SGleb Smirnoff return (NULL); 3063b3a8eb9SGleb Smirnoff } 3073b3a8eb9SGleb Smirnoff 3083b3a8eb9SGleb Smirnoff void 3093b3a8eb9SGleb Smirnoff print_op(u_int8_t op, const char *a1, const char *a2) 3103b3a8eb9SGleb Smirnoff { 3113b3a8eb9SGleb Smirnoff if (op == PF_OP_IRG) 3123b3a8eb9SGleb Smirnoff printf(" %s >< %s", a1, a2); 3133b3a8eb9SGleb Smirnoff else if (op == PF_OP_XRG) 3143b3a8eb9SGleb Smirnoff printf(" %s <> %s", a1, a2); 3153b3a8eb9SGleb Smirnoff else if (op == PF_OP_EQ) 3163b3a8eb9SGleb Smirnoff printf(" = %s", a1); 3173b3a8eb9SGleb Smirnoff else if (op == PF_OP_NE) 3183b3a8eb9SGleb Smirnoff printf(" != %s", a1); 3193b3a8eb9SGleb Smirnoff else if (op == PF_OP_LT) 3203b3a8eb9SGleb Smirnoff printf(" < %s", a1); 3213b3a8eb9SGleb Smirnoff else if (op == PF_OP_LE) 3223b3a8eb9SGleb Smirnoff printf(" <= %s", a1); 3233b3a8eb9SGleb Smirnoff else if (op == PF_OP_GT) 3243b3a8eb9SGleb Smirnoff printf(" > %s", a1); 3253b3a8eb9SGleb Smirnoff else if (op == PF_OP_GE) 3263b3a8eb9SGleb Smirnoff printf(" >= %s", a1); 3273b3a8eb9SGleb Smirnoff else if (op == PF_OP_RRG) 3283b3a8eb9SGleb Smirnoff printf(" %s:%s", a1, a2); 3293b3a8eb9SGleb Smirnoff } 3303b3a8eb9SGleb Smirnoff 3313b3a8eb9SGleb Smirnoff void 3323b3a8eb9SGleb Smirnoff print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int numeric) 3333b3a8eb9SGleb Smirnoff { 3343b3a8eb9SGleb Smirnoff char a1[6], a2[6]; 3353b3a8eb9SGleb Smirnoff struct servent *s; 3363b3a8eb9SGleb Smirnoff 3373b3a8eb9SGleb Smirnoff if (!numeric) 3383b3a8eb9SGleb Smirnoff s = getservbyport(p1, proto); 3393b3a8eb9SGleb Smirnoff else 3403b3a8eb9SGleb Smirnoff s = NULL; 3413b3a8eb9SGleb Smirnoff p1 = ntohs(p1); 3423b3a8eb9SGleb Smirnoff p2 = ntohs(p2); 3433b3a8eb9SGleb Smirnoff snprintf(a1, sizeof(a1), "%u", p1); 3443b3a8eb9SGleb Smirnoff snprintf(a2, sizeof(a2), "%u", p2); 3453b3a8eb9SGleb Smirnoff printf(" port"); 3463b3a8eb9SGleb Smirnoff if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE)) 3473b3a8eb9SGleb Smirnoff print_op(op, s->s_name, a2); 3483b3a8eb9SGleb Smirnoff else 3493b3a8eb9SGleb Smirnoff print_op(op, a1, a2); 3503b3a8eb9SGleb Smirnoff } 3513b3a8eb9SGleb Smirnoff 3523b3a8eb9SGleb Smirnoff void 3533b3a8eb9SGleb Smirnoff print_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax) 3543b3a8eb9SGleb Smirnoff { 3553b3a8eb9SGleb Smirnoff char a1[11], a2[11]; 3563b3a8eb9SGleb Smirnoff 3573b3a8eb9SGleb Smirnoff snprintf(a1, sizeof(a1), "%u", u1); 3583b3a8eb9SGleb Smirnoff snprintf(a2, sizeof(a2), "%u", u2); 3593b3a8eb9SGleb Smirnoff printf(" %s", t); 3603b3a8eb9SGleb Smirnoff if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE)) 3613b3a8eb9SGleb Smirnoff print_op(op, "unknown", a2); 3623b3a8eb9SGleb Smirnoff else 3633b3a8eb9SGleb Smirnoff print_op(op, a1, a2); 3643b3a8eb9SGleb Smirnoff } 3653b3a8eb9SGleb Smirnoff 3663b3a8eb9SGleb Smirnoff void 3673b3a8eb9SGleb Smirnoff print_flags(u_int8_t f) 3683b3a8eb9SGleb Smirnoff { 3693b3a8eb9SGleb Smirnoff int i; 3703b3a8eb9SGleb Smirnoff 3713b3a8eb9SGleb Smirnoff for (i = 0; tcpflags[i]; ++i) 3723b3a8eb9SGleb Smirnoff if (f & (1 << i)) 3733b3a8eb9SGleb Smirnoff printf("%c", tcpflags[i]); 3743b3a8eb9SGleb Smirnoff } 3753b3a8eb9SGleb Smirnoff 3763b3a8eb9SGleb Smirnoff void 3773b3a8eb9SGleb Smirnoff print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, 3783b3a8eb9SGleb Smirnoff sa_family_t af, u_int8_t proto, int verbose, int numeric) 3793b3a8eb9SGleb Smirnoff { 3803b3a8eb9SGleb Smirnoff char buf[PF_OSFP_LEN*3]; 3813b3a8eb9SGleb Smirnoff if (src->addr.type == PF_ADDR_ADDRMASK && 3823b3a8eb9SGleb Smirnoff dst->addr.type == PF_ADDR_ADDRMASK && 3833b3a8eb9SGleb Smirnoff PF_AZERO(&src->addr.v.a.addr, AF_INET6) && 3843b3a8eb9SGleb Smirnoff PF_AZERO(&src->addr.v.a.mask, AF_INET6) && 3853b3a8eb9SGleb Smirnoff PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && 3863b3a8eb9SGleb Smirnoff PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && 3873b3a8eb9SGleb Smirnoff !src->neg && !dst->neg && 3883b3a8eb9SGleb Smirnoff !src->port_op && !dst->port_op && 3893b3a8eb9SGleb Smirnoff osfp == PF_OSFP_ANY) 3903b3a8eb9SGleb Smirnoff printf(" all"); 3913b3a8eb9SGleb Smirnoff else { 3923b3a8eb9SGleb Smirnoff printf(" from "); 3933b3a8eb9SGleb Smirnoff if (src->neg) 3943b3a8eb9SGleb Smirnoff printf("! "); 3953b3a8eb9SGleb Smirnoff print_addr(&src->addr, af, verbose); 3963b3a8eb9SGleb Smirnoff if (src->port_op) 3973b3a8eb9SGleb Smirnoff print_port(src->port_op, src->port[0], 3983b3a8eb9SGleb Smirnoff src->port[1], 3993b3a8eb9SGleb Smirnoff proto == IPPROTO_TCP ? "tcp" : "udp", 4003b3a8eb9SGleb Smirnoff numeric); 4013b3a8eb9SGleb Smirnoff if (osfp != PF_OSFP_ANY) 4023b3a8eb9SGleb Smirnoff printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf, 4033b3a8eb9SGleb Smirnoff sizeof(buf))); 4043b3a8eb9SGleb Smirnoff 4053b3a8eb9SGleb Smirnoff printf(" to "); 4063b3a8eb9SGleb Smirnoff if (dst->neg) 4073b3a8eb9SGleb Smirnoff printf("! "); 4083b3a8eb9SGleb Smirnoff print_addr(&dst->addr, af, verbose); 4093b3a8eb9SGleb Smirnoff if (dst->port_op) 4103b3a8eb9SGleb Smirnoff print_port(dst->port_op, dst->port[0], 4113b3a8eb9SGleb Smirnoff dst->port[1], 4123b3a8eb9SGleb Smirnoff proto == IPPROTO_TCP ? "tcp" : "udp", 4133b3a8eb9SGleb Smirnoff numeric); 4143b3a8eb9SGleb Smirnoff } 4153b3a8eb9SGleb Smirnoff } 4163b3a8eb9SGleb Smirnoff 4173b3a8eb9SGleb Smirnoff void 418600bd6ceSKurosawa Takahiro print_pool(struct pfctl_pool *pool, u_int16_t p1, u_int16_t p2, 4193b3a8eb9SGleb Smirnoff sa_family_t af, int id) 4203b3a8eb9SGleb Smirnoff { 4213b3a8eb9SGleb Smirnoff struct pf_pooladdr *pooladdr; 4223b3a8eb9SGleb Smirnoff 4233b3a8eb9SGleb Smirnoff if ((TAILQ_FIRST(&pool->list) != NULL) && 4243b3a8eb9SGleb Smirnoff TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4253b3a8eb9SGleb Smirnoff printf("{ "); 4263b3a8eb9SGleb Smirnoff TAILQ_FOREACH(pooladdr, &pool->list, entries){ 4273b3a8eb9SGleb Smirnoff switch (id) { 4283b3a8eb9SGleb Smirnoff case PF_NAT: 4293b3a8eb9SGleb Smirnoff case PF_RDR: 4303b3a8eb9SGleb Smirnoff case PF_BINAT: 4313b3a8eb9SGleb Smirnoff print_addr(&pooladdr->addr, af, 0); 4323b3a8eb9SGleb Smirnoff break; 4333b3a8eb9SGleb Smirnoff case PF_PASS: 43439282ef3SKajetan Staszkiewicz case PF_MATCH: 4353b3a8eb9SGleb Smirnoff if (PF_AZERO(&pooladdr->addr.v.a.addr, af)) 4363b3a8eb9SGleb Smirnoff printf("%s", pooladdr->ifname); 4373b3a8eb9SGleb Smirnoff else { 4383b3a8eb9SGleb Smirnoff printf("(%s ", pooladdr->ifname); 4393b3a8eb9SGleb Smirnoff print_addr(&pooladdr->addr, af, 0); 4403b3a8eb9SGleb Smirnoff printf(")"); 4413b3a8eb9SGleb Smirnoff } 4423b3a8eb9SGleb Smirnoff break; 4433b3a8eb9SGleb Smirnoff default: 4443b3a8eb9SGleb Smirnoff break; 4453b3a8eb9SGleb Smirnoff } 4463b3a8eb9SGleb Smirnoff if (TAILQ_NEXT(pooladdr, entries) != NULL) 4473b3a8eb9SGleb Smirnoff printf(", "); 4483b3a8eb9SGleb Smirnoff else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4493b3a8eb9SGleb Smirnoff printf(" }"); 4503b3a8eb9SGleb Smirnoff } 4513b3a8eb9SGleb Smirnoff switch (id) { 4523b3a8eb9SGleb Smirnoff case PF_NAT: 4533b3a8eb9SGleb Smirnoff if ((p1 != PF_NAT_PROXY_PORT_LOW || 4543b3a8eb9SGleb Smirnoff p2 != PF_NAT_PROXY_PORT_HIGH) && (p1 != 0 || p2 != 0)) { 4553b3a8eb9SGleb Smirnoff if (p1 == p2) 4563b3a8eb9SGleb Smirnoff printf(" port %u", p1); 4573b3a8eb9SGleb Smirnoff else 4583b3a8eb9SGleb Smirnoff printf(" port %u:%u", p1, p2); 4593b3a8eb9SGleb Smirnoff } 4603b3a8eb9SGleb Smirnoff break; 4613b3a8eb9SGleb Smirnoff case PF_RDR: 4623b3a8eb9SGleb Smirnoff if (p1) { 4633b3a8eb9SGleb Smirnoff printf(" port %u", p1); 4643b3a8eb9SGleb Smirnoff if (p2 && (p2 != p1)) 4653b3a8eb9SGleb Smirnoff printf(":%u", p2); 4663b3a8eb9SGleb Smirnoff } 4673b3a8eb9SGleb Smirnoff break; 4683b3a8eb9SGleb Smirnoff default: 4693b3a8eb9SGleb Smirnoff break; 4703b3a8eb9SGleb Smirnoff } 4713b3a8eb9SGleb Smirnoff switch (pool->opts & PF_POOL_TYPEMASK) { 4723b3a8eb9SGleb Smirnoff case PF_POOL_NONE: 4733b3a8eb9SGleb Smirnoff break; 4743b3a8eb9SGleb Smirnoff case PF_POOL_BITMASK: 4753b3a8eb9SGleb Smirnoff printf(" bitmask"); 4763b3a8eb9SGleb Smirnoff break; 4773b3a8eb9SGleb Smirnoff case PF_POOL_RANDOM: 4783b3a8eb9SGleb Smirnoff printf(" random"); 4793b3a8eb9SGleb Smirnoff break; 4803b3a8eb9SGleb Smirnoff case PF_POOL_SRCHASH: 4813b3a8eb9SGleb Smirnoff printf(" source-hash 0x%08x%08x%08x%08x", 4823b3a8eb9SGleb Smirnoff pool->key.key32[0], pool->key.key32[1], 4833b3a8eb9SGleb Smirnoff pool->key.key32[2], pool->key.key32[3]); 4843b3a8eb9SGleb Smirnoff break; 4853b3a8eb9SGleb Smirnoff case PF_POOL_ROUNDROBIN: 4863b3a8eb9SGleb Smirnoff printf(" round-robin"); 4873b3a8eb9SGleb Smirnoff break; 4883b3a8eb9SGleb Smirnoff } 4893b3a8eb9SGleb Smirnoff if (pool->opts & PF_POOL_STICKYADDR) 4903b3a8eb9SGleb Smirnoff printf(" sticky-address"); 4913b3a8eb9SGleb Smirnoff if (id == PF_NAT && p1 == 0 && p2 == 0) 4923b3a8eb9SGleb Smirnoff printf(" static-port"); 4932aa21096SKurosawa Takahiro if (pool->mape.offset > 0) 4942aa21096SKurosawa Takahiro printf(" map-e-portset %u/%u/%u", 4952aa21096SKurosawa Takahiro pool->mape.offset, pool->mape.psidlen, pool->mape.psid); 4963b3a8eb9SGleb Smirnoff } 4973b3a8eb9SGleb Smirnoff 49872a3cf0fSKristof Provost const char * const pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 49972a3cf0fSKristof Provost const char * const pf_lcounters[LCNT_MAX+1] = LCNT_NAMES; 50072a3cf0fSKristof Provost const char * const pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 50172a3cf0fSKristof Provost const char * const pf_scounters[FCNT_MAX+1] = FCNT_NAMES; 5023b3a8eb9SGleb Smirnoff 5033b3a8eb9SGleb Smirnoff void 50480078d9dSKristof Provost print_status(struct pfctl_status *s, struct pfctl_syncookies *cookies, int opts) 5053b3a8eb9SGleb Smirnoff { 50680078d9dSKristof Provost struct pfctl_status_counter *c; 5073b3a8eb9SGleb Smirnoff char statline[80], *running; 5083b3a8eb9SGleb Smirnoff time_t runtime; 5093b3a8eb9SGleb Smirnoff int i; 5103b3a8eb9SGleb Smirnoff char buf[PF_MD5_DIGEST_LENGTH * 2 + 1]; 5113b3a8eb9SGleb Smirnoff static const char hex[] = "0123456789abcdef"; 5123b3a8eb9SGleb Smirnoff 5133b3a8eb9SGleb Smirnoff runtime = time(NULL) - s->since; 5143b3a8eb9SGleb Smirnoff running = s->running ? "Enabled" : "Disabled"; 5153b3a8eb9SGleb Smirnoff 5163b3a8eb9SGleb Smirnoff if (s->since) { 5173b3a8eb9SGleb Smirnoff unsigned int sec, min, hrs, day = runtime; 5183b3a8eb9SGleb Smirnoff 5193b3a8eb9SGleb Smirnoff sec = day % 60; 5203b3a8eb9SGleb Smirnoff day /= 60; 5213b3a8eb9SGleb Smirnoff min = day % 60; 5223b3a8eb9SGleb Smirnoff day /= 60; 5233b3a8eb9SGleb Smirnoff hrs = day % 24; 5243b3a8eb9SGleb Smirnoff day /= 24; 5253b3a8eb9SGleb Smirnoff snprintf(statline, sizeof(statline), 5263b3a8eb9SGleb Smirnoff "Status: %s for %u days %.2u:%.2u:%.2u", 5273b3a8eb9SGleb Smirnoff running, day, hrs, min, sec); 5283b3a8eb9SGleb Smirnoff } else 5293b3a8eb9SGleb Smirnoff snprintf(statline, sizeof(statline), "Status: %s", running); 5303b3a8eb9SGleb Smirnoff printf("%-44s", statline); 5313b3a8eb9SGleb Smirnoff switch (s->debug) { 5323b3a8eb9SGleb Smirnoff case PF_DEBUG_NONE: 5333b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: None"); 5343b3a8eb9SGleb Smirnoff break; 5353b3a8eb9SGleb Smirnoff case PF_DEBUG_URGENT: 5363b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Urgent"); 5373b3a8eb9SGleb Smirnoff break; 5383b3a8eb9SGleb Smirnoff case PF_DEBUG_MISC: 5393b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Misc"); 5403b3a8eb9SGleb Smirnoff break; 5413b3a8eb9SGleb Smirnoff case PF_DEBUG_NOISY: 5423b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Loud"); 5433b3a8eb9SGleb Smirnoff break; 5443b3a8eb9SGleb Smirnoff } 5453b3a8eb9SGleb Smirnoff 5463b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 547735748f3SKristof Provost printf("Hostid: 0x%08x\n", s->hostid); 5483b3a8eb9SGleb Smirnoff 5493b3a8eb9SGleb Smirnoff for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) { 5503b3a8eb9SGleb Smirnoff buf[i + i] = hex[s->pf_chksum[i] >> 4]; 5513b3a8eb9SGleb Smirnoff buf[i + i + 1] = hex[s->pf_chksum[i] & 0x0f]; 5523b3a8eb9SGleb Smirnoff } 5533b3a8eb9SGleb Smirnoff buf[i + i] = '\0'; 5543b3a8eb9SGleb Smirnoff printf("Checksum: 0x%s\n\n", buf); 5553b3a8eb9SGleb Smirnoff } 5563b3a8eb9SGleb Smirnoff 5573b3a8eb9SGleb Smirnoff if (s->ifname[0] != 0) { 5583b3a8eb9SGleb Smirnoff printf("Interface Stats for %-16s %5s %16s\n", 5593b3a8eb9SGleb Smirnoff s->ifname, "IPv4", "IPv6"); 5603b3a8eb9SGleb Smirnoff printf(" %-25s %14llu %16llu\n", "Bytes In", 5613b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[0][0], 5623b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[1][0]); 5633b3a8eb9SGleb Smirnoff printf(" %-25s %14llu %16llu\n", "Bytes Out", 5643b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[0][1], 5653b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[1][1]); 5663b3a8eb9SGleb Smirnoff printf(" Packets In\n"); 5673b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Passed", 5683b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][0][PF_PASS], 5693b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][0][PF_PASS]); 5703b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Blocked", 5713b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][0][PF_DROP], 5723b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][0][PF_DROP]); 5733b3a8eb9SGleb Smirnoff printf(" Packets Out\n"); 5743b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Passed", 5753b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][1][PF_PASS], 5763b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][1][PF_PASS]); 5773b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n\n", "Blocked", 5783b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][1][PF_DROP], 5793b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][1][PF_DROP]); 5803b3a8eb9SGleb Smirnoff } 5813b3a8eb9SGleb Smirnoff printf("%-27s %14s %16s\n", "State Table", "Total", "Rate"); 582846a6e8fSKristof Provost printf(" %-25s %14ju %14s\n", "current entries", s->states, ""); 58380078d9dSKristof Provost TAILQ_FOREACH(c, &s->fcounters, entry) { 584846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 5853b3a8eb9SGleb Smirnoff if (runtime > 0) 5863b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 58780078d9dSKristof Provost (double)c->counter / (double)runtime); 5883b3a8eb9SGleb Smirnoff else 5893b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 5903b3a8eb9SGleb Smirnoff } 5913b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 5923b3a8eb9SGleb Smirnoff printf("Source Tracking Table\n"); 593846a6e8fSKristof Provost printf(" %-25s %14ju %14s\n", "current entries", 5943b3a8eb9SGleb Smirnoff s->src_nodes, ""); 59580078d9dSKristof Provost TAILQ_FOREACH(c, &s->scounters, entry) { 596846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 5973b3a8eb9SGleb Smirnoff if (runtime > 0) 5983b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 59980078d9dSKristof Provost (double)c->counter / (double)runtime); 6003b3a8eb9SGleb Smirnoff else 6013b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6023b3a8eb9SGleb Smirnoff } 6033b3a8eb9SGleb Smirnoff } 6043b3a8eb9SGleb Smirnoff printf("Counters\n"); 60580078d9dSKristof Provost TAILQ_FOREACH(c, &s->counters, entry) { 606846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 6073b3a8eb9SGleb Smirnoff if (runtime > 0) 6083b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 60980078d9dSKristof Provost (double)c->counter / (double)runtime); 6103b3a8eb9SGleb Smirnoff else 6113b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6123b3a8eb9SGleb Smirnoff } 6133b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 6143b3a8eb9SGleb Smirnoff printf("Limit Counters\n"); 61580078d9dSKristof Provost TAILQ_FOREACH(c, &s->lcounters, entry) { 616846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 6173b3a8eb9SGleb Smirnoff if (runtime > 0) 6183b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 61980078d9dSKristof Provost (double)c->counter / (double)runtime); 6203b3a8eb9SGleb Smirnoff else 6213b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6223b3a8eb9SGleb Smirnoff } 623c69121c4SKristof Provost 624c69121c4SKristof Provost printf("Syncookies\n"); 6255062afffSKristof Provost assert(cookies->mode <= PFCTL_SYNCOOKIES_ADAPTIVE); 626c69121c4SKristof Provost printf(" %-25s %s\n", "mode", 6275062afffSKristof Provost PFCTL_SYNCOOKIES_MODE_NAMES[cookies->mode]); 628444a77caSKristof Provost printf(" %-25s %s\n", "active", 629444a77caSKristof Provost s->syncookies_active ? "active" : "inactive"); 630a6173e94SKristof Provost if (opts & PF_OPT_VERBOSE2) { 631a6173e94SKristof Provost printf(" %-25s %d %%\n", "highwater", cookies->highwater); 632a6173e94SKristof Provost printf(" %-25s %d %%\n", "lowwater", cookies->lowwater); 633a6173e94SKristof Provost printf(" %-25s %d\n", "halfopen states", cookies->halfopen_states); 634a6173e94SKristof Provost } 63539282ef3SKajetan Staszkiewicz printf("Reassemble %24s %s\n", 63639282ef3SKajetan Staszkiewicz s->reass & PF_REASS_ENABLED ? "yes" : "no", 63739282ef3SKajetan Staszkiewicz s->reass & PF_REASS_NODF ? "no-df" : "" 63839282ef3SKajetan Staszkiewicz ); 6393b3a8eb9SGleb Smirnoff } 6403b3a8eb9SGleb Smirnoff } 6413b3a8eb9SGleb Smirnoff 6423b3a8eb9SGleb Smirnoff void 64380078d9dSKristof Provost print_running(struct pfctl_status *status) 644fa1d4439SKristof Provost { 645fa1d4439SKristof Provost printf("%s\n", status->running ? "Enabled" : "Disabled"); 646fa1d4439SKristof Provost } 647fa1d4439SKristof Provost 648fa1d4439SKristof Provost void 6493b3a8eb9SGleb Smirnoff print_src_node(struct pf_src_node *sn, int opts) 6503b3a8eb9SGleb Smirnoff { 6513b3a8eb9SGleb Smirnoff struct pf_addr_wrap aw; 6523b3a8eb9SGleb Smirnoff int min, sec; 6533b3a8eb9SGleb Smirnoff 6543b3a8eb9SGleb Smirnoff memset(&aw, 0, sizeof(aw)); 6553b3a8eb9SGleb Smirnoff if (sn->af == AF_INET) 6563b3a8eb9SGleb Smirnoff aw.v.a.mask.addr32[0] = 0xffffffff; 6573b3a8eb9SGleb Smirnoff else 6583b3a8eb9SGleb Smirnoff memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask)); 6593b3a8eb9SGleb Smirnoff 6603b3a8eb9SGleb Smirnoff aw.v.a.addr = sn->addr; 6613b3a8eb9SGleb Smirnoff print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); 6623b3a8eb9SGleb Smirnoff printf(" -> "); 6633b3a8eb9SGleb Smirnoff aw.v.a.addr = sn->raddr; 6643b3a8eb9SGleb Smirnoff print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); 6653b3a8eb9SGleb Smirnoff printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states, 6663b3a8eb9SGleb Smirnoff sn->conn, sn->conn_rate.count / 1000, 6673b3a8eb9SGleb Smirnoff (sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds); 6683b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 6693b3a8eb9SGleb Smirnoff sec = sn->creation % 60; 6703b3a8eb9SGleb Smirnoff sn->creation /= 60; 6713b3a8eb9SGleb Smirnoff min = sn->creation % 60; 6723b3a8eb9SGleb Smirnoff sn->creation /= 60; 6733b3a8eb9SGleb Smirnoff printf(" age %.2u:%.2u:%.2u", sn->creation, min, sec); 6743b3a8eb9SGleb Smirnoff if (sn->states == 0) { 6753b3a8eb9SGleb Smirnoff sec = sn->expire % 60; 6763b3a8eb9SGleb Smirnoff sn->expire /= 60; 6773b3a8eb9SGleb Smirnoff min = sn->expire % 60; 6783b3a8eb9SGleb Smirnoff sn->expire /= 60; 6793b3a8eb9SGleb Smirnoff printf(", expires in %.2u:%.2u:%.2u", 6803b3a8eb9SGleb Smirnoff sn->expire, min, sec); 6813b3a8eb9SGleb Smirnoff } 6823b3a8eb9SGleb Smirnoff printf(", %llu pkts, %llu bytes", 6833b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 6843b3a8eb9SGleb Smirnoff (unsigned long long)(sn->packets[0] + sn->packets[1]), 6853b3a8eb9SGleb Smirnoff (unsigned long long)(sn->bytes[0] + sn->bytes[1])); 6863b3a8eb9SGleb Smirnoff #else 6873b3a8eb9SGleb Smirnoff sn->packets[0] + sn->packets[1], 6883b3a8eb9SGleb Smirnoff sn->bytes[0] + sn->bytes[1]); 6893b3a8eb9SGleb Smirnoff #endif 6903b3a8eb9SGleb Smirnoff switch (sn->ruletype) { 6913b3a8eb9SGleb Smirnoff case PF_NAT: 6923b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 6933b3a8eb9SGleb Smirnoff printf(", nat rule %u", sn->rule.nr); 6943b3a8eb9SGleb Smirnoff break; 6953b3a8eb9SGleb Smirnoff case PF_RDR: 6963b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 6973b3a8eb9SGleb Smirnoff printf(", rdr rule %u", sn->rule.nr); 6983b3a8eb9SGleb Smirnoff break; 6993b3a8eb9SGleb Smirnoff case PF_PASS: 70039282ef3SKajetan Staszkiewicz case PF_MATCH: 7013b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 7023b3a8eb9SGleb Smirnoff printf(", filter rule %u", sn->rule.nr); 7033b3a8eb9SGleb Smirnoff break; 7043b3a8eb9SGleb Smirnoff } 7053b3a8eb9SGleb Smirnoff printf("\n"); 7063b3a8eb9SGleb Smirnoff } 7073b3a8eb9SGleb Smirnoff } 7083b3a8eb9SGleb Smirnoff 7092b29ceb8SKristof Provost static void 7102b29ceb8SKristof Provost print_eth_addr(const struct pfctl_eth_addr *a) 7112b29ceb8SKristof Provost { 712b590f17aSKristof Provost int i, masklen = ETHER_ADDR_LEN * 8; 713b590f17aSKristof Provost bool seen_unset = false; 714b590f17aSKristof Provost 715c696d5c7SKristof Provost for (i = 0; i < ETHER_ADDR_LEN; i++) { 716c696d5c7SKristof Provost if (a->addr[i] != 0) 717c696d5c7SKristof Provost break; 718c696d5c7SKristof Provost } 719c696d5c7SKristof Provost 720c696d5c7SKristof Provost /* Unset, so don't print anything. */ 721c696d5c7SKristof Provost if (i == ETHER_ADDR_LEN) 722c696d5c7SKristof Provost return; 723c696d5c7SKristof Provost 7242b29ceb8SKristof Provost printf("%s%02x:%02x:%02x:%02x:%02x:%02x", a->neg ? "! " : "", 7252b29ceb8SKristof Provost a->addr[0], a->addr[1], a->addr[2], a->addr[3], a->addr[4], 7262b29ceb8SKristof Provost a->addr[5]); 727b590f17aSKristof Provost 728b590f17aSKristof Provost for (i = 0; i < (ETHER_ADDR_LEN * 8); i++) { 729b590f17aSKristof Provost bool isset = a->mask[i / 8] & (1 << i % 8); 730b590f17aSKristof Provost 731b590f17aSKristof Provost if (! seen_unset) { 732b590f17aSKristof Provost if (isset) 733b590f17aSKristof Provost continue; 734b590f17aSKristof Provost seen_unset = true; 735b590f17aSKristof Provost masklen = i; 736b590f17aSKristof Provost } else { 737b590f17aSKristof Provost /* Not actually a continuous mask, so print the whole 738b590f17aSKristof Provost * thing. */ 739b590f17aSKristof Provost if (isset) 740b590f17aSKristof Provost break; 741b590f17aSKristof Provost continue; 742b590f17aSKristof Provost } 743b590f17aSKristof Provost } 744b590f17aSKristof Provost 745b590f17aSKristof Provost if (masklen == (ETHER_ADDR_LEN * 8)) 746b590f17aSKristof Provost return; 747b590f17aSKristof Provost 748b590f17aSKristof Provost if (i == (ETHER_ADDR_LEN * 8)) { 749b590f17aSKristof Provost printf("/%d", masklen); 750b590f17aSKristof Provost return; 751b590f17aSKristof Provost } 752b590f17aSKristof Provost 753b590f17aSKristof Provost printf("&%02x:%02x:%02x:%02x:%02x:%02x", 754b590f17aSKristof Provost a->mask[0], a->mask[1], a->mask[2], a->mask[3], a->mask[4], 755b590f17aSKristof Provost a->mask[5]); 7562b29ceb8SKristof Provost } 7572b29ceb8SKristof Provost 7582b29ceb8SKristof Provost void 759c5131afeSKristof Provost print_eth_rule(struct pfctl_eth_rule *r, const char *anchor_call, 760c5131afeSKristof Provost int rule_numbers) 7612b29ceb8SKristof Provost { 762d27c9f5bSKristof Provost static const char *actiontypes[] = { "pass", "block", "", "", "", "", 763d27c9f5bSKristof Provost "", "", "", "", "", "", "match" }; 7642b29ceb8SKristof Provost 765ef661d4aSChristian McDonald int i; 766ef661d4aSChristian McDonald 7672b29ceb8SKristof Provost if (rule_numbers) 7682b29ceb8SKristof Provost printf("@%u ", r->nr); 7692b29ceb8SKristof Provost 770c5131afeSKristof Provost printf("ether "); 771c5131afeSKristof Provost if (anchor_call[0]) { 772c5131afeSKristof Provost if (anchor_call[0] == '_') { 773c5131afeSKristof Provost printf("anchor"); 774c5131afeSKristof Provost } else 775c5131afeSKristof Provost printf("anchor \"%s\"", anchor_call); 776c5131afeSKristof Provost } else { 777c5131afeSKristof Provost printf("%s", actiontypes[r->action]); 778c5131afeSKristof Provost } 7792b29ceb8SKristof Provost if (r->direction == PF_IN) 7802b29ceb8SKristof Provost printf(" in"); 7812b29ceb8SKristof Provost else if (r->direction == PF_OUT) 7822b29ceb8SKristof Provost printf(" out"); 7832b29ceb8SKristof Provost 7842b29ceb8SKristof Provost if (r->quick) 7852b29ceb8SKristof Provost printf(" quick"); 7862b29ceb8SKristof Provost if (r->ifname[0]) { 7872b29ceb8SKristof Provost if (r->ifnot) 7882b29ceb8SKristof Provost printf(" on ! %s", r->ifname); 7892b29ceb8SKristof Provost else 7902b29ceb8SKristof Provost printf(" on %s", r->ifname); 7912b29ceb8SKristof Provost } 7928a8af942SKristof Provost if (r->bridge_to[0]) 7938a8af942SKristof Provost printf(" bridge-to %s", r->bridge_to); 7942b29ceb8SKristof Provost if (r->proto) 7952b29ceb8SKristof Provost printf(" proto 0x%04x", r->proto); 7962b29ceb8SKristof Provost 797c696d5c7SKristof Provost if (r->src.isset) { 7982b29ceb8SKristof Provost printf(" from "); 7992b29ceb8SKristof Provost print_eth_addr(&r->src); 800c696d5c7SKristof Provost } 801c696d5c7SKristof Provost if (r->dst.isset) { 8022b29ceb8SKristof Provost printf(" to "); 8032b29ceb8SKristof Provost print_eth_addr(&r->dst); 804c696d5c7SKristof Provost } 8058a42005dSKristof Provost printf(" l3"); 8068a42005dSKristof Provost print_fromto(&r->ipsrc, PF_OSFP_ANY, &r->ipdst, 8078a42005dSKristof Provost r->proto == ETHERTYPE_IP ? AF_INET : AF_INET6, 0, 8088a42005dSKristof Provost 0, 0); 809ef661d4aSChristian McDonald 810ef661d4aSChristian McDonald i = 0; 811ef661d4aSChristian McDonald while (r->label[i][0]) 812ef661d4aSChristian McDonald printf(" label \"%s\"", r->label[i++]); 813ef661d4aSChristian McDonald if (r->ridentifier) 814ef661d4aSChristian McDonald printf(" ridentifier %u", r->ridentifier); 815ef661d4aSChristian McDonald 8162b29ceb8SKristof Provost if (r->qname[0]) 8172b29ceb8SKristof Provost printf(" queue %s", r->qname); 8182b29ceb8SKristof Provost if (r->tagname[0]) 8192b29ceb8SKristof Provost printf(" tag %s", r->tagname); 8201f61367fSKristof Provost if (r->match_tagname[0]) { 8211f61367fSKristof Provost if (r->match_tag_not) 8221f61367fSKristof Provost printf(" !"); 8231f61367fSKristof Provost printf(" tagged %s", r->match_tagname); 8241f61367fSKristof Provost } 825fb330f39SKristof Provost if (r->dnpipe) 826fb330f39SKristof Provost printf(" %s %d", 827fb330f39SKristof Provost r->dnflags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", 828fb330f39SKristof Provost r->dnpipe); 8292b29ceb8SKristof Provost } 8302b29ceb8SKristof Provost 8313b3a8eb9SGleb Smirnoff void 832e9eb0941SKristof Provost print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numeric) 8333b3a8eb9SGleb Smirnoff { 8343b3a8eb9SGleb Smirnoff static const char *actiontypes[] = { "pass", "block", "scrub", 83539282ef3SKajetan Staszkiewicz "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr", 83639282ef3SKajetan Staszkiewicz "", "", "match"}; 8373b3a8eb9SGleb Smirnoff static const char *anchortypes[] = { "anchor", "anchor", "anchor", 8383b3a8eb9SGleb Smirnoff "anchor", "nat-anchor", "nat-anchor", "binat-anchor", 8393b3a8eb9SGleb Smirnoff "binat-anchor", "rdr-anchor", "rdr-anchor" }; 8403b3a8eb9SGleb Smirnoff int i, opts; 841585a5ed0SKristof Provost char *p; 8423b3a8eb9SGleb Smirnoff 8433b3a8eb9SGleb Smirnoff if (verbose) 8443b3a8eb9SGleb Smirnoff printf("@%d ", r->nr); 845ef950daaSKristof Provost if (r->action == PF_MATCH) 846ef950daaSKristof Provost printf("match"); 847ef950daaSKristof Provost else if (r->action > PF_NORDR) 8483b3a8eb9SGleb Smirnoff printf("action(%d)", r->action); 8493b3a8eb9SGleb Smirnoff else if (anchor_call[0]) { 850585a5ed0SKristof Provost p = strrchr(anchor_call, '/'); 851585a5ed0SKristof Provost if (p ? p[1] == '_' : anchor_call[0] == '_') 8523b3a8eb9SGleb Smirnoff printf("%s", anchortypes[r->action]); 853585a5ed0SKristof Provost else 8543b3a8eb9SGleb Smirnoff printf("%s \"%s\"", anchortypes[r->action], 8553b3a8eb9SGleb Smirnoff anchor_call); 8563b3a8eb9SGleb Smirnoff } else { 8573b3a8eb9SGleb Smirnoff printf("%s", actiontypes[r->action]); 8583b3a8eb9SGleb Smirnoff if (r->natpass) 8593b3a8eb9SGleb Smirnoff printf(" pass"); 8603b3a8eb9SGleb Smirnoff } 8613b3a8eb9SGleb Smirnoff if (r->action == PF_DROP) { 8623b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RETURN) 8633b3a8eb9SGleb Smirnoff printf(" return"); 8643b3a8eb9SGleb Smirnoff else if (r->rule_flag & PFRULE_RETURNRST) { 8653b3a8eb9SGleb Smirnoff if (!r->return_ttl) 8663b3a8eb9SGleb Smirnoff printf(" return-rst"); 8673b3a8eb9SGleb Smirnoff else 8683b3a8eb9SGleb Smirnoff printf(" return-rst(ttl %d)", r->return_ttl); 8693b3a8eb9SGleb Smirnoff } else if (r->rule_flag & PFRULE_RETURNICMP) { 8703b3a8eb9SGleb Smirnoff const struct icmpcodeent *ic, *ic6; 8713b3a8eb9SGleb Smirnoff 8723b3a8eb9SGleb Smirnoff ic = geticmpcodebynumber(r->return_icmp >> 8, 8733b3a8eb9SGleb Smirnoff r->return_icmp & 255, AF_INET); 8743b3a8eb9SGleb Smirnoff ic6 = geticmpcodebynumber(r->return_icmp6 >> 8, 8753b3a8eb9SGleb Smirnoff r->return_icmp6 & 255, AF_INET6); 8763b3a8eb9SGleb Smirnoff 8773b3a8eb9SGleb Smirnoff switch (r->af) { 8783b3a8eb9SGleb Smirnoff case AF_INET: 8793b3a8eb9SGleb Smirnoff printf(" return-icmp"); 8803b3a8eb9SGleb Smirnoff if (ic == NULL) 8813b3a8eb9SGleb Smirnoff printf("(%u)", r->return_icmp & 255); 8823b3a8eb9SGleb Smirnoff else 8833b3a8eb9SGleb Smirnoff printf("(%s)", ic->name); 8843b3a8eb9SGleb Smirnoff break; 8853b3a8eb9SGleb Smirnoff case AF_INET6: 8863b3a8eb9SGleb Smirnoff printf(" return-icmp6"); 8873b3a8eb9SGleb Smirnoff if (ic6 == NULL) 8883b3a8eb9SGleb Smirnoff printf("(%u)", r->return_icmp6 & 255); 8893b3a8eb9SGleb Smirnoff else 8903b3a8eb9SGleb Smirnoff printf("(%s)", ic6->name); 8913b3a8eb9SGleb Smirnoff break; 8923b3a8eb9SGleb Smirnoff default: 8933b3a8eb9SGleb Smirnoff printf(" return-icmp"); 8943b3a8eb9SGleb Smirnoff if (ic == NULL) 8953b3a8eb9SGleb Smirnoff printf("(%u, ", r->return_icmp & 255); 8963b3a8eb9SGleb Smirnoff else 8973b3a8eb9SGleb Smirnoff printf("(%s, ", ic->name); 8983b3a8eb9SGleb Smirnoff if (ic6 == NULL) 8993b3a8eb9SGleb Smirnoff printf("%u)", r->return_icmp6 & 255); 9003b3a8eb9SGleb Smirnoff else 9013b3a8eb9SGleb Smirnoff printf("%s)", ic6->name); 9023b3a8eb9SGleb Smirnoff break; 9033b3a8eb9SGleb Smirnoff } 9043b3a8eb9SGleb Smirnoff } else 9053b3a8eb9SGleb Smirnoff printf(" drop"); 9063b3a8eb9SGleb Smirnoff } 9073b3a8eb9SGleb Smirnoff if (r->direction == PF_IN) 9083b3a8eb9SGleb Smirnoff printf(" in"); 9093b3a8eb9SGleb Smirnoff else if (r->direction == PF_OUT) 9103b3a8eb9SGleb Smirnoff printf(" out"); 9113b3a8eb9SGleb Smirnoff if (r->log) { 9123b3a8eb9SGleb Smirnoff printf(" log"); 9133b3a8eb9SGleb Smirnoff if (r->log & ~PF_LOG || r->logif) { 9143b3a8eb9SGleb Smirnoff int count = 0; 9153b3a8eb9SGleb Smirnoff 9163b3a8eb9SGleb Smirnoff printf(" ("); 9173b3a8eb9SGleb Smirnoff if (r->log & PF_LOG_ALL) 9183b3a8eb9SGleb Smirnoff printf("%sall", count++ ? ", " : ""); 9193b3a8eb9SGleb Smirnoff if (r->log & PF_LOG_SOCKET_LOOKUP) 9203b3a8eb9SGleb Smirnoff printf("%suser", count++ ? ", " : ""); 9213b3a8eb9SGleb Smirnoff if (r->logif) 9223b3a8eb9SGleb Smirnoff printf("%sto pflog%u", count++ ? ", " : "", 9233b3a8eb9SGleb Smirnoff r->logif); 9243b3a8eb9SGleb Smirnoff printf(")"); 9253b3a8eb9SGleb Smirnoff } 9263b3a8eb9SGleb Smirnoff } 9273b3a8eb9SGleb Smirnoff if (r->quick) 9283b3a8eb9SGleb Smirnoff printf(" quick"); 9293b3a8eb9SGleb Smirnoff if (r->ifname[0]) { 9303b3a8eb9SGleb Smirnoff if (r->ifnot) 9313b3a8eb9SGleb Smirnoff printf(" on ! %s", r->ifname); 9323b3a8eb9SGleb Smirnoff else 9333b3a8eb9SGleb Smirnoff printf(" on %s", r->ifname); 9343b3a8eb9SGleb Smirnoff } 9353b3a8eb9SGleb Smirnoff if (r->rt) { 9363b3a8eb9SGleb Smirnoff if (r->rt == PF_ROUTETO) 9373b3a8eb9SGleb Smirnoff printf(" route-to"); 9383b3a8eb9SGleb Smirnoff else if (r->rt == PF_REPLYTO) 9393b3a8eb9SGleb Smirnoff printf(" reply-to"); 9403b3a8eb9SGleb Smirnoff else if (r->rt == PF_DUPTO) 9413b3a8eb9SGleb Smirnoff printf(" dup-to"); 9423b3a8eb9SGleb Smirnoff printf(" "); 9433b3a8eb9SGleb Smirnoff print_pool(&r->rpool, 0, 0, r->af, PF_PASS); 9443b3a8eb9SGleb Smirnoff } 9453b3a8eb9SGleb Smirnoff if (r->af) { 9463b3a8eb9SGleb Smirnoff if (r->af == AF_INET) 9473b3a8eb9SGleb Smirnoff printf(" inet"); 9483b3a8eb9SGleb Smirnoff else 9493b3a8eb9SGleb Smirnoff printf(" inet6"); 9503b3a8eb9SGleb Smirnoff } 9513b3a8eb9SGleb Smirnoff if (r->proto) { 952858937beSMateusz Guzik const char *protoname; 9533b3a8eb9SGleb Smirnoff 954858937beSMateusz Guzik if ((protoname = pfctl_proto2name(r->proto)) != NULL) 955858937beSMateusz Guzik printf(" proto %s", protoname); 9563b3a8eb9SGleb Smirnoff else 9573b3a8eb9SGleb Smirnoff printf(" proto %u", r->proto); 9583b3a8eb9SGleb Smirnoff } 9593b3a8eb9SGleb Smirnoff print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto, 9603b3a8eb9SGleb Smirnoff verbose, numeric); 9613b3a8eb9SGleb Smirnoff if (r->uid.op) 9623b3a8eb9SGleb Smirnoff print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user", 9633b3a8eb9SGleb Smirnoff UID_MAX); 9643b3a8eb9SGleb Smirnoff if (r->gid.op) 9653b3a8eb9SGleb Smirnoff print_ugid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group", 9663b3a8eb9SGleb Smirnoff GID_MAX); 9673b3a8eb9SGleb Smirnoff if (r->flags || r->flagset) { 9683b3a8eb9SGleb Smirnoff printf(" flags "); 9693b3a8eb9SGleb Smirnoff print_flags(r->flags); 9703b3a8eb9SGleb Smirnoff printf("/"); 9713b3a8eb9SGleb Smirnoff print_flags(r->flagset); 97239282ef3SKajetan Staszkiewicz } else if ((r->action == PF_PASS || r->action == PF_MATCH) && 9733b3a8eb9SGleb Smirnoff (!r->proto || r->proto == IPPROTO_TCP) && 9743b3a8eb9SGleb Smirnoff !(r->rule_flag & PFRULE_FRAGMENT) && 9753b3a8eb9SGleb Smirnoff !anchor_call[0] && r->keep_state) 9763b3a8eb9SGleb Smirnoff printf(" flags any"); 9773b3a8eb9SGleb Smirnoff if (r->type) { 9783b3a8eb9SGleb Smirnoff const struct icmptypeent *it; 9793b3a8eb9SGleb Smirnoff 9803b3a8eb9SGleb Smirnoff it = geticmptypebynumber(r->type-1, r->af); 9813b3a8eb9SGleb Smirnoff if (r->af != AF_INET6) 9823b3a8eb9SGleb Smirnoff printf(" icmp-type"); 9833b3a8eb9SGleb Smirnoff else 9843b3a8eb9SGleb Smirnoff printf(" icmp6-type"); 9853b3a8eb9SGleb Smirnoff if (it != NULL) 9863b3a8eb9SGleb Smirnoff printf(" %s", it->name); 9873b3a8eb9SGleb Smirnoff else 9883b3a8eb9SGleb Smirnoff printf(" %u", r->type-1); 9893b3a8eb9SGleb Smirnoff if (r->code) { 9903b3a8eb9SGleb Smirnoff const struct icmpcodeent *ic; 9913b3a8eb9SGleb Smirnoff 9923b3a8eb9SGleb Smirnoff ic = geticmpcodebynumber(r->type-1, r->code-1, r->af); 9933b3a8eb9SGleb Smirnoff if (ic != NULL) 9943b3a8eb9SGleb Smirnoff printf(" code %s", ic->name); 9953b3a8eb9SGleb Smirnoff else 9963b3a8eb9SGleb Smirnoff printf(" code %u", r->code-1); 9973b3a8eb9SGleb Smirnoff } 9983b3a8eb9SGleb Smirnoff } 9993b3a8eb9SGleb Smirnoff if (r->tos) 10003b3a8eb9SGleb Smirnoff printf(" tos 0x%2.2x", r->tos); 10013e248e0fSKristof Provost if (r->prio) 10023e248e0fSKristof Provost printf(" prio %u", r->prio == PF_PRIO_ZERO ? 0 : r->prio); 10033e248e0fSKristof Provost if (r->scrub_flags & PFSTATE_SETMASK) { 10043e248e0fSKristof Provost char *comma = ""; 10053e248e0fSKristof Provost printf(" set ("); 10063e248e0fSKristof Provost if (r->scrub_flags & PFSTATE_SETPRIO) { 10073e248e0fSKristof Provost if (r->set_prio[0] == r->set_prio[1]) 10083e248e0fSKristof Provost printf("%s prio %u", comma, r->set_prio[0]); 10093e248e0fSKristof Provost else 10103e248e0fSKristof Provost printf("%s prio(%u, %u)", comma, r->set_prio[0], 10113e248e0fSKristof Provost r->set_prio[1]); 10123e248e0fSKristof Provost comma = ","; 10133e248e0fSKristof Provost } 101439282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_SETTOS) { 101539282ef3SKajetan Staszkiewicz printf("%s tos 0x%2.2x", comma, r->set_tos); 101639282ef3SKajetan Staszkiewicz comma = ","; 101739282ef3SKajetan Staszkiewicz } 10183e248e0fSKristof Provost printf(" )"); 10193e248e0fSKristof Provost } 10203b3a8eb9SGleb Smirnoff if (!r->keep_state && r->action == PF_PASS && !anchor_call[0]) 10213b3a8eb9SGleb Smirnoff printf(" no state"); 10223b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_NORMAL) 10233b3a8eb9SGleb Smirnoff printf(" keep state"); 10243b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_MODULATE) 10253b3a8eb9SGleb Smirnoff printf(" modulate state"); 10263b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_SYNPROXY) 10273b3a8eb9SGleb Smirnoff printf(" synproxy state"); 10283b3a8eb9SGleb Smirnoff if (r->prob) { 10293b3a8eb9SGleb Smirnoff char buf[20]; 10303b3a8eb9SGleb Smirnoff 10313b3a8eb9SGleb Smirnoff snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0)); 10323b3a8eb9SGleb Smirnoff for (i = strlen(buf)-1; i > 0; i--) { 10333b3a8eb9SGleb Smirnoff if (buf[i] == '0') 10343b3a8eb9SGleb Smirnoff buf[i] = '\0'; 10353b3a8eb9SGleb Smirnoff else { 10363b3a8eb9SGleb Smirnoff if (buf[i] == '.') 10373b3a8eb9SGleb Smirnoff buf[i] = '\0'; 10383b3a8eb9SGleb Smirnoff break; 10393b3a8eb9SGleb Smirnoff } 10403b3a8eb9SGleb Smirnoff } 10413b3a8eb9SGleb Smirnoff printf(" probability %s%%", buf); 10423b3a8eb9SGleb Smirnoff } 10433b3a8eb9SGleb Smirnoff opts = 0; 10443b3a8eb9SGleb Smirnoff if (r->max_states || r->max_src_nodes || r->max_src_states) 10453b3a8eb9SGleb Smirnoff opts = 1; 10463b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NOSYNC) 10473b3a8eb9SGleb Smirnoff opts = 1; 10483b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SRCTRACK) 10493b3a8eb9SGleb Smirnoff opts = 1; 10503b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_IFBOUND) 10513b3a8eb9SGleb Smirnoff opts = 1; 10523b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY) 10533b3a8eb9SGleb Smirnoff opts = 1; 1054*baf9b6d0SKristof Provost if (r->rule_flag & PFRULE_PFLOW) 1055*baf9b6d0SKristof Provost opts = 1; 10563b3a8eb9SGleb Smirnoff for (i = 0; !opts && i < PFTM_MAX; ++i) 10573b3a8eb9SGleb Smirnoff if (r->timeout[i]) 10583b3a8eb9SGleb Smirnoff opts = 1; 10593b3a8eb9SGleb Smirnoff if (opts) { 10603b3a8eb9SGleb Smirnoff printf(" ("); 10613b3a8eb9SGleb Smirnoff if (r->max_states) { 10623b3a8eb9SGleb Smirnoff printf("max %u", r->max_states); 10633b3a8eb9SGleb Smirnoff opts = 0; 10643b3a8eb9SGleb Smirnoff } 10653b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NOSYNC) { 10663b3a8eb9SGleb Smirnoff if (!opts) 10673b3a8eb9SGleb Smirnoff printf(", "); 10683b3a8eb9SGleb Smirnoff printf("no-sync"); 10693b3a8eb9SGleb Smirnoff opts = 0; 10703b3a8eb9SGleb Smirnoff } 10713b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SRCTRACK) { 10723b3a8eb9SGleb Smirnoff if (!opts) 10733b3a8eb9SGleb Smirnoff printf(", "); 10743b3a8eb9SGleb Smirnoff printf("source-track"); 10753b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RULESRCTRACK) 10763b3a8eb9SGleb Smirnoff printf(" rule"); 10773b3a8eb9SGleb Smirnoff else 10783b3a8eb9SGleb Smirnoff printf(" global"); 10793b3a8eb9SGleb Smirnoff opts = 0; 10803b3a8eb9SGleb Smirnoff } 10813b3a8eb9SGleb Smirnoff if (r->max_src_states) { 10823b3a8eb9SGleb Smirnoff if (!opts) 10833b3a8eb9SGleb Smirnoff printf(", "); 10843b3a8eb9SGleb Smirnoff printf("max-src-states %u", r->max_src_states); 10853b3a8eb9SGleb Smirnoff opts = 0; 10863b3a8eb9SGleb Smirnoff } 10873b3a8eb9SGleb Smirnoff if (r->max_src_conn) { 10883b3a8eb9SGleb Smirnoff if (!opts) 10893b3a8eb9SGleb Smirnoff printf(", "); 10903b3a8eb9SGleb Smirnoff printf("max-src-conn %u", r->max_src_conn); 10913b3a8eb9SGleb Smirnoff opts = 0; 10923b3a8eb9SGleb Smirnoff } 10933b3a8eb9SGleb Smirnoff if (r->max_src_conn_rate.limit) { 10943b3a8eb9SGleb Smirnoff if (!opts) 10953b3a8eb9SGleb Smirnoff printf(", "); 10963b3a8eb9SGleb Smirnoff printf("max-src-conn-rate %u/%u", 10973b3a8eb9SGleb Smirnoff r->max_src_conn_rate.limit, 10983b3a8eb9SGleb Smirnoff r->max_src_conn_rate.seconds); 10993b3a8eb9SGleb Smirnoff opts = 0; 11003b3a8eb9SGleb Smirnoff } 11013b3a8eb9SGleb Smirnoff if (r->max_src_nodes) { 11023b3a8eb9SGleb Smirnoff if (!opts) 11033b3a8eb9SGleb Smirnoff printf(", "); 11043b3a8eb9SGleb Smirnoff printf("max-src-nodes %u", r->max_src_nodes); 11053b3a8eb9SGleb Smirnoff opts = 0; 11063b3a8eb9SGleb Smirnoff } 11073b3a8eb9SGleb Smirnoff if (r->overload_tblname[0]) { 11083b3a8eb9SGleb Smirnoff if (!opts) 11093b3a8eb9SGleb Smirnoff printf(", "); 11103b3a8eb9SGleb Smirnoff printf("overload <%s>", r->overload_tblname); 11113b3a8eb9SGleb Smirnoff if (r->flush) 11123b3a8eb9SGleb Smirnoff printf(" flush"); 11133b3a8eb9SGleb Smirnoff if (r->flush & PF_FLUSH_GLOBAL) 11143b3a8eb9SGleb Smirnoff printf(" global"); 11153b3a8eb9SGleb Smirnoff } 11163b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_IFBOUND) { 11173b3a8eb9SGleb Smirnoff if (!opts) 11183b3a8eb9SGleb Smirnoff printf(", "); 11193b3a8eb9SGleb Smirnoff printf("if-bound"); 11203b3a8eb9SGleb Smirnoff opts = 0; 11213b3a8eb9SGleb Smirnoff } 11223b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY) { 11233b3a8eb9SGleb Smirnoff if (!opts) 11243b3a8eb9SGleb Smirnoff printf(", "); 11253b3a8eb9SGleb Smirnoff printf("sloppy"); 11263b3a8eb9SGleb Smirnoff opts = 0; 11273b3a8eb9SGleb Smirnoff } 1128*baf9b6d0SKristof Provost if (r->rule_flag & PFRULE_PFLOW) { 1129*baf9b6d0SKristof Provost if (!opts) 1130*baf9b6d0SKristof Provost printf(", "); 1131*baf9b6d0SKristof Provost printf("pflow"); 1132*baf9b6d0SKristof Provost opts = 0; 1133*baf9b6d0SKristof Provost } 11343b3a8eb9SGleb Smirnoff for (i = 0; i < PFTM_MAX; ++i) 11353b3a8eb9SGleb Smirnoff if (r->timeout[i]) { 11363b3a8eb9SGleb Smirnoff int j; 11373b3a8eb9SGleb Smirnoff 11383b3a8eb9SGleb Smirnoff if (!opts) 11393b3a8eb9SGleb Smirnoff printf(", "); 11403b3a8eb9SGleb Smirnoff opts = 0; 11413b3a8eb9SGleb Smirnoff for (j = 0; pf_timeouts[j].name != NULL; 11423b3a8eb9SGleb Smirnoff ++j) 11433b3a8eb9SGleb Smirnoff if (pf_timeouts[j].timeout == i) 11443b3a8eb9SGleb Smirnoff break; 11453b3a8eb9SGleb Smirnoff printf("%s %u", pf_timeouts[j].name == NULL ? 11463b3a8eb9SGleb Smirnoff "inv.timeout" : pf_timeouts[j].name, 11473b3a8eb9SGleb Smirnoff r->timeout[i]); 11483b3a8eb9SGleb Smirnoff } 11493b3a8eb9SGleb Smirnoff printf(")"); 11503b3a8eb9SGleb Smirnoff } 115139282ef3SKajetan Staszkiewicz if (r->allow_opts) 115239282ef3SKajetan Staszkiewicz printf(" allow-opts"); 11533b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_FRAGMENT) 11543b3a8eb9SGleb Smirnoff printf(" fragment"); 115539282ef3SKajetan Staszkiewicz if (r->action == PF_SCRUB) { 115639282ef3SKajetan Staszkiewicz /* Scrub flags for old-style scrub. */ 11573b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NODF) 11583b3a8eb9SGleb Smirnoff printf(" no-df"); 11593b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RANDOMID) 11603b3a8eb9SGleb Smirnoff printf(" random-id"); 11613b3a8eb9SGleb Smirnoff if (r->min_ttl) 11623b3a8eb9SGleb Smirnoff printf(" min-ttl %d", r->min_ttl); 11633b3a8eb9SGleb Smirnoff if (r->max_mss) 11643b3a8eb9SGleb Smirnoff printf(" max-mss %d", r->max_mss); 11653b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SET_TOS) 11663b3a8eb9SGleb Smirnoff printf(" set-tos 0x%2.2x", r->set_tos); 11673b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_REASSEMBLE_TCP) 11683b3a8eb9SGleb Smirnoff printf(" reassemble tcp"); 116939282ef3SKajetan Staszkiewicz /* The PFRULE_FRAGMENT_NOREASS is set on all rules by default! */ 117057e047e5SKristof Provost printf(" fragment %sreassemble", 117157e047e5SKristof Provost r->rule_flag & PFRULE_FRAGMENT_NOREASS ? "no " : ""); 117239282ef3SKajetan Staszkiewicz } else if (r->scrub_flags & PFSTATE_SCRUBMASK || r->min_ttl || r->max_mss) { 117339282ef3SKajetan Staszkiewicz /* Scrub actions on normal rules. */ 117439282ef3SKajetan Staszkiewicz printf(" scrub("); 117539282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_NODF) 117639282ef3SKajetan Staszkiewicz printf(" no-df"); 117739282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_RANDOMID) 117839282ef3SKajetan Staszkiewicz printf(" random-id"); 117939282ef3SKajetan Staszkiewicz if (r->min_ttl) 118039282ef3SKajetan Staszkiewicz printf(" min-ttl %d", r->min_ttl); 118139282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_SETTOS) 118239282ef3SKajetan Staszkiewicz printf(" set-tos 0x%2.2x", r->set_tos); 118339282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_SCRUB_TCP) 118439282ef3SKajetan Staszkiewicz printf(" reassemble tcp"); 118539282ef3SKajetan Staszkiewicz if (r->max_mss) 118639282ef3SKajetan Staszkiewicz printf(" max-mss %d", r->max_mss); 118739282ef3SKajetan Staszkiewicz printf(")"); 11883b3a8eb9SGleb Smirnoff } 11896fcc8e04SKristof Provost i = 0; 11906fcc8e04SKristof Provost while (r->label[i][0]) 11916fcc8e04SKristof Provost printf(" label \"%s\"", r->label[i++]); 119276c5eeccSKristof Provost if (r->ridentifier) 119376c5eeccSKristof Provost printf(" ridentifier %u", r->ridentifier); 119463b3c1c7SKristof Provost /* Only dnrpipe as we might do (0, 42) to only queue return traffic. */ 119563b3c1c7SKristof Provost if (r->dnrpipe) 119663b3c1c7SKristof Provost printf(" %s(%d, %d)", 119763b3c1c7SKristof Provost r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", 119863b3c1c7SKristof Provost r->dnpipe, r->dnrpipe); 119963b3c1c7SKristof Provost else if (r->dnpipe) 120063b3c1c7SKristof Provost printf(" %s %d", 120163b3c1c7SKristof Provost r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", 120263b3c1c7SKristof Provost r->dnpipe); 12033b3a8eb9SGleb Smirnoff if (r->qname[0] && r->pqname[0]) 12043b3a8eb9SGleb Smirnoff printf(" queue(%s, %s)", r->qname, r->pqname); 12053b3a8eb9SGleb Smirnoff else if (r->qname[0]) 12063b3a8eb9SGleb Smirnoff printf(" queue %s", r->qname); 12073b3a8eb9SGleb Smirnoff if (r->tagname[0]) 12083b3a8eb9SGleb Smirnoff printf(" tag %s", r->tagname); 12093b3a8eb9SGleb Smirnoff if (r->match_tagname[0]) { 12103b3a8eb9SGleb Smirnoff if (r->match_tag_not) 12113b3a8eb9SGleb Smirnoff printf(" !"); 12123b3a8eb9SGleb Smirnoff printf(" tagged %s", r->match_tagname); 12133b3a8eb9SGleb Smirnoff } 12143b3a8eb9SGleb Smirnoff if (r->rtableid != -1) 12153b3a8eb9SGleb Smirnoff printf(" rtable %u", r->rtableid); 12163b3a8eb9SGleb Smirnoff if (r->divert.port) { 12173b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 12183b3a8eb9SGleb Smirnoff printf(" divert-to %u", ntohs(r->divert.port)); 12193b3a8eb9SGleb Smirnoff #else 12203b3a8eb9SGleb Smirnoff if (PF_AZERO(&r->divert.addr, r->af)) { 12213b3a8eb9SGleb Smirnoff printf(" divert-reply"); 12223b3a8eb9SGleb Smirnoff } else { 12233b3a8eb9SGleb Smirnoff /* XXX cut&paste from print_addr */ 12243b3a8eb9SGleb Smirnoff char buf[48]; 12253b3a8eb9SGleb Smirnoff 12263b3a8eb9SGleb Smirnoff printf(" divert-to "); 12273b3a8eb9SGleb Smirnoff if (inet_ntop(r->af, &r->divert.addr, buf, 12283b3a8eb9SGleb Smirnoff sizeof(buf)) == NULL) 12293b3a8eb9SGleb Smirnoff printf("?"); 12303b3a8eb9SGleb Smirnoff else 12313b3a8eb9SGleb Smirnoff printf("%s", buf); 12323b3a8eb9SGleb Smirnoff printf(" port %u", ntohs(r->divert.port)); 12333b3a8eb9SGleb Smirnoff } 12343b3a8eb9SGleb Smirnoff #endif 12353b3a8eb9SGleb Smirnoff } 12363b3a8eb9SGleb Smirnoff if (!anchor_call[0] && (r->action == PF_NAT || 12373b3a8eb9SGleb Smirnoff r->action == PF_BINAT || r->action == PF_RDR)) { 12383b3a8eb9SGleb Smirnoff printf(" -> "); 12393b3a8eb9SGleb Smirnoff print_pool(&r->rpool, r->rpool.proxy_port[0], 12403b3a8eb9SGleb Smirnoff r->rpool.proxy_port[1], r->af, r->action); 12413b3a8eb9SGleb Smirnoff } 12423b3a8eb9SGleb Smirnoff } 12433b3a8eb9SGleb Smirnoff 12443b3a8eb9SGleb Smirnoff void 12453b3a8eb9SGleb Smirnoff print_tabledef(const char *name, int flags, int addrs, 12463b3a8eb9SGleb Smirnoff struct node_tinithead *nodes) 12473b3a8eb9SGleb Smirnoff { 12483b3a8eb9SGleb Smirnoff struct node_tinit *ti, *nti; 12493b3a8eb9SGleb Smirnoff struct node_host *h; 12503b3a8eb9SGleb Smirnoff 12513b3a8eb9SGleb Smirnoff printf("table <%s>", name); 12523b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_CONST) 12533b3a8eb9SGleb Smirnoff printf(" const"); 12543b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_PERSIST) 12553b3a8eb9SGleb Smirnoff printf(" persist"); 12563b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_COUNTERS) 12573b3a8eb9SGleb Smirnoff printf(" counters"); 12583b3a8eb9SGleb Smirnoff SIMPLEQ_FOREACH(ti, nodes, entries) { 12593b3a8eb9SGleb Smirnoff if (ti->file) { 12603b3a8eb9SGleb Smirnoff printf(" file \"%s\"", ti->file); 12613b3a8eb9SGleb Smirnoff continue; 12623b3a8eb9SGleb Smirnoff } 12633b3a8eb9SGleb Smirnoff printf(" {"); 12643b3a8eb9SGleb Smirnoff for (;;) { 12653b3a8eb9SGleb Smirnoff for (h = ti->host; h != NULL; h = h->next) { 12663b3a8eb9SGleb Smirnoff printf(h->not ? " !" : " "); 12673b3a8eb9SGleb Smirnoff print_addr(&h->addr, h->af, 0); 12683b3a8eb9SGleb Smirnoff } 12693b3a8eb9SGleb Smirnoff nti = SIMPLEQ_NEXT(ti, entries); 12703b3a8eb9SGleb Smirnoff if (nti != NULL && nti->file == NULL) 12713b3a8eb9SGleb Smirnoff ti = nti; /* merge lists */ 12723b3a8eb9SGleb Smirnoff else 12733b3a8eb9SGleb Smirnoff break; 12743b3a8eb9SGleb Smirnoff } 12753b3a8eb9SGleb Smirnoff printf(" }"); 12763b3a8eb9SGleb Smirnoff } 12773b3a8eb9SGleb Smirnoff if (addrs && SIMPLEQ_EMPTY(nodes)) 12783b3a8eb9SGleb Smirnoff printf(" { }"); 12793b3a8eb9SGleb Smirnoff printf("\n"); 12803b3a8eb9SGleb Smirnoff } 12813b3a8eb9SGleb Smirnoff 12823b3a8eb9SGleb Smirnoff int 12833b3a8eb9SGleb Smirnoff parse_flags(char *s) 12843b3a8eb9SGleb Smirnoff { 12853b3a8eb9SGleb Smirnoff char *p, *q; 12863b3a8eb9SGleb Smirnoff u_int8_t f = 0; 12873b3a8eb9SGleb Smirnoff 12883b3a8eb9SGleb Smirnoff for (p = s; *p; p++) { 12893b3a8eb9SGleb Smirnoff if ((q = strchr(tcpflags, *p)) == NULL) 12903b3a8eb9SGleb Smirnoff return -1; 12913b3a8eb9SGleb Smirnoff else 12923b3a8eb9SGleb Smirnoff f |= 1 << (q - tcpflags); 12933b3a8eb9SGleb Smirnoff } 12943b3a8eb9SGleb Smirnoff return (f ? f : PF_TH_ALL); 12953b3a8eb9SGleb Smirnoff } 12963b3a8eb9SGleb Smirnoff 12973b3a8eb9SGleb Smirnoff void 12983b3a8eb9SGleb Smirnoff set_ipmask(struct node_host *h, u_int8_t b) 12993b3a8eb9SGleb Smirnoff { 13003b3a8eb9SGleb Smirnoff struct pf_addr *m, *n; 13013b3a8eb9SGleb Smirnoff int i, j = 0; 13023b3a8eb9SGleb Smirnoff 13033b3a8eb9SGleb Smirnoff m = &h->addr.v.a.mask; 13043b3a8eb9SGleb Smirnoff memset(m, 0, sizeof(*m)); 13053b3a8eb9SGleb Smirnoff 13063b3a8eb9SGleb Smirnoff while (b >= 32) { 13073b3a8eb9SGleb Smirnoff m->addr32[j++] = 0xffffffff; 13083b3a8eb9SGleb Smirnoff b -= 32; 13093b3a8eb9SGleb Smirnoff } 13103b3a8eb9SGleb Smirnoff for (i = 31; i > 31-b; --i) 13113b3a8eb9SGleb Smirnoff m->addr32[j] |= (1 << i); 13123b3a8eb9SGleb Smirnoff if (b) 13133b3a8eb9SGleb Smirnoff m->addr32[j] = htonl(m->addr32[j]); 13143b3a8eb9SGleb Smirnoff 13153b3a8eb9SGleb Smirnoff /* Mask off bits of the address that will never be used. */ 13163b3a8eb9SGleb Smirnoff n = &h->addr.v.a.addr; 13173b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_ADDRMASK) 13183b3a8eb9SGleb Smirnoff for (i = 0; i < 4; i++) 13193b3a8eb9SGleb Smirnoff n->addr32[i] = n->addr32[i] & m->addr32[i]; 13203b3a8eb9SGleb Smirnoff } 13213b3a8eb9SGleb Smirnoff 13223b3a8eb9SGleb Smirnoff int 13233b3a8eb9SGleb Smirnoff check_netmask(struct node_host *h, sa_family_t af) 13243b3a8eb9SGleb Smirnoff { 13253b3a8eb9SGleb Smirnoff struct node_host *n = NULL; 13263b3a8eb9SGleb Smirnoff struct pf_addr *m; 13273b3a8eb9SGleb Smirnoff 13283b3a8eb9SGleb Smirnoff for (n = h; n != NULL; n = n->next) { 13293b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_TABLE) 13303b3a8eb9SGleb Smirnoff continue; 13313b3a8eb9SGleb Smirnoff m = &h->addr.v.a.mask; 13323b3a8eb9SGleb Smirnoff /* netmasks > 32 bit are invalid on v4 */ 13333b3a8eb9SGleb Smirnoff if (af == AF_INET && 13343b3a8eb9SGleb Smirnoff (m->addr32[1] || m->addr32[2] || m->addr32[3])) { 13353b3a8eb9SGleb Smirnoff fprintf(stderr, "netmask %u invalid for IPv4 address\n", 13363b3a8eb9SGleb Smirnoff unmask(m, AF_INET6)); 13373b3a8eb9SGleb Smirnoff return (1); 13383b3a8eb9SGleb Smirnoff } 13393b3a8eb9SGleb Smirnoff } 13403b3a8eb9SGleb Smirnoff return (0); 13413b3a8eb9SGleb Smirnoff } 13423b3a8eb9SGleb Smirnoff 13437ce98cf2SKristof Provost struct node_host * 13447ce98cf2SKristof Provost gen_dynnode(struct node_host *h, sa_family_t af) 13457ce98cf2SKristof Provost { 13467ce98cf2SKristof Provost struct node_host *n; 13477ce98cf2SKristof Provost struct pf_addr *m; 13487ce98cf2SKristof Provost 13497ce98cf2SKristof Provost if (h->addr.type != PF_ADDR_DYNIFTL) 13507ce98cf2SKristof Provost return (NULL); 13517ce98cf2SKristof Provost 13527ce98cf2SKristof Provost if ((n = calloc(1, sizeof(*n))) == NULL) 13537ce98cf2SKristof Provost return (NULL); 13547ce98cf2SKristof Provost bcopy(h, n, sizeof(*n)); 13557ce98cf2SKristof Provost n->ifname = NULL; 13567ce98cf2SKristof Provost n->next = NULL; 13577ce98cf2SKristof Provost n->tail = NULL; 13587ce98cf2SKristof Provost 13597ce98cf2SKristof Provost /* fix up netmask */ 13607ce98cf2SKristof Provost m = &n->addr.v.a.mask; 13617ce98cf2SKristof Provost if (af == AF_INET && unmask(m, AF_INET6) > 32) 13627ce98cf2SKristof Provost set_ipmask(n, 32); 13637ce98cf2SKristof Provost 13647ce98cf2SKristof Provost return (n); 13657ce98cf2SKristof Provost } 13667ce98cf2SKristof Provost 13673b3a8eb9SGleb Smirnoff /* interface lookup routines */ 13683b3a8eb9SGleb Smirnoff 136913cfafabSKristof Provost static struct node_host *iftab; 13703b3a8eb9SGleb Smirnoff 13711d34c9daSPatrick Kelsey /* 13721d34c9daSPatrick Kelsey * Retrieve the list of groups this interface is a member of and make sure 13731d34c9daSPatrick Kelsey * each group is in the group map. 13741d34c9daSPatrick Kelsey */ 13751d34c9daSPatrick Kelsey static void 13761d34c9daSPatrick Kelsey ifa_add_groups_to_map(char *ifa_name) 13771d34c9daSPatrick Kelsey { 13781d34c9daSPatrick Kelsey int s, len; 13791d34c9daSPatrick Kelsey struct ifgroupreq ifgr; 13801d34c9daSPatrick Kelsey struct ifg_req *ifg; 13811d34c9daSPatrick Kelsey 13821d34c9daSPatrick Kelsey s = get_query_socket(); 13831d34c9daSPatrick Kelsey 13841d34c9daSPatrick Kelsey /* Get size of group list for this interface */ 13851d34c9daSPatrick Kelsey memset(&ifgr, 0, sizeof(ifgr)); 13861d34c9daSPatrick Kelsey strlcpy(ifgr.ifgr_name, ifa_name, IFNAMSIZ); 13871d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 13881d34c9daSPatrick Kelsey err(1, "SIOCGIFGROUP"); 13891d34c9daSPatrick Kelsey 13901d34c9daSPatrick Kelsey /* Retrieve group list for this interface */ 13911d34c9daSPatrick Kelsey len = ifgr.ifgr_len; 13921d34c9daSPatrick Kelsey ifgr.ifgr_groups = 13931d34c9daSPatrick Kelsey (struct ifg_req *)calloc(len / sizeof(struct ifg_req), 13941d34c9daSPatrick Kelsey sizeof(struct ifg_req)); 13951d34c9daSPatrick Kelsey if (ifgr.ifgr_groups == NULL) 13961d34c9daSPatrick Kelsey err(1, "calloc"); 13971d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 13981d34c9daSPatrick Kelsey err(1, "SIOCGIFGROUP"); 13991d34c9daSPatrick Kelsey 14001d34c9daSPatrick Kelsey ifg = ifgr.ifgr_groups; 14011d34c9daSPatrick Kelsey for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 14021d34c9daSPatrick Kelsey len -= sizeof(struct ifg_req); 14031d34c9daSPatrick Kelsey if (strcmp(ifg->ifgrq_group, "all")) { 14041d34c9daSPatrick Kelsey ENTRY item; 14051d34c9daSPatrick Kelsey ENTRY *ret_item; 14061d34c9daSPatrick Kelsey int *answer; 14071d34c9daSPatrick Kelsey 14081d34c9daSPatrick Kelsey item.key = ifg->ifgrq_group; 14091d34c9daSPatrick Kelsey if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) { 14101d34c9daSPatrick Kelsey struct ifgroupreq ifgr2; 14111d34c9daSPatrick Kelsey 14121d34c9daSPatrick Kelsey /* Don't know the answer yet */ 14131d34c9daSPatrick Kelsey if ((answer = malloc(sizeof(int))) == NULL) 14141d34c9daSPatrick Kelsey err(1, "malloc"); 14151d34c9daSPatrick Kelsey 14161d34c9daSPatrick Kelsey bzero(&ifgr2, sizeof(ifgr2)); 14171d34c9daSPatrick Kelsey strlcpy(ifgr2.ifgr_name, ifg->ifgrq_group, 14181d34c9daSPatrick Kelsey sizeof(ifgr2.ifgr_name)); 14191d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr2) == 0) 14201d34c9daSPatrick Kelsey *answer = ifgr2.ifgr_len; 14211d34c9daSPatrick Kelsey else 14221d34c9daSPatrick Kelsey *answer = 0; 14231d34c9daSPatrick Kelsey 14241d34c9daSPatrick Kelsey item.key = strdup(ifg->ifgrq_group); 14251d34c9daSPatrick Kelsey item.data = answer; 14261d34c9daSPatrick Kelsey if (hsearch_r(item, ENTER, &ret_item, 14271d34c9daSPatrick Kelsey &isgroup_map) == 0) 14281d34c9daSPatrick Kelsey err(1, "interface group query response" 14291d34c9daSPatrick Kelsey " map insert"); 14301d34c9daSPatrick Kelsey } 14311d34c9daSPatrick Kelsey } 14321d34c9daSPatrick Kelsey } 14331d34c9daSPatrick Kelsey free(ifgr.ifgr_groups); 14341d34c9daSPatrick Kelsey } 14351d34c9daSPatrick Kelsey 14363b3a8eb9SGleb Smirnoff void 14373b3a8eb9SGleb Smirnoff ifa_load(void) 14383b3a8eb9SGleb Smirnoff { 14393b3a8eb9SGleb Smirnoff struct ifaddrs *ifap, *ifa; 14403b3a8eb9SGleb Smirnoff struct node_host *n = NULL, *h = NULL; 14413b3a8eb9SGleb Smirnoff 14423b3a8eb9SGleb Smirnoff if (getifaddrs(&ifap) < 0) 14433b3a8eb9SGleb Smirnoff err(1, "getifaddrs"); 14443b3a8eb9SGleb Smirnoff 14453b3a8eb9SGleb Smirnoff for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 14463b3a8eb9SGleb Smirnoff if (!(ifa->ifa_addr->sa_family == AF_INET || 14473b3a8eb9SGleb Smirnoff ifa->ifa_addr->sa_family == AF_INET6 || 14483b3a8eb9SGleb Smirnoff ifa->ifa_addr->sa_family == AF_LINK)) 14493b3a8eb9SGleb Smirnoff continue; 14503b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 14513b3a8eb9SGleb Smirnoff if (n == NULL) 14523b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 14533b3a8eb9SGleb Smirnoff n->af = ifa->ifa_addr->sa_family; 14543b3a8eb9SGleb Smirnoff n->ifa_flags = ifa->ifa_flags; 14553b3a8eb9SGleb Smirnoff #ifdef __KAME__ 14563b3a8eb9SGleb Smirnoff if (n->af == AF_INET6 && 14573b3a8eb9SGleb Smirnoff IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) 14583b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_addr) && 14593b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 14603b3a8eb9SGleb Smirnoff 0) { 14613b3a8eb9SGleb Smirnoff struct sockaddr_in6 *sin6; 14623b3a8eb9SGleb Smirnoff 14633b3a8eb9SGleb Smirnoff sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 14643b3a8eb9SGleb Smirnoff sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | 14653b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[3]; 14663b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[2] = 0; 14673b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[3] = 0; 14683b3a8eb9SGleb Smirnoff } 14693b3a8eb9SGleb Smirnoff #endif 14703b3a8eb9SGleb Smirnoff n->ifindex = 0; 14713b3a8eb9SGleb Smirnoff if (n->af == AF_INET) { 14723b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) 14733b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin_addr.s_addr, 14743b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 14753b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) 14763b3a8eb9SGleb Smirnoff ifa->ifa_netmask)->sin_addr.s_addr, 14773b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 14783b3a8eb9SGleb Smirnoff if (ifa->ifa_broadaddr != NULL) 14793b3a8eb9SGleb Smirnoff memcpy(&n->bcast, &((struct sockaddr_in *) 14803b3a8eb9SGleb Smirnoff ifa->ifa_broadaddr)->sin_addr.s_addr, 14813b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 14823b3a8eb9SGleb Smirnoff if (ifa->ifa_dstaddr != NULL) 14833b3a8eb9SGleb Smirnoff memcpy(&n->peer, &((struct sockaddr_in *) 14843b3a8eb9SGleb Smirnoff ifa->ifa_dstaddr)->sin_addr.s_addr, 14853b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 14863b3a8eb9SGleb Smirnoff } else if (n->af == AF_INET6) { 14873b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) 14883b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_addr.s6_addr, 14893b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 14903b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) 14913b3a8eb9SGleb Smirnoff ifa->ifa_netmask)->sin6_addr.s6_addr, 14923b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 14933b3a8eb9SGleb Smirnoff if (ifa->ifa_broadaddr != NULL) 14943b3a8eb9SGleb Smirnoff memcpy(&n->bcast, &((struct sockaddr_in6 *) 14953b3a8eb9SGleb Smirnoff ifa->ifa_broadaddr)->sin6_addr.s6_addr, 14963b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 14973b3a8eb9SGleb Smirnoff if (ifa->ifa_dstaddr != NULL) 14983b3a8eb9SGleb Smirnoff memcpy(&n->peer, &((struct sockaddr_in6 *) 14993b3a8eb9SGleb Smirnoff ifa->ifa_dstaddr)->sin6_addr.s6_addr, 15003b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 15013b3a8eb9SGleb Smirnoff n->ifindex = ((struct sockaddr_in6 *) 15023b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_scope_id; 15031d34c9daSPatrick Kelsey } else if (n->af == AF_LINK) { 15041d34c9daSPatrick Kelsey ifa_add_groups_to_map(ifa->ifa_name); 15053b3a8eb9SGleb Smirnoff } 15063b3a8eb9SGleb Smirnoff if ((n->ifname = strdup(ifa->ifa_name)) == NULL) 15073b3a8eb9SGleb Smirnoff err(1, "ifa_load: strdup"); 15083b3a8eb9SGleb Smirnoff n->next = NULL; 15093b3a8eb9SGleb Smirnoff n->tail = n; 15103b3a8eb9SGleb Smirnoff if (h == NULL) 15113b3a8eb9SGleb Smirnoff h = n; 15123b3a8eb9SGleb Smirnoff else { 15133b3a8eb9SGleb Smirnoff h->tail->next = n; 15143b3a8eb9SGleb Smirnoff h->tail = n; 15153b3a8eb9SGleb Smirnoff } 15163b3a8eb9SGleb Smirnoff } 15173b3a8eb9SGleb Smirnoff 15183b3a8eb9SGleb Smirnoff iftab = h; 15193b3a8eb9SGleb Smirnoff freeifaddrs(ifap); 15203b3a8eb9SGleb Smirnoff } 15213b3a8eb9SGleb Smirnoff 15221d34c9daSPatrick Kelsey static int 1523f870cb7fSBjoern A. Zeeb get_socket_domain(void) 1524f870cb7fSBjoern A. Zeeb { 1525f870cb7fSBjoern A. Zeeb int sdom; 1526f870cb7fSBjoern A. Zeeb 1527f870cb7fSBjoern A. Zeeb sdom = AF_UNSPEC; 1528f870cb7fSBjoern A. Zeeb #ifdef WITH_INET6 1529f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC && feature_present("inet6")) 1530f870cb7fSBjoern A. Zeeb sdom = AF_INET6; 1531f870cb7fSBjoern A. Zeeb #endif 1532f870cb7fSBjoern A. Zeeb #ifdef WITH_INET 1533f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC && feature_present("inet")) 1534f870cb7fSBjoern A. Zeeb sdom = AF_INET; 1535f870cb7fSBjoern A. Zeeb #endif 1536f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC) 1537f870cb7fSBjoern A. Zeeb sdom = AF_LINK; 1538f870cb7fSBjoern A. Zeeb 1539f870cb7fSBjoern A. Zeeb return (sdom); 1540f870cb7fSBjoern A. Zeeb } 1541f870cb7fSBjoern A. Zeeb 15421d34c9daSPatrick Kelsey int 15431d34c9daSPatrick Kelsey get_query_socket(void) 15441d34c9daSPatrick Kelsey { 15451d34c9daSPatrick Kelsey static int s = -1; 15461d34c9daSPatrick Kelsey 15471d34c9daSPatrick Kelsey if (s == -1) { 15481d34c9daSPatrick Kelsey if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) 15491d34c9daSPatrick Kelsey err(1, "socket"); 15501d34c9daSPatrick Kelsey } 15511d34c9daSPatrick Kelsey 15521d34c9daSPatrick Kelsey return (s); 15531d34c9daSPatrick Kelsey } 15541d34c9daSPatrick Kelsey 15551d34c9daSPatrick Kelsey /* 15561d34c9daSPatrick Kelsey * Returns the response len if the name is a group, otherwise returns 0. 15571d34c9daSPatrick Kelsey */ 15581d34c9daSPatrick Kelsey static int 15591d34c9daSPatrick Kelsey is_a_group(char *name) 15601d34c9daSPatrick Kelsey { 15611d34c9daSPatrick Kelsey ENTRY item; 15621d34c9daSPatrick Kelsey ENTRY *ret_item; 15631d34c9daSPatrick Kelsey 15641d34c9daSPatrick Kelsey item.key = name; 15651d34c9daSPatrick Kelsey if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) 15661d34c9daSPatrick Kelsey return (0); 15671d34c9daSPatrick Kelsey 15681d34c9daSPatrick Kelsey return (*(int *)ret_item->data); 15691d34c9daSPatrick Kelsey } 15701d34c9daSPatrick Kelsey 15713b3a8eb9SGleb Smirnoff struct node_host * 15721d34c9daSPatrick Kelsey ifa_exists(char *ifa_name) 15733b3a8eb9SGleb Smirnoff { 15743b3a8eb9SGleb Smirnoff struct node_host *n; 15753b3a8eb9SGleb Smirnoff 15763b3a8eb9SGleb Smirnoff if (iftab == NULL) 15773b3a8eb9SGleb Smirnoff ifa_load(); 15783b3a8eb9SGleb Smirnoff 15791d34c9daSPatrick Kelsey /* check whether this is a group */ 15801d34c9daSPatrick Kelsey if (is_a_group(ifa_name)) { 15813b3a8eb9SGleb Smirnoff /* fake a node_host */ 15823b3a8eb9SGleb Smirnoff if ((n = calloc(1, sizeof(*n))) == NULL) 15833b3a8eb9SGleb Smirnoff err(1, "calloc"); 15843b3a8eb9SGleb Smirnoff if ((n->ifname = strdup(ifa_name)) == NULL) 15853b3a8eb9SGleb Smirnoff err(1, "strdup"); 15863b3a8eb9SGleb Smirnoff return (n); 15873b3a8eb9SGleb Smirnoff } 15883b3a8eb9SGleb Smirnoff 15893b3a8eb9SGleb Smirnoff for (n = iftab; n; n = n->next) { 15903b3a8eb9SGleb Smirnoff if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) 15913b3a8eb9SGleb Smirnoff return (n); 15923b3a8eb9SGleb Smirnoff } 15933b3a8eb9SGleb Smirnoff 15943b3a8eb9SGleb Smirnoff return (NULL); 15953b3a8eb9SGleb Smirnoff } 15963b3a8eb9SGleb Smirnoff 15973b3a8eb9SGleb Smirnoff struct node_host * 15981d34c9daSPatrick Kelsey ifa_grouplookup(char *ifa_name, int flags) 15993b3a8eb9SGleb Smirnoff { 16003b3a8eb9SGleb Smirnoff struct ifg_req *ifg; 16013b3a8eb9SGleb Smirnoff struct ifgroupreq ifgr; 16023b3a8eb9SGleb Smirnoff int s, len; 16033b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 16043b3a8eb9SGleb Smirnoff 16051d34c9daSPatrick Kelsey s = get_query_socket(); 16061d34c9daSPatrick Kelsey len = is_a_group(ifa_name); 16071d34c9daSPatrick Kelsey if (len == 0) 16081d34c9daSPatrick Kelsey return (NULL); 16093b3a8eb9SGleb Smirnoff bzero(&ifgr, sizeof(ifgr)); 16103b3a8eb9SGleb Smirnoff strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); 16114c8fb952SKristof Provost ifgr.ifgr_len = len; 16123b3a8eb9SGleb Smirnoff if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 16133b3a8eb9SGleb Smirnoff err(1, "calloc"); 16143b3a8eb9SGleb Smirnoff if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 16153b3a8eb9SGleb Smirnoff err(1, "SIOCGIFGMEMB"); 16163b3a8eb9SGleb Smirnoff 16173b3a8eb9SGleb Smirnoff for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req); 16183b3a8eb9SGleb Smirnoff ifg++) { 16193b3a8eb9SGleb Smirnoff len -= sizeof(struct ifg_req); 1620d5b08e13SKristof Provost if ((n = ifa_lookup(ifg->ifgrq_member, flags)) == NULL) 16213b3a8eb9SGleb Smirnoff continue; 16223b3a8eb9SGleb Smirnoff if (h == NULL) 16233b3a8eb9SGleb Smirnoff h = n; 16243b3a8eb9SGleb Smirnoff else { 16253b3a8eb9SGleb Smirnoff h->tail->next = n; 16263b3a8eb9SGleb Smirnoff h->tail = n->tail; 16273b3a8eb9SGleb Smirnoff } 16283b3a8eb9SGleb Smirnoff } 16293b3a8eb9SGleb Smirnoff free(ifgr.ifgr_groups); 16303b3a8eb9SGleb Smirnoff 16313b3a8eb9SGleb Smirnoff return (h); 16323b3a8eb9SGleb Smirnoff } 16333b3a8eb9SGleb Smirnoff 16343b3a8eb9SGleb Smirnoff struct node_host * 16351d34c9daSPatrick Kelsey ifa_lookup(char *ifa_name, int flags) 16363b3a8eb9SGleb Smirnoff { 16373b3a8eb9SGleb Smirnoff struct node_host *p = NULL, *h = NULL, *n = NULL; 16383b3a8eb9SGleb Smirnoff int got4 = 0, got6 = 0; 16393b3a8eb9SGleb Smirnoff const char *last_if = NULL; 16403b3a8eb9SGleb Smirnoff 16418fd675d8SKristof Provost /* first load iftab and isgroup_map */ 16428fd675d8SKristof Provost if (iftab == NULL) 16438fd675d8SKristof Provost ifa_load(); 16448fd675d8SKristof Provost 16453b3a8eb9SGleb Smirnoff if ((h = ifa_grouplookup(ifa_name, flags)) != NULL) 16463b3a8eb9SGleb Smirnoff return (h); 16473b3a8eb9SGleb Smirnoff 16483b3a8eb9SGleb Smirnoff if (!strncmp(ifa_name, "self", IFNAMSIZ)) 16493b3a8eb9SGleb Smirnoff ifa_name = NULL; 16503b3a8eb9SGleb Smirnoff 16513b3a8eb9SGleb Smirnoff for (p = iftab; p; p = p->next) { 16523b3a8eb9SGleb Smirnoff if (ifa_skip_if(ifa_name, p)) 16533b3a8eb9SGleb Smirnoff continue; 16543b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET) 16553b3a8eb9SGleb Smirnoff continue; 16563b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_BROADCAST) && 16573b3a8eb9SGleb Smirnoff !(p->ifa_flags & IFF_BROADCAST)) 16583b3a8eb9SGleb Smirnoff continue; 16593b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_PEER) && 16603b3a8eb9SGleb Smirnoff !(p->ifa_flags & IFF_POINTOPOINT)) 16613b3a8eb9SGleb Smirnoff continue; 16623b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NETWORK) && p->ifindex > 0) 16633b3a8eb9SGleb Smirnoff continue; 16643b3a8eb9SGleb Smirnoff if (last_if == NULL || strcmp(last_if, p->ifname)) 16653b3a8eb9SGleb Smirnoff got4 = got6 = 0; 16663b3a8eb9SGleb Smirnoff last_if = p->ifname; 16673b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET && got4) 16683b3a8eb9SGleb Smirnoff continue; 166999eb0055SKristof Provost if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && 167099eb0055SKristof Provost IN6_IS_ADDR_LINKLOCAL(&p->addr.v.a.addr.v6)) 167199eb0055SKristof Provost continue; 16723b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && got6) 16733b3a8eb9SGleb Smirnoff continue; 16743b3a8eb9SGleb Smirnoff if (p->af == AF_INET) 16753b3a8eb9SGleb Smirnoff got4 = 1; 16763b3a8eb9SGleb Smirnoff else 16773b3a8eb9SGleb Smirnoff got6 = 1; 16783b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 16793b3a8eb9SGleb Smirnoff if (n == NULL) 16803b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 16813b3a8eb9SGleb Smirnoff n->af = p->af; 16823b3a8eb9SGleb Smirnoff if (flags & PFI_AFLAG_BROADCAST) 16833b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->bcast, 16843b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 16853b3a8eb9SGleb Smirnoff else if (flags & PFI_AFLAG_PEER) 16863b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->peer, 16873b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 16883b3a8eb9SGleb Smirnoff else 16893b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, 16903b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 16913b3a8eb9SGleb Smirnoff if (flags & PFI_AFLAG_NETWORK) 16923b3a8eb9SGleb Smirnoff set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); 16933b3a8eb9SGleb Smirnoff else { 16943b3a8eb9SGleb Smirnoff if (n->af == AF_INET) { 16953b3a8eb9SGleb Smirnoff if (p->ifa_flags & IFF_LOOPBACK && 16963b3a8eb9SGleb Smirnoff p->ifa_flags & IFF_LINK1) 16973b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, 16983b3a8eb9SGleb Smirnoff &p->addr.v.a.mask, 16993b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 17003b3a8eb9SGleb Smirnoff else 17013b3a8eb9SGleb Smirnoff set_ipmask(n, 32); 17023b3a8eb9SGleb Smirnoff } else 17033b3a8eb9SGleb Smirnoff set_ipmask(n, 128); 17043b3a8eb9SGleb Smirnoff } 17053b3a8eb9SGleb Smirnoff n->ifindex = p->ifindex; 17060f9e47a9SKristof Provost n->ifname = strdup(p->ifname); 17073b3a8eb9SGleb Smirnoff 17083b3a8eb9SGleb Smirnoff n->next = NULL; 17093b3a8eb9SGleb Smirnoff n->tail = n; 17103b3a8eb9SGleb Smirnoff if (h == NULL) 17113b3a8eb9SGleb Smirnoff h = n; 17123b3a8eb9SGleb Smirnoff else { 17133b3a8eb9SGleb Smirnoff h->tail->next = n; 17143b3a8eb9SGleb Smirnoff h->tail = n; 17153b3a8eb9SGleb Smirnoff } 17163b3a8eb9SGleb Smirnoff } 17173b3a8eb9SGleb Smirnoff return (h); 17183b3a8eb9SGleb Smirnoff } 17193b3a8eb9SGleb Smirnoff 17203b3a8eb9SGleb Smirnoff int 17213b3a8eb9SGleb Smirnoff ifa_skip_if(const char *filter, struct node_host *p) 17223b3a8eb9SGleb Smirnoff { 17233b3a8eb9SGleb Smirnoff int n; 17243b3a8eb9SGleb Smirnoff 17253b3a8eb9SGleb Smirnoff if (p->af != AF_INET && p->af != AF_INET6) 17263b3a8eb9SGleb Smirnoff return (1); 17273b3a8eb9SGleb Smirnoff if (filter == NULL || !*filter) 17283b3a8eb9SGleb Smirnoff return (0); 17293b3a8eb9SGleb Smirnoff if (!strcmp(p->ifname, filter)) 17303b3a8eb9SGleb Smirnoff return (0); /* exact match */ 17313b3a8eb9SGleb Smirnoff n = strlen(filter); 17323b3a8eb9SGleb Smirnoff if (n < 1 || n >= IFNAMSIZ) 17333b3a8eb9SGleb Smirnoff return (1); /* sanity check */ 17343b3a8eb9SGleb Smirnoff if (filter[n-1] >= '0' && filter[n-1] <= '9') 17353b3a8eb9SGleb Smirnoff return (1); /* only do exact match in that case */ 17363b3a8eb9SGleb Smirnoff if (strncmp(p->ifname, filter, n)) 17373b3a8eb9SGleb Smirnoff return (1); /* prefix doesn't match */ 17383b3a8eb9SGleb Smirnoff return (p->ifname[n] < '0' || p->ifname[n] > '9'); 17393b3a8eb9SGleb Smirnoff } 17403b3a8eb9SGleb Smirnoff 17413b3a8eb9SGleb Smirnoff 17423b3a8eb9SGleb Smirnoff struct node_host * 17433b3a8eb9SGleb Smirnoff host(const char *s) 17443b3a8eb9SGleb Smirnoff { 17453b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 17463b3a8eb9SGleb Smirnoff int mask, v4mask, v6mask, cont = 1; 17473b3a8eb9SGleb Smirnoff char *p, *q, *ps; 17483b3a8eb9SGleb Smirnoff 17493b3a8eb9SGleb Smirnoff if ((p = strrchr(s, '/')) != NULL) { 17503b3a8eb9SGleb Smirnoff mask = strtol(p+1, &q, 0); 17513b3a8eb9SGleb Smirnoff if (!q || *q || mask > 128 || q == (p+1)) { 17523b3a8eb9SGleb Smirnoff fprintf(stderr, "invalid netmask '%s'\n", p); 17533b3a8eb9SGleb Smirnoff return (NULL); 17543b3a8eb9SGleb Smirnoff } 17553b3a8eb9SGleb Smirnoff if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 17563b3a8eb9SGleb Smirnoff err(1, "host: malloc"); 17573b3a8eb9SGleb Smirnoff strlcpy(ps, s, strlen(s) - strlen(p) + 1); 17583b3a8eb9SGleb Smirnoff v4mask = v6mask = mask; 17593b3a8eb9SGleb Smirnoff } else { 17603b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 17613b3a8eb9SGleb Smirnoff err(1, "host: strdup"); 17623b3a8eb9SGleb Smirnoff v4mask = 32; 17633b3a8eb9SGleb Smirnoff v6mask = 128; 17643b3a8eb9SGleb Smirnoff mask = -1; 17653b3a8eb9SGleb Smirnoff } 17663b3a8eb9SGleb Smirnoff 17673b3a8eb9SGleb Smirnoff /* IPv4 address? */ 17683b3a8eb9SGleb Smirnoff if (cont && (h = host_v4(s, mask)) != NULL) 17693b3a8eb9SGleb Smirnoff cont = 0; 17703b3a8eb9SGleb Smirnoff 17713b3a8eb9SGleb Smirnoff /* IPv6 address? */ 17723b3a8eb9SGleb Smirnoff if (cont && (h = host_v6(ps, v6mask)) != NULL) 17733b3a8eb9SGleb Smirnoff cont = 0; 17743b3a8eb9SGleb Smirnoff 1775d2568b02SKristof Provost /* interface with this name exists? */ 1776d2568b02SKristof Provost /* expensive with thousands of interfaces - prioritze IPv4/6 check */ 177728b64169SFranco Fichtner if (cont && (h = host_if(ps, mask, &cont)) != NULL) 1778d2568b02SKristof Provost cont = 0; 1779d2568b02SKristof Provost 17803b3a8eb9SGleb Smirnoff /* dns lookup */ 17813b3a8eb9SGleb Smirnoff if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL) 17823b3a8eb9SGleb Smirnoff cont = 0; 17833b3a8eb9SGleb Smirnoff free(ps); 17843b3a8eb9SGleb Smirnoff 17853b3a8eb9SGleb Smirnoff if (h == NULL || cont == 1) { 17863b3a8eb9SGleb Smirnoff fprintf(stderr, "no IP address found for %s\n", s); 17873b3a8eb9SGleb Smirnoff return (NULL); 17883b3a8eb9SGleb Smirnoff } 17893b3a8eb9SGleb Smirnoff return (h); 17903b3a8eb9SGleb Smirnoff } 17913b3a8eb9SGleb Smirnoff 17923b3a8eb9SGleb Smirnoff struct node_host * 179328b64169SFranco Fichtner host_if(const char *s, int mask, int *cont) 17943b3a8eb9SGleb Smirnoff { 17953b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 17963b3a8eb9SGleb Smirnoff char *p, *ps; 17973b3a8eb9SGleb Smirnoff int flags = 0; 17983b3a8eb9SGleb Smirnoff 17993b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 18003b3a8eb9SGleb Smirnoff err(1, "host_if: strdup"); 18013b3a8eb9SGleb Smirnoff while ((p = strrchr(ps, ':')) != NULL) { 18023b3a8eb9SGleb Smirnoff if (!strcmp(p+1, "network")) 18033b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NETWORK; 18043b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "broadcast")) 18053b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_BROADCAST; 18063b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "peer")) 18073b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_PEER; 18083b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "0")) 18093b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NOALIAS; 18103b3a8eb9SGleb Smirnoff else { 18113b3a8eb9SGleb Smirnoff free(ps); 18123b3a8eb9SGleb Smirnoff return (NULL); 18133b3a8eb9SGleb Smirnoff } 18143b3a8eb9SGleb Smirnoff *p = '\0'; 181528b64169SFranco Fichtner *cont = 0; 18163b3a8eb9SGleb Smirnoff } 18173b3a8eb9SGleb Smirnoff if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */ 18183b3a8eb9SGleb Smirnoff fprintf(stderr, "illegal combination of interface modifiers\n"); 18193b3a8eb9SGleb Smirnoff free(ps); 18203b3a8eb9SGleb Smirnoff return (NULL); 18213b3a8eb9SGleb Smirnoff } 18223b3a8eb9SGleb Smirnoff if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) { 18233b3a8eb9SGleb Smirnoff fprintf(stderr, "network or broadcast lookup, but " 18243b3a8eb9SGleb Smirnoff "extra netmask given\n"); 18253b3a8eb9SGleb Smirnoff free(ps); 18263b3a8eb9SGleb Smirnoff return (NULL); 18273b3a8eb9SGleb Smirnoff } 18283b3a8eb9SGleb Smirnoff if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) { 18293b3a8eb9SGleb Smirnoff /* interface with this name exists */ 18303b3a8eb9SGleb Smirnoff h = ifa_lookup(ps, flags); 18313b3a8eb9SGleb Smirnoff for (n = h; n != NULL && mask > -1; n = n->next) 18323b3a8eb9SGleb Smirnoff set_ipmask(n, mask); 18333b3a8eb9SGleb Smirnoff } 18343b3a8eb9SGleb Smirnoff 18353b3a8eb9SGleb Smirnoff free(ps); 18363b3a8eb9SGleb Smirnoff return (h); 18373b3a8eb9SGleb Smirnoff } 18383b3a8eb9SGleb Smirnoff 18393b3a8eb9SGleb Smirnoff struct node_host * 18403b3a8eb9SGleb Smirnoff host_v4(const char *s, int mask) 18413b3a8eb9SGleb Smirnoff { 18423b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 18433b3a8eb9SGleb Smirnoff struct in_addr ina; 18443b3a8eb9SGleb Smirnoff int bits = 32; 18453b3a8eb9SGleb Smirnoff 18463b3a8eb9SGleb Smirnoff memset(&ina, 0, sizeof(struct in_addr)); 18473b3a8eb9SGleb Smirnoff if (strrchr(s, '/') != NULL) { 18483b3a8eb9SGleb Smirnoff if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 18493b3a8eb9SGleb Smirnoff return (NULL); 18503b3a8eb9SGleb Smirnoff } else { 18513b3a8eb9SGleb Smirnoff if (inet_pton(AF_INET, s, &ina) != 1) 18523b3a8eb9SGleb Smirnoff return (NULL); 18533b3a8eb9SGleb Smirnoff } 18543b3a8eb9SGleb Smirnoff 18553b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(struct node_host)); 18563b3a8eb9SGleb Smirnoff if (h == NULL) 18573b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 18583b3a8eb9SGleb Smirnoff h->ifname = NULL; 18593b3a8eb9SGleb Smirnoff h->af = AF_INET; 18603b3a8eb9SGleb Smirnoff h->addr.v.a.addr.addr32[0] = ina.s_addr; 18613b3a8eb9SGleb Smirnoff set_ipmask(h, bits); 18623b3a8eb9SGleb Smirnoff h->next = NULL; 18633b3a8eb9SGleb Smirnoff h->tail = h; 18643b3a8eb9SGleb Smirnoff 18653b3a8eb9SGleb Smirnoff return (h); 18663b3a8eb9SGleb Smirnoff } 18673b3a8eb9SGleb Smirnoff 18683b3a8eb9SGleb Smirnoff struct node_host * 18693b3a8eb9SGleb Smirnoff host_v6(const char *s, int mask) 18703b3a8eb9SGleb Smirnoff { 18713b3a8eb9SGleb Smirnoff struct addrinfo hints, *res; 18723b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 18733b3a8eb9SGleb Smirnoff 18743b3a8eb9SGleb Smirnoff memset(&hints, 0, sizeof(hints)); 18753b3a8eb9SGleb Smirnoff hints.ai_family = AF_INET6; 18763b3a8eb9SGleb Smirnoff hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 18773b3a8eb9SGleb Smirnoff hints.ai_flags = AI_NUMERICHOST; 18783b3a8eb9SGleb Smirnoff if (getaddrinfo(s, "0", &hints, &res) == 0) { 18793b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(struct node_host)); 18803b3a8eb9SGleb Smirnoff if (h == NULL) 18813b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 18823b3a8eb9SGleb Smirnoff h->ifname = NULL; 18833b3a8eb9SGleb Smirnoff h->af = AF_INET6; 18843b3a8eb9SGleb Smirnoff memcpy(&h->addr.v.a.addr, 18853b3a8eb9SGleb Smirnoff &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 18863b3a8eb9SGleb Smirnoff sizeof(h->addr.v.a.addr)); 18873b3a8eb9SGleb Smirnoff h->ifindex = 18883b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 18893b3a8eb9SGleb Smirnoff set_ipmask(h, mask); 18903b3a8eb9SGleb Smirnoff freeaddrinfo(res); 18913b3a8eb9SGleb Smirnoff h->next = NULL; 18923b3a8eb9SGleb Smirnoff h->tail = h; 18933b3a8eb9SGleb Smirnoff } 18943b3a8eb9SGleb Smirnoff 18953b3a8eb9SGleb Smirnoff return (h); 18963b3a8eb9SGleb Smirnoff } 18973b3a8eb9SGleb Smirnoff 18983b3a8eb9SGleb Smirnoff struct node_host * 18993b3a8eb9SGleb Smirnoff host_dns(const char *s, int v4mask, int v6mask) 19003b3a8eb9SGleb Smirnoff { 19013b3a8eb9SGleb Smirnoff struct addrinfo hints, *res0, *res; 19023b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 19033b3a8eb9SGleb Smirnoff int error, noalias = 0; 19043b3a8eb9SGleb Smirnoff int got4 = 0, got6 = 0; 19053b3a8eb9SGleb Smirnoff char *p, *ps; 19063b3a8eb9SGleb Smirnoff 19073b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 19083b3a8eb9SGleb Smirnoff err(1, "host_dns: strdup"); 19093b3a8eb9SGleb Smirnoff if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) { 19103b3a8eb9SGleb Smirnoff noalias = 1; 19113b3a8eb9SGleb Smirnoff *p = '\0'; 19123b3a8eb9SGleb Smirnoff } 19133b3a8eb9SGleb Smirnoff memset(&hints, 0, sizeof(hints)); 19143b3a8eb9SGleb Smirnoff hints.ai_family = PF_UNSPEC; 19153b3a8eb9SGleb Smirnoff hints.ai_socktype = SOCK_STREAM; /* DUMMY */ 19163b3a8eb9SGleb Smirnoff error = getaddrinfo(ps, NULL, &hints, &res0); 19173b3a8eb9SGleb Smirnoff if (error) { 19183b3a8eb9SGleb Smirnoff free(ps); 19193b3a8eb9SGleb Smirnoff return (h); 19203b3a8eb9SGleb Smirnoff } 19213b3a8eb9SGleb Smirnoff 19223b3a8eb9SGleb Smirnoff for (res = res0; res; res = res->ai_next) { 19233b3a8eb9SGleb Smirnoff if (res->ai_family != AF_INET && 19243b3a8eb9SGleb Smirnoff res->ai_family != AF_INET6) 19253b3a8eb9SGleb Smirnoff continue; 19263b3a8eb9SGleb Smirnoff if (noalias) { 19273b3a8eb9SGleb Smirnoff if (res->ai_family == AF_INET) { 19283b3a8eb9SGleb Smirnoff if (got4) 19293b3a8eb9SGleb Smirnoff continue; 19303b3a8eb9SGleb Smirnoff got4 = 1; 19313b3a8eb9SGleb Smirnoff } else { 19323b3a8eb9SGleb Smirnoff if (got6) 19333b3a8eb9SGleb Smirnoff continue; 19343b3a8eb9SGleb Smirnoff got6 = 1; 19353b3a8eb9SGleb Smirnoff } 19363b3a8eb9SGleb Smirnoff } 19373b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 19383b3a8eb9SGleb Smirnoff if (n == NULL) 19393b3a8eb9SGleb Smirnoff err(1, "host_dns: calloc"); 19403b3a8eb9SGleb Smirnoff n->ifname = NULL; 19413b3a8eb9SGleb Smirnoff n->af = res->ai_family; 19423b3a8eb9SGleb Smirnoff if (res->ai_family == AF_INET) { 19433b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, 19443b3a8eb9SGleb Smirnoff &((struct sockaddr_in *) 19453b3a8eb9SGleb Smirnoff res->ai_addr)->sin_addr.s_addr, 19463b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 19473b3a8eb9SGleb Smirnoff set_ipmask(n, v4mask); 19483b3a8eb9SGleb Smirnoff } else { 19493b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, 19503b3a8eb9SGleb Smirnoff &((struct sockaddr_in6 *) 19513b3a8eb9SGleb Smirnoff res->ai_addr)->sin6_addr.s6_addr, 19523b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 19533b3a8eb9SGleb Smirnoff n->ifindex = 19543b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *) 19553b3a8eb9SGleb Smirnoff res->ai_addr)->sin6_scope_id; 19563b3a8eb9SGleb Smirnoff set_ipmask(n, v6mask); 19573b3a8eb9SGleb Smirnoff } 19583b3a8eb9SGleb Smirnoff n->next = NULL; 19593b3a8eb9SGleb Smirnoff n->tail = n; 19603b3a8eb9SGleb Smirnoff if (h == NULL) 19613b3a8eb9SGleb Smirnoff h = n; 19623b3a8eb9SGleb Smirnoff else { 19633b3a8eb9SGleb Smirnoff h->tail->next = n; 19643b3a8eb9SGleb Smirnoff h->tail = n; 19653b3a8eb9SGleb Smirnoff } 19663b3a8eb9SGleb Smirnoff } 19673b3a8eb9SGleb Smirnoff freeaddrinfo(res0); 19683b3a8eb9SGleb Smirnoff free(ps); 19693b3a8eb9SGleb Smirnoff 19703b3a8eb9SGleb Smirnoff return (h); 19713b3a8eb9SGleb Smirnoff } 19723b3a8eb9SGleb Smirnoff 19733b3a8eb9SGleb Smirnoff /* 19743b3a8eb9SGleb Smirnoff * convert a hostname to a list of addresses and put them in the given buffer. 19753b3a8eb9SGleb Smirnoff * test: 19763b3a8eb9SGleb Smirnoff * if set to 1, only simple addresses are accepted (no netblock, no "!"). 19773b3a8eb9SGleb Smirnoff */ 19783b3a8eb9SGleb Smirnoff int 19793b3a8eb9SGleb Smirnoff append_addr(struct pfr_buffer *b, char *s, int test) 19803b3a8eb9SGleb Smirnoff { 19813b3a8eb9SGleb Smirnoff char *r; 19823b3a8eb9SGleb Smirnoff struct node_host *h, *n; 19833b3a8eb9SGleb Smirnoff int rv, not = 0; 19843b3a8eb9SGleb Smirnoff 19853b3a8eb9SGleb Smirnoff for (r = s; *r == '!'; r++) 19863b3a8eb9SGleb Smirnoff not = !not; 19873b3a8eb9SGleb Smirnoff if ((n = host(r)) == NULL) { 19883b3a8eb9SGleb Smirnoff errno = 0; 19893b3a8eb9SGleb Smirnoff return (-1); 19903b3a8eb9SGleb Smirnoff } 19913b3a8eb9SGleb Smirnoff rv = append_addr_host(b, n, test, not); 19923b3a8eb9SGleb Smirnoff do { 19933b3a8eb9SGleb Smirnoff h = n; 19943b3a8eb9SGleb Smirnoff n = n->next; 19953b3a8eb9SGleb Smirnoff free(h); 19963b3a8eb9SGleb Smirnoff } while (n != NULL); 19973b3a8eb9SGleb Smirnoff return (rv); 19983b3a8eb9SGleb Smirnoff } 19993b3a8eb9SGleb Smirnoff 20003b3a8eb9SGleb Smirnoff /* 20013b3a8eb9SGleb Smirnoff * same as previous function, but with a pre-parsed input and the ability 20023b3a8eb9SGleb Smirnoff * to "negate" the result. Does not free the node_host list. 20033b3a8eb9SGleb Smirnoff * not: 20043b3a8eb9SGleb Smirnoff * setting it to 1 is equivalent to adding "!" in front of parameter s. 20053b3a8eb9SGleb Smirnoff */ 20063b3a8eb9SGleb Smirnoff int 20073b3a8eb9SGleb Smirnoff append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not) 20083b3a8eb9SGleb Smirnoff { 20093b3a8eb9SGleb Smirnoff int bits; 20103b3a8eb9SGleb Smirnoff struct pfr_addr addr; 20113b3a8eb9SGleb Smirnoff 20123b3a8eb9SGleb Smirnoff do { 20133b3a8eb9SGleb Smirnoff bzero(&addr, sizeof(addr)); 20143b3a8eb9SGleb Smirnoff addr.pfra_not = n->not ^ not; 20153b3a8eb9SGleb Smirnoff addr.pfra_af = n->af; 20163b3a8eb9SGleb Smirnoff addr.pfra_net = unmask(&n->addr.v.a.mask, n->af); 20173b3a8eb9SGleb Smirnoff switch (n->af) { 20183b3a8eb9SGleb Smirnoff case AF_INET: 20193b3a8eb9SGleb Smirnoff addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0]; 20203b3a8eb9SGleb Smirnoff bits = 32; 20213b3a8eb9SGleb Smirnoff break; 20223b3a8eb9SGleb Smirnoff case AF_INET6: 20233b3a8eb9SGleb Smirnoff memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6, 20243b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 20253b3a8eb9SGleb Smirnoff bits = 128; 20263b3a8eb9SGleb Smirnoff break; 20273b3a8eb9SGleb Smirnoff default: 20283b3a8eb9SGleb Smirnoff errno = EINVAL; 20293b3a8eb9SGleb Smirnoff return (-1); 20303b3a8eb9SGleb Smirnoff } 20313b3a8eb9SGleb Smirnoff if ((test && (not || addr.pfra_net != bits)) || 20323b3a8eb9SGleb Smirnoff addr.pfra_net > bits) { 20333b3a8eb9SGleb Smirnoff errno = EINVAL; 20343b3a8eb9SGleb Smirnoff return (-1); 20353b3a8eb9SGleb Smirnoff } 20363b3a8eb9SGleb Smirnoff if (pfr_buf_add(b, &addr)) 20373b3a8eb9SGleb Smirnoff return (-1); 20383b3a8eb9SGleb Smirnoff } while ((n = n->next) != NULL); 20393b3a8eb9SGleb Smirnoff 20403b3a8eb9SGleb Smirnoff return (0); 20413b3a8eb9SGleb Smirnoff } 20423b3a8eb9SGleb Smirnoff 20433b3a8eb9SGleb Smirnoff int 20443b3a8eb9SGleb Smirnoff pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor) 20453b3a8eb9SGleb Smirnoff { 20463b3a8eb9SGleb Smirnoff struct pfioc_trans_e trans; 20473b3a8eb9SGleb Smirnoff 20483b3a8eb9SGleb Smirnoff bzero(&trans, sizeof(trans)); 20493b3a8eb9SGleb Smirnoff trans.rs_num = rs_num; 20503b3a8eb9SGleb Smirnoff if (strlcpy(trans.anchor, anchor, 20513b3a8eb9SGleb Smirnoff sizeof(trans.anchor)) >= sizeof(trans.anchor)) 20523b3a8eb9SGleb Smirnoff errx(1, "pfctl_add_trans: strlcpy"); 20533b3a8eb9SGleb Smirnoff 20543b3a8eb9SGleb Smirnoff return pfr_buf_add(buf, &trans); 20553b3a8eb9SGleb Smirnoff } 20563b3a8eb9SGleb Smirnoff 20573b3a8eb9SGleb Smirnoff u_int32_t 20583b3a8eb9SGleb Smirnoff pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor) 20593b3a8eb9SGleb Smirnoff { 20603b3a8eb9SGleb Smirnoff struct pfioc_trans_e *p; 20613b3a8eb9SGleb Smirnoff 20623b3a8eb9SGleb Smirnoff PFRB_FOREACH(p, buf) 20633b3a8eb9SGleb Smirnoff if (rs_num == p->rs_num && !strcmp(anchor, p->anchor)) 20643b3a8eb9SGleb Smirnoff return (p->ticket); 20653b3a8eb9SGleb Smirnoff errx(1, "pfctl_get_ticket: assertion failed"); 20663b3a8eb9SGleb Smirnoff } 20673b3a8eb9SGleb Smirnoff 20683b3a8eb9SGleb Smirnoff int 20693b3a8eb9SGleb Smirnoff pfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from) 20703b3a8eb9SGleb Smirnoff { 20713b3a8eb9SGleb Smirnoff struct pfioc_trans trans; 20723b3a8eb9SGleb Smirnoff 20733b3a8eb9SGleb Smirnoff bzero(&trans, sizeof(trans)); 20743b3a8eb9SGleb Smirnoff trans.size = buf->pfrb_size - from; 20753b3a8eb9SGleb Smirnoff trans.esize = sizeof(struct pfioc_trans_e); 20763b3a8eb9SGleb Smirnoff trans.array = ((struct pfioc_trans_e *)buf->pfrb_caddr) + from; 20773b3a8eb9SGleb Smirnoff return ioctl(dev, cmd, &trans); 20783b3a8eb9SGleb Smirnoff } 2079