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> 47347dd053SRichard Scheffenegger #include <netinet/tcp.h> 483b3a8eb9SGleb Smirnoff #include <net/pfvar.h> 493b3a8eb9SGleb Smirnoff #include <arpa/inet.h> 503b3a8eb9SGleb Smirnoff 515062afffSKristof Provost #include <assert.h> 521d34c9daSPatrick Kelsey #include <search.h> 533b3a8eb9SGleb Smirnoff #include <stdio.h> 543b3a8eb9SGleb Smirnoff #include <stdlib.h> 553b3a8eb9SGleb Smirnoff #include <string.h> 563b3a8eb9SGleb Smirnoff #include <ctype.h> 573b3a8eb9SGleb Smirnoff #include <netdb.h> 583b3a8eb9SGleb Smirnoff #include <stdarg.h> 593b3a8eb9SGleb Smirnoff #include <errno.h> 603b3a8eb9SGleb Smirnoff #include <err.h> 613b3a8eb9SGleb Smirnoff #include <ifaddrs.h> 629c125336SKristof Provost #include <inttypes.h> 633b3a8eb9SGleb Smirnoff #include <unistd.h> 643b3a8eb9SGleb Smirnoff 653b3a8eb9SGleb Smirnoff #include "pfctl_parser.h" 663b3a8eb9SGleb Smirnoff #include "pfctl.h" 673b3a8eb9SGleb Smirnoff 683b3a8eb9SGleb Smirnoff void print_op (u_int8_t, const char *, const char *); 693b3a8eb9SGleb Smirnoff void print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int); 703b3a8eb9SGleb Smirnoff void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned); 71347dd053SRichard Scheffenegger void print_flags (uint16_t); 723b3a8eb9SGleb Smirnoff void print_fromto(struct pf_rule_addr *, pf_osfp_t, 73dbce131bSKristof Provost struct pf_rule_addr *, sa_family_t, u_int8_t, int, int); 743b3a8eb9SGleb Smirnoff int ifa_skip_if(const char *filter, struct node_host *p); 753b3a8eb9SGleb Smirnoff 7628b64169SFranco Fichtner struct node_host *host_if(const char *, int, int *); 773b3a8eb9SGleb Smirnoff struct node_host *host_v4(const char *, int); 783b3a8eb9SGleb Smirnoff struct node_host *host_v6(const char *, int); 793b3a8eb9SGleb Smirnoff struct node_host *host_dns(const char *, int, int); 803b3a8eb9SGleb Smirnoff 81347dd053SRichard Scheffenegger const char * const tcpflags = "FSRPAUEWe"; 823b3a8eb9SGleb Smirnoff 833b3a8eb9SGleb Smirnoff static const struct icmptypeent icmp_type[] = { 843b3a8eb9SGleb Smirnoff { "echoreq", ICMP_ECHO }, 853b3a8eb9SGleb Smirnoff { "echorep", ICMP_ECHOREPLY }, 863b3a8eb9SGleb Smirnoff { "unreach", ICMP_UNREACH }, 873b3a8eb9SGleb Smirnoff { "squench", ICMP_SOURCEQUENCH }, 883b3a8eb9SGleb Smirnoff { "redir", ICMP_REDIRECT }, 893b3a8eb9SGleb Smirnoff { "althost", ICMP_ALTHOSTADDR }, 903b3a8eb9SGleb Smirnoff { "routeradv", ICMP_ROUTERADVERT }, 913b3a8eb9SGleb Smirnoff { "routersol", ICMP_ROUTERSOLICIT }, 923b3a8eb9SGleb Smirnoff { "timex", ICMP_TIMXCEED }, 933b3a8eb9SGleb Smirnoff { "paramprob", ICMP_PARAMPROB }, 943b3a8eb9SGleb Smirnoff { "timereq", ICMP_TSTAMP }, 953b3a8eb9SGleb Smirnoff { "timerep", ICMP_TSTAMPREPLY }, 963b3a8eb9SGleb Smirnoff { "inforeq", ICMP_IREQ }, 973b3a8eb9SGleb Smirnoff { "inforep", ICMP_IREQREPLY }, 983b3a8eb9SGleb Smirnoff { "maskreq", ICMP_MASKREQ }, 993b3a8eb9SGleb Smirnoff { "maskrep", ICMP_MASKREPLY }, 1003b3a8eb9SGleb Smirnoff { "trace", ICMP_TRACEROUTE }, 1013b3a8eb9SGleb Smirnoff { "dataconv", ICMP_DATACONVERR }, 1023b3a8eb9SGleb Smirnoff { "mobredir", ICMP_MOBILE_REDIRECT }, 1033b3a8eb9SGleb Smirnoff { "ipv6-where", ICMP_IPV6_WHEREAREYOU }, 1043b3a8eb9SGleb Smirnoff { "ipv6-here", ICMP_IPV6_IAMHERE }, 1053b3a8eb9SGleb Smirnoff { "mobregreq", ICMP_MOBILE_REGREQUEST }, 1063b3a8eb9SGleb Smirnoff { "mobregrep", ICMP_MOBILE_REGREPLY }, 1073b3a8eb9SGleb Smirnoff { "skip", ICMP_SKIP }, 1083b3a8eb9SGleb Smirnoff { "photuris", ICMP_PHOTURIS } 1093b3a8eb9SGleb Smirnoff }; 1103b3a8eb9SGleb Smirnoff 1113b3a8eb9SGleb Smirnoff static const struct icmptypeent icmp6_type[] = { 1123b3a8eb9SGleb Smirnoff { "unreach", ICMP6_DST_UNREACH }, 1133b3a8eb9SGleb Smirnoff { "toobig", ICMP6_PACKET_TOO_BIG }, 1143b3a8eb9SGleb Smirnoff { "timex", ICMP6_TIME_EXCEEDED }, 1153b3a8eb9SGleb Smirnoff { "paramprob", ICMP6_PARAM_PROB }, 1163b3a8eb9SGleb Smirnoff { "echoreq", ICMP6_ECHO_REQUEST }, 1173b3a8eb9SGleb Smirnoff { "echorep", ICMP6_ECHO_REPLY }, 1183b3a8eb9SGleb Smirnoff { "groupqry", ICMP6_MEMBERSHIP_QUERY }, 1193b3a8eb9SGleb Smirnoff { "listqry", MLD_LISTENER_QUERY }, 1203b3a8eb9SGleb Smirnoff { "grouprep", ICMP6_MEMBERSHIP_REPORT }, 1213b3a8eb9SGleb Smirnoff { "listenrep", MLD_LISTENER_REPORT }, 1223b3a8eb9SGleb Smirnoff { "groupterm", ICMP6_MEMBERSHIP_REDUCTION }, 1233b3a8eb9SGleb Smirnoff { "listendone", MLD_LISTENER_DONE }, 1243b3a8eb9SGleb Smirnoff { "routersol", ND_ROUTER_SOLICIT }, 1253b3a8eb9SGleb Smirnoff { "routeradv", ND_ROUTER_ADVERT }, 1263b3a8eb9SGleb Smirnoff { "neighbrsol", ND_NEIGHBOR_SOLICIT }, 1273b3a8eb9SGleb Smirnoff { "neighbradv", ND_NEIGHBOR_ADVERT }, 1283b3a8eb9SGleb Smirnoff { "redir", ND_REDIRECT }, 1293b3a8eb9SGleb Smirnoff { "routrrenum", ICMP6_ROUTER_RENUMBERING }, 1303b3a8eb9SGleb Smirnoff { "wrureq", ICMP6_WRUREQUEST }, 1313b3a8eb9SGleb Smirnoff { "wrurep", ICMP6_WRUREPLY }, 1323b3a8eb9SGleb Smirnoff { "fqdnreq", ICMP6_FQDN_QUERY }, 1333b3a8eb9SGleb Smirnoff { "fqdnrep", ICMP6_FQDN_REPLY }, 1343b3a8eb9SGleb Smirnoff { "niqry", ICMP6_NI_QUERY }, 1353b3a8eb9SGleb Smirnoff { "nirep", ICMP6_NI_REPLY }, 1363b3a8eb9SGleb Smirnoff { "mtraceresp", MLD_MTRACE_RESP }, 1373b3a8eb9SGleb Smirnoff { "mtrace", MLD_MTRACE } 1383b3a8eb9SGleb Smirnoff }; 1393b3a8eb9SGleb Smirnoff 1403b3a8eb9SGleb Smirnoff static const struct icmpcodeent icmp_code[] = { 1413b3a8eb9SGleb Smirnoff { "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET }, 1423b3a8eb9SGleb Smirnoff { "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST }, 1433b3a8eb9SGleb Smirnoff { "proto-unr", ICMP_UNREACH, ICMP_UNREACH_PROTOCOL }, 1443b3a8eb9SGleb Smirnoff { "port-unr", ICMP_UNREACH, ICMP_UNREACH_PORT }, 1453b3a8eb9SGleb Smirnoff { "needfrag", ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG }, 1463b3a8eb9SGleb Smirnoff { "srcfail", ICMP_UNREACH, ICMP_UNREACH_SRCFAIL }, 1473b3a8eb9SGleb Smirnoff { "net-unk", ICMP_UNREACH, ICMP_UNREACH_NET_UNKNOWN }, 1483b3a8eb9SGleb Smirnoff { "host-unk", ICMP_UNREACH, ICMP_UNREACH_HOST_UNKNOWN }, 1493b3a8eb9SGleb Smirnoff { "isolate", ICMP_UNREACH, ICMP_UNREACH_ISOLATED }, 1503b3a8eb9SGleb Smirnoff { "net-prohib", ICMP_UNREACH, ICMP_UNREACH_NET_PROHIB }, 1513b3a8eb9SGleb Smirnoff { "host-prohib", ICMP_UNREACH, ICMP_UNREACH_HOST_PROHIB }, 1523b3a8eb9SGleb Smirnoff { "net-tos", ICMP_UNREACH, ICMP_UNREACH_TOSNET }, 1533b3a8eb9SGleb Smirnoff { "host-tos", ICMP_UNREACH, ICMP_UNREACH_TOSHOST }, 1543b3a8eb9SGleb Smirnoff { "filter-prohib", ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB }, 1553b3a8eb9SGleb Smirnoff { "host-preced", ICMP_UNREACH, ICMP_UNREACH_HOST_PRECEDENCE }, 1563b3a8eb9SGleb Smirnoff { "cutoff-preced", ICMP_UNREACH, ICMP_UNREACH_PRECEDENCE_CUTOFF }, 1573b3a8eb9SGleb Smirnoff { "redir-net", ICMP_REDIRECT, ICMP_REDIRECT_NET }, 1583b3a8eb9SGleb Smirnoff { "redir-host", ICMP_REDIRECT, ICMP_REDIRECT_HOST }, 1593b3a8eb9SGleb Smirnoff { "redir-tos-net", ICMP_REDIRECT, ICMP_REDIRECT_TOSNET }, 1603b3a8eb9SGleb Smirnoff { "redir-tos-host", ICMP_REDIRECT, ICMP_REDIRECT_TOSHOST }, 1613b3a8eb9SGleb Smirnoff { "normal-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL }, 1623b3a8eb9SGleb Smirnoff { "common-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON }, 1633b3a8eb9SGleb Smirnoff { "transit", ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS }, 1643b3a8eb9SGleb Smirnoff { "reassemb", ICMP_TIMXCEED, ICMP_TIMXCEED_REASS }, 1653b3a8eb9SGleb Smirnoff { "badhead", ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR }, 1663b3a8eb9SGleb Smirnoff { "optmiss", ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT }, 1673b3a8eb9SGleb Smirnoff { "badlen", ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH }, 1683b3a8eb9SGleb Smirnoff { "unknown-ind", ICMP_PHOTURIS, ICMP_PHOTURIS_UNKNOWN_INDEX }, 1693b3a8eb9SGleb Smirnoff { "auth-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_AUTH_FAILED }, 1703b3a8eb9SGleb Smirnoff { "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED } 1713b3a8eb9SGleb Smirnoff }; 1723b3a8eb9SGleb Smirnoff 1733b3a8eb9SGleb Smirnoff static const struct icmpcodeent icmp6_code[] = { 1743b3a8eb9SGleb Smirnoff { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN }, 1753b3a8eb9SGleb Smirnoff { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE }, 1763b3a8eb9SGleb Smirnoff { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR }, 1773b3a8eb9SGleb Smirnoff { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE }, 1783b3a8eb9SGleb Smirnoff { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR }, 1793b3a8eb9SGleb Smirnoff { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT }, 1803b3a8eb9SGleb Smirnoff { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT }, 1813b3a8eb9SGleb Smirnoff { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY }, 1823b3a8eb9SGleb Smirnoff { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER }, 1833b3a8eb9SGleb Smirnoff { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER }, 1843b3a8eb9SGleb Smirnoff { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK }, 1853b3a8eb9SGleb Smirnoff { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER } 1863b3a8eb9SGleb Smirnoff }; 1873b3a8eb9SGleb Smirnoff 1883b3a8eb9SGleb Smirnoff const struct pf_timeout pf_timeouts[] = { 1893b3a8eb9SGleb Smirnoff { "tcp.first", PFTM_TCP_FIRST_PACKET }, 1903b3a8eb9SGleb Smirnoff { "tcp.opening", PFTM_TCP_OPENING }, 1913b3a8eb9SGleb Smirnoff { "tcp.established", PFTM_TCP_ESTABLISHED }, 1923b3a8eb9SGleb Smirnoff { "tcp.closing", PFTM_TCP_CLOSING }, 1933b3a8eb9SGleb Smirnoff { "tcp.finwait", PFTM_TCP_FIN_WAIT }, 1943b3a8eb9SGleb Smirnoff { "tcp.closed", PFTM_TCP_CLOSED }, 1953b3a8eb9SGleb Smirnoff { "tcp.tsdiff", PFTM_TS_DIFF }, 196ca9dbde8SKristof Provost { "sctp.first", PFTM_SCTP_FIRST_PACKET }, 197ca9dbde8SKristof Provost { "sctp.opening", PFTM_SCTP_OPENING }, 198ca9dbde8SKristof Provost { "sctp.established", PFTM_SCTP_ESTABLISHED }, 199ca9dbde8SKristof Provost { "sctp.closing", PFTM_SCTP_CLOSING }, 200ca9dbde8SKristof Provost { "sctp.closed", PFTM_SCTP_CLOSED }, 2013b3a8eb9SGleb Smirnoff { "udp.first", PFTM_UDP_FIRST_PACKET }, 2023b3a8eb9SGleb Smirnoff { "udp.single", PFTM_UDP_SINGLE }, 2033b3a8eb9SGleb Smirnoff { "udp.multiple", PFTM_UDP_MULTIPLE }, 2043b3a8eb9SGleb Smirnoff { "icmp.first", PFTM_ICMP_FIRST_PACKET }, 2053b3a8eb9SGleb Smirnoff { "icmp.error", PFTM_ICMP_ERROR_REPLY }, 2063b3a8eb9SGleb Smirnoff { "other.first", PFTM_OTHER_FIRST_PACKET }, 2073b3a8eb9SGleb Smirnoff { "other.single", PFTM_OTHER_SINGLE }, 2083b3a8eb9SGleb Smirnoff { "other.multiple", PFTM_OTHER_MULTIPLE }, 2093b3a8eb9SGleb Smirnoff { "frag", PFTM_FRAG }, 2103b3a8eb9SGleb Smirnoff { "interval", PFTM_INTERVAL }, 2113b3a8eb9SGleb Smirnoff { "adaptive.start", PFTM_ADAPTIVE_START }, 2123b3a8eb9SGleb Smirnoff { "adaptive.end", PFTM_ADAPTIVE_END }, 2133b3a8eb9SGleb Smirnoff { "src.track", PFTM_SRC_NODE }, 2143b3a8eb9SGleb Smirnoff { NULL, 0 } 2153b3a8eb9SGleb Smirnoff }; 2163b3a8eb9SGleb Smirnoff 2171d34c9daSPatrick Kelsey static struct hsearch_data isgroup_map; 2181d34c9daSPatrick Kelsey 2191d34c9daSPatrick Kelsey static __attribute__((constructor)) void 2201d34c9daSPatrick Kelsey pfctl_parser_init(void) 2211d34c9daSPatrick Kelsey { 2221d34c9daSPatrick Kelsey /* 2231d34c9daSPatrick Kelsey * As hdestroy() will never be called on these tables, it will be 2241d34c9daSPatrick Kelsey * safe to use references into the stored data as keys. 2251d34c9daSPatrick Kelsey */ 2261d34c9daSPatrick Kelsey if (hcreate_r(0, &isgroup_map) == 0) 2271d34c9daSPatrick Kelsey err(1, "Failed to create interface group query response map"); 2281d34c9daSPatrick Kelsey } 2291d34c9daSPatrick Kelsey 2303b3a8eb9SGleb Smirnoff const struct icmptypeent * 2313b3a8eb9SGleb Smirnoff geticmptypebynumber(u_int8_t type, sa_family_t af) 2323b3a8eb9SGleb Smirnoff { 2333b3a8eb9SGleb Smirnoff unsigned int i; 2343b3a8eb9SGleb Smirnoff 2353b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 236c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_type); i++) { 2373b3a8eb9SGleb Smirnoff if (type == icmp_type[i].type) 2383b3a8eb9SGleb Smirnoff return (&icmp_type[i]); 2393b3a8eb9SGleb Smirnoff } 2403b3a8eb9SGleb Smirnoff } else { 241c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_type); i++) { 2423b3a8eb9SGleb Smirnoff if (type == icmp6_type[i].type) 2433b3a8eb9SGleb Smirnoff return (&icmp6_type[i]); 2443b3a8eb9SGleb Smirnoff } 2453b3a8eb9SGleb Smirnoff } 2463b3a8eb9SGleb Smirnoff return (NULL); 2473b3a8eb9SGleb Smirnoff } 2483b3a8eb9SGleb Smirnoff 2493b3a8eb9SGleb Smirnoff const struct icmptypeent * 2503b3a8eb9SGleb Smirnoff geticmptypebyname(char *w, sa_family_t af) 2513b3a8eb9SGleb Smirnoff { 2523b3a8eb9SGleb Smirnoff unsigned int i; 2533b3a8eb9SGleb Smirnoff 2543b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 255c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_type); i++) { 2563b3a8eb9SGleb Smirnoff if (!strcmp(w, icmp_type[i].name)) 2573b3a8eb9SGleb Smirnoff return (&icmp_type[i]); 2583b3a8eb9SGleb Smirnoff } 2593b3a8eb9SGleb Smirnoff } else { 260c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_type); i++) { 2613b3a8eb9SGleb Smirnoff if (!strcmp(w, icmp6_type[i].name)) 2623b3a8eb9SGleb Smirnoff return (&icmp6_type[i]); 2633b3a8eb9SGleb Smirnoff } 2643b3a8eb9SGleb Smirnoff } 2653b3a8eb9SGleb Smirnoff return (NULL); 2663b3a8eb9SGleb Smirnoff } 2673b3a8eb9SGleb Smirnoff 2683b3a8eb9SGleb Smirnoff const struct icmpcodeent * 2693b3a8eb9SGleb Smirnoff geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af) 2703b3a8eb9SGleb Smirnoff { 2713b3a8eb9SGleb Smirnoff unsigned int i; 2723b3a8eb9SGleb Smirnoff 2733b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 274c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_code); i++) { 2753b3a8eb9SGleb Smirnoff if (type == icmp_code[i].type && 2763b3a8eb9SGleb Smirnoff code == icmp_code[i].code) 2773b3a8eb9SGleb Smirnoff return (&icmp_code[i]); 2783b3a8eb9SGleb Smirnoff } 2793b3a8eb9SGleb Smirnoff } else { 280c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_code); i++) { 2813b3a8eb9SGleb Smirnoff if (type == icmp6_code[i].type && 2823b3a8eb9SGleb Smirnoff code == icmp6_code[i].code) 2833b3a8eb9SGleb Smirnoff return (&icmp6_code[i]); 2843b3a8eb9SGleb Smirnoff } 2853b3a8eb9SGleb Smirnoff } 2863b3a8eb9SGleb Smirnoff return (NULL); 2873b3a8eb9SGleb Smirnoff } 2883b3a8eb9SGleb Smirnoff 2893b3a8eb9SGleb Smirnoff const struct icmpcodeent * 2903b3a8eb9SGleb Smirnoff geticmpcodebyname(u_long type, char *w, sa_family_t af) 2913b3a8eb9SGleb Smirnoff { 2923b3a8eb9SGleb Smirnoff unsigned int i; 2933b3a8eb9SGleb Smirnoff 2943b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 295c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_code); i++) { 2963b3a8eb9SGleb Smirnoff if (type == icmp_code[i].type && 2973b3a8eb9SGleb Smirnoff !strcmp(w, icmp_code[i].name)) 2983b3a8eb9SGleb Smirnoff return (&icmp_code[i]); 2993b3a8eb9SGleb Smirnoff } 3003b3a8eb9SGleb Smirnoff } else { 301c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_code); i++) { 3023b3a8eb9SGleb Smirnoff if (type == icmp6_code[i].type && 3033b3a8eb9SGleb Smirnoff !strcmp(w, icmp6_code[i].name)) 3043b3a8eb9SGleb Smirnoff return (&icmp6_code[i]); 3053b3a8eb9SGleb Smirnoff } 3063b3a8eb9SGleb Smirnoff } 3073b3a8eb9SGleb Smirnoff return (NULL); 3083b3a8eb9SGleb Smirnoff } 3093b3a8eb9SGleb Smirnoff 3103b3a8eb9SGleb Smirnoff void 3113b3a8eb9SGleb Smirnoff print_op(u_int8_t op, const char *a1, const char *a2) 3123b3a8eb9SGleb Smirnoff { 3133b3a8eb9SGleb Smirnoff if (op == PF_OP_IRG) 3143b3a8eb9SGleb Smirnoff printf(" %s >< %s", a1, a2); 3153b3a8eb9SGleb Smirnoff else if (op == PF_OP_XRG) 3163b3a8eb9SGleb Smirnoff printf(" %s <> %s", a1, a2); 3173b3a8eb9SGleb Smirnoff else if (op == PF_OP_EQ) 3183b3a8eb9SGleb Smirnoff printf(" = %s", a1); 3193b3a8eb9SGleb Smirnoff else if (op == PF_OP_NE) 3203b3a8eb9SGleb Smirnoff printf(" != %s", a1); 3213b3a8eb9SGleb Smirnoff else if (op == PF_OP_LT) 3223b3a8eb9SGleb Smirnoff printf(" < %s", a1); 3233b3a8eb9SGleb Smirnoff else if (op == PF_OP_LE) 3243b3a8eb9SGleb Smirnoff printf(" <= %s", a1); 3253b3a8eb9SGleb Smirnoff else if (op == PF_OP_GT) 3263b3a8eb9SGleb Smirnoff printf(" > %s", a1); 3273b3a8eb9SGleb Smirnoff else if (op == PF_OP_GE) 3283b3a8eb9SGleb Smirnoff printf(" >= %s", a1); 3293b3a8eb9SGleb Smirnoff else if (op == PF_OP_RRG) 3303b3a8eb9SGleb Smirnoff printf(" %s:%s", a1, a2); 3313b3a8eb9SGleb Smirnoff } 3323b3a8eb9SGleb Smirnoff 3333b3a8eb9SGleb Smirnoff void 3343b3a8eb9SGleb Smirnoff print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int numeric) 3353b3a8eb9SGleb Smirnoff { 3363b3a8eb9SGleb Smirnoff char a1[6], a2[6]; 3373b3a8eb9SGleb Smirnoff struct servent *s; 3383b3a8eb9SGleb Smirnoff 3393b3a8eb9SGleb Smirnoff if (!numeric) 3403b3a8eb9SGleb Smirnoff s = getservbyport(p1, proto); 3413b3a8eb9SGleb Smirnoff else 3423b3a8eb9SGleb Smirnoff s = NULL; 3433b3a8eb9SGleb Smirnoff p1 = ntohs(p1); 3443b3a8eb9SGleb Smirnoff p2 = ntohs(p2); 3453b3a8eb9SGleb Smirnoff snprintf(a1, sizeof(a1), "%u", p1); 3463b3a8eb9SGleb Smirnoff snprintf(a2, sizeof(a2), "%u", p2); 3473b3a8eb9SGleb Smirnoff printf(" port"); 3483b3a8eb9SGleb Smirnoff if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE)) 3493b3a8eb9SGleb Smirnoff print_op(op, s->s_name, a2); 3503b3a8eb9SGleb Smirnoff else 3513b3a8eb9SGleb Smirnoff print_op(op, a1, a2); 3523b3a8eb9SGleb Smirnoff } 3533b3a8eb9SGleb Smirnoff 3543b3a8eb9SGleb Smirnoff void 3553b3a8eb9SGleb Smirnoff print_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax) 3563b3a8eb9SGleb Smirnoff { 3573b3a8eb9SGleb Smirnoff char a1[11], a2[11]; 3583b3a8eb9SGleb Smirnoff 3593b3a8eb9SGleb Smirnoff snprintf(a1, sizeof(a1), "%u", u1); 3603b3a8eb9SGleb Smirnoff snprintf(a2, sizeof(a2), "%u", u2); 3613b3a8eb9SGleb Smirnoff printf(" %s", t); 3623b3a8eb9SGleb Smirnoff if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE)) 3633b3a8eb9SGleb Smirnoff print_op(op, "unknown", a2); 3643b3a8eb9SGleb Smirnoff else 3653b3a8eb9SGleb Smirnoff print_op(op, a1, a2); 3663b3a8eb9SGleb Smirnoff } 3673b3a8eb9SGleb Smirnoff 3683b3a8eb9SGleb Smirnoff void 369347dd053SRichard Scheffenegger print_flags(uint16_t f) 3703b3a8eb9SGleb Smirnoff { 3713b3a8eb9SGleb Smirnoff int i; 3723b3a8eb9SGleb Smirnoff 3733b3a8eb9SGleb Smirnoff for (i = 0; tcpflags[i]; ++i) 3743b3a8eb9SGleb Smirnoff if (f & (1 << i)) 3753b3a8eb9SGleb Smirnoff printf("%c", tcpflags[i]); 3763b3a8eb9SGleb Smirnoff } 3773b3a8eb9SGleb Smirnoff 3783b3a8eb9SGleb Smirnoff void 3793b3a8eb9SGleb Smirnoff print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, 3803b3a8eb9SGleb Smirnoff sa_family_t af, u_int8_t proto, int verbose, int numeric) 3813b3a8eb9SGleb Smirnoff { 3823b3a8eb9SGleb Smirnoff char buf[PF_OSFP_LEN*3]; 3833b3a8eb9SGleb Smirnoff if (src->addr.type == PF_ADDR_ADDRMASK && 3843b3a8eb9SGleb Smirnoff dst->addr.type == PF_ADDR_ADDRMASK && 3853b3a8eb9SGleb Smirnoff PF_AZERO(&src->addr.v.a.addr, AF_INET6) && 3863b3a8eb9SGleb Smirnoff PF_AZERO(&src->addr.v.a.mask, AF_INET6) && 3873b3a8eb9SGleb Smirnoff PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && 3883b3a8eb9SGleb Smirnoff PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && 3893b3a8eb9SGleb Smirnoff !src->neg && !dst->neg && 3903b3a8eb9SGleb Smirnoff !src->port_op && !dst->port_op && 3913b3a8eb9SGleb Smirnoff osfp == PF_OSFP_ANY) 3923b3a8eb9SGleb Smirnoff printf(" all"); 3933b3a8eb9SGleb Smirnoff else { 3943b3a8eb9SGleb Smirnoff printf(" from "); 3953b3a8eb9SGleb Smirnoff if (src->neg) 3963b3a8eb9SGleb Smirnoff printf("! "); 3973b3a8eb9SGleb Smirnoff print_addr(&src->addr, af, verbose); 3983b3a8eb9SGleb Smirnoff if (src->port_op) 3993b3a8eb9SGleb Smirnoff print_port(src->port_op, src->port[0], 4003b3a8eb9SGleb Smirnoff src->port[1], 4013b3a8eb9SGleb Smirnoff proto == IPPROTO_TCP ? "tcp" : "udp", 4023b3a8eb9SGleb Smirnoff numeric); 4033b3a8eb9SGleb Smirnoff if (osfp != PF_OSFP_ANY) 4043b3a8eb9SGleb Smirnoff printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf, 4053b3a8eb9SGleb Smirnoff sizeof(buf))); 4063b3a8eb9SGleb Smirnoff 4073b3a8eb9SGleb Smirnoff printf(" to "); 4083b3a8eb9SGleb Smirnoff if (dst->neg) 4093b3a8eb9SGleb Smirnoff printf("! "); 4103b3a8eb9SGleb Smirnoff print_addr(&dst->addr, af, verbose); 4113b3a8eb9SGleb Smirnoff if (dst->port_op) 4123b3a8eb9SGleb Smirnoff print_port(dst->port_op, dst->port[0], 4133b3a8eb9SGleb Smirnoff dst->port[1], 4143b3a8eb9SGleb Smirnoff proto == IPPROTO_TCP ? "tcp" : "udp", 4153b3a8eb9SGleb Smirnoff numeric); 4163b3a8eb9SGleb Smirnoff } 4173b3a8eb9SGleb Smirnoff } 4183b3a8eb9SGleb Smirnoff 4193b3a8eb9SGleb Smirnoff void 420600bd6ceSKurosawa Takahiro print_pool(struct pfctl_pool *pool, u_int16_t p1, u_int16_t p2, 4213b3a8eb9SGleb Smirnoff sa_family_t af, int id) 4223b3a8eb9SGleb Smirnoff { 4233b3a8eb9SGleb Smirnoff struct pf_pooladdr *pooladdr; 4243b3a8eb9SGleb Smirnoff 4253b3a8eb9SGleb Smirnoff if ((TAILQ_FIRST(&pool->list) != NULL) && 4263b3a8eb9SGleb Smirnoff TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4273b3a8eb9SGleb Smirnoff printf("{ "); 4283b3a8eb9SGleb Smirnoff TAILQ_FOREACH(pooladdr, &pool->list, entries){ 4293b3a8eb9SGleb Smirnoff switch (id) { 4303b3a8eb9SGleb Smirnoff case PF_NAT: 4313b3a8eb9SGleb Smirnoff case PF_RDR: 4323b3a8eb9SGleb Smirnoff case PF_BINAT: 4333b3a8eb9SGleb Smirnoff print_addr(&pooladdr->addr, af, 0); 4343b3a8eb9SGleb Smirnoff break; 4353b3a8eb9SGleb Smirnoff case PF_PASS: 43639282ef3SKajetan Staszkiewicz case PF_MATCH: 4373b3a8eb9SGleb Smirnoff if (PF_AZERO(&pooladdr->addr.v.a.addr, af)) 4383b3a8eb9SGleb Smirnoff printf("%s", pooladdr->ifname); 4393b3a8eb9SGleb Smirnoff else { 4403b3a8eb9SGleb Smirnoff printf("(%s ", pooladdr->ifname); 4413b3a8eb9SGleb Smirnoff print_addr(&pooladdr->addr, af, 0); 4423b3a8eb9SGleb Smirnoff printf(")"); 4433b3a8eb9SGleb Smirnoff } 4443b3a8eb9SGleb Smirnoff break; 4453b3a8eb9SGleb Smirnoff default: 4463b3a8eb9SGleb Smirnoff break; 4473b3a8eb9SGleb Smirnoff } 4483b3a8eb9SGleb Smirnoff if (TAILQ_NEXT(pooladdr, entries) != NULL) 4493b3a8eb9SGleb Smirnoff printf(", "); 4503b3a8eb9SGleb Smirnoff else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4513b3a8eb9SGleb Smirnoff printf(" }"); 4523b3a8eb9SGleb Smirnoff } 4533b3a8eb9SGleb Smirnoff switch (id) { 4543b3a8eb9SGleb Smirnoff case PF_NAT: 4553b3a8eb9SGleb Smirnoff if ((p1 != PF_NAT_PROXY_PORT_LOW || 4563b3a8eb9SGleb Smirnoff p2 != PF_NAT_PROXY_PORT_HIGH) && (p1 != 0 || p2 != 0)) { 4573b3a8eb9SGleb Smirnoff if (p1 == p2) 4583b3a8eb9SGleb Smirnoff printf(" port %u", p1); 4593b3a8eb9SGleb Smirnoff else 4603b3a8eb9SGleb Smirnoff printf(" port %u:%u", p1, p2); 4613b3a8eb9SGleb Smirnoff } 4623b3a8eb9SGleb Smirnoff break; 4633b3a8eb9SGleb Smirnoff case PF_RDR: 4643b3a8eb9SGleb Smirnoff if (p1) { 4653b3a8eb9SGleb Smirnoff printf(" port %u", p1); 4663b3a8eb9SGleb Smirnoff if (p2 && (p2 != p1)) 4673b3a8eb9SGleb Smirnoff printf(":%u", p2); 4683b3a8eb9SGleb Smirnoff } 4693b3a8eb9SGleb Smirnoff break; 4703b3a8eb9SGleb Smirnoff default: 4713b3a8eb9SGleb Smirnoff break; 4723b3a8eb9SGleb Smirnoff } 4733b3a8eb9SGleb Smirnoff switch (pool->opts & PF_POOL_TYPEMASK) { 4743b3a8eb9SGleb Smirnoff case PF_POOL_NONE: 4753b3a8eb9SGleb Smirnoff break; 4763b3a8eb9SGleb Smirnoff case PF_POOL_BITMASK: 4773b3a8eb9SGleb Smirnoff printf(" bitmask"); 4783b3a8eb9SGleb Smirnoff break; 4793b3a8eb9SGleb Smirnoff case PF_POOL_RANDOM: 4803b3a8eb9SGleb Smirnoff printf(" random"); 4813b3a8eb9SGleb Smirnoff break; 4823b3a8eb9SGleb Smirnoff case PF_POOL_SRCHASH: 4833b3a8eb9SGleb Smirnoff printf(" source-hash 0x%08x%08x%08x%08x", 4843b3a8eb9SGleb Smirnoff pool->key.key32[0], pool->key.key32[1], 4853b3a8eb9SGleb Smirnoff pool->key.key32[2], pool->key.key32[3]); 4863b3a8eb9SGleb Smirnoff break; 4873b3a8eb9SGleb Smirnoff case PF_POOL_ROUNDROBIN: 4883b3a8eb9SGleb Smirnoff printf(" round-robin"); 4893b3a8eb9SGleb Smirnoff break; 4903b3a8eb9SGleb Smirnoff } 4913b3a8eb9SGleb Smirnoff if (pool->opts & PF_POOL_STICKYADDR) 4923b3a8eb9SGleb Smirnoff printf(" sticky-address"); 493390dc369STom Jones if (pool->opts & PF_POOL_ENDPI) 494390dc369STom Jones printf(" endpoint-independent"); 4953b3a8eb9SGleb Smirnoff if (id == PF_NAT && p1 == 0 && p2 == 0) 4963b3a8eb9SGleb Smirnoff printf(" static-port"); 4972aa21096SKurosawa Takahiro if (pool->mape.offset > 0) 4982aa21096SKurosawa Takahiro printf(" map-e-portset %u/%u/%u", 4992aa21096SKurosawa Takahiro pool->mape.offset, pool->mape.psidlen, pool->mape.psid); 5003b3a8eb9SGleb Smirnoff } 5013b3a8eb9SGleb Smirnoff 50272a3cf0fSKristof Provost const char * const pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 50372a3cf0fSKristof Provost const char * const pf_lcounters[LCNT_MAX+1] = LCNT_NAMES; 50472a3cf0fSKristof Provost const char * const pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 50572a3cf0fSKristof Provost const char * const pf_scounters[FCNT_MAX+1] = FCNT_NAMES; 5063b3a8eb9SGleb Smirnoff 5073b3a8eb9SGleb Smirnoff void 50880078d9dSKristof Provost print_status(struct pfctl_status *s, struct pfctl_syncookies *cookies, int opts) 5093b3a8eb9SGleb Smirnoff { 51080078d9dSKristof Provost struct pfctl_status_counter *c; 5113b3a8eb9SGleb Smirnoff char statline[80], *running; 5123b3a8eb9SGleb Smirnoff time_t runtime; 5133b3a8eb9SGleb Smirnoff int i; 5143b3a8eb9SGleb Smirnoff char buf[PF_MD5_DIGEST_LENGTH * 2 + 1]; 5153b3a8eb9SGleb Smirnoff static const char hex[] = "0123456789abcdef"; 5163b3a8eb9SGleb Smirnoff 5173b3a8eb9SGleb Smirnoff runtime = time(NULL) - s->since; 5183b3a8eb9SGleb Smirnoff running = s->running ? "Enabled" : "Disabled"; 5193b3a8eb9SGleb Smirnoff 5203b3a8eb9SGleb Smirnoff if (s->since) { 5213b3a8eb9SGleb Smirnoff unsigned int sec, min, hrs, day = runtime; 5223b3a8eb9SGleb Smirnoff 5233b3a8eb9SGleb Smirnoff sec = day % 60; 5243b3a8eb9SGleb Smirnoff day /= 60; 5253b3a8eb9SGleb Smirnoff min = day % 60; 5263b3a8eb9SGleb Smirnoff day /= 60; 5273b3a8eb9SGleb Smirnoff hrs = day % 24; 5283b3a8eb9SGleb Smirnoff day /= 24; 5293b3a8eb9SGleb Smirnoff snprintf(statline, sizeof(statline), 5303b3a8eb9SGleb Smirnoff "Status: %s for %u days %.2u:%.2u:%.2u", 5313b3a8eb9SGleb Smirnoff running, day, hrs, min, sec); 5323b3a8eb9SGleb Smirnoff } else 5333b3a8eb9SGleb Smirnoff snprintf(statline, sizeof(statline), "Status: %s", running); 5343b3a8eb9SGleb Smirnoff printf("%-44s", statline); 5353b3a8eb9SGleb Smirnoff switch (s->debug) { 5363b3a8eb9SGleb Smirnoff case PF_DEBUG_NONE: 5373b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: None"); 5383b3a8eb9SGleb Smirnoff break; 5393b3a8eb9SGleb Smirnoff case PF_DEBUG_URGENT: 5403b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Urgent"); 5413b3a8eb9SGleb Smirnoff break; 5423b3a8eb9SGleb Smirnoff case PF_DEBUG_MISC: 5433b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Misc"); 5443b3a8eb9SGleb Smirnoff break; 5453b3a8eb9SGleb Smirnoff case PF_DEBUG_NOISY: 5463b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Loud"); 5473b3a8eb9SGleb Smirnoff break; 5483b3a8eb9SGleb Smirnoff } 5493b3a8eb9SGleb Smirnoff 5503b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 551735748f3SKristof Provost printf("Hostid: 0x%08x\n", s->hostid); 5523b3a8eb9SGleb Smirnoff 5533b3a8eb9SGleb Smirnoff for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) { 5543b3a8eb9SGleb Smirnoff buf[i + i] = hex[s->pf_chksum[i] >> 4]; 5553b3a8eb9SGleb Smirnoff buf[i + i + 1] = hex[s->pf_chksum[i] & 0x0f]; 5563b3a8eb9SGleb Smirnoff } 5573b3a8eb9SGleb Smirnoff buf[i + i] = '\0'; 5583b3a8eb9SGleb Smirnoff printf("Checksum: 0x%s\n\n", buf); 5593b3a8eb9SGleb Smirnoff } 5603b3a8eb9SGleb Smirnoff 5613b3a8eb9SGleb Smirnoff if (s->ifname[0] != 0) { 5623b3a8eb9SGleb Smirnoff printf("Interface Stats for %-16s %5s %16s\n", 5633b3a8eb9SGleb Smirnoff s->ifname, "IPv4", "IPv6"); 5643b3a8eb9SGleb Smirnoff printf(" %-25s %14llu %16llu\n", "Bytes In", 5653b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[0][0], 5663b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[1][0]); 5673b3a8eb9SGleb Smirnoff printf(" %-25s %14llu %16llu\n", "Bytes Out", 5683b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[0][1], 5693b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[1][1]); 5703b3a8eb9SGleb Smirnoff printf(" Packets In\n"); 5713b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Passed", 5723b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][0][PF_PASS], 5733b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][0][PF_PASS]); 5743b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Blocked", 5753b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][0][PF_DROP], 5763b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][0][PF_DROP]); 5773b3a8eb9SGleb Smirnoff printf(" Packets Out\n"); 5783b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Passed", 5793b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][1][PF_PASS], 5803b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][1][PF_PASS]); 5813b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n\n", "Blocked", 5823b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][1][PF_DROP], 5833b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][1][PF_DROP]); 5843b3a8eb9SGleb Smirnoff } 5853b3a8eb9SGleb Smirnoff printf("%-27s %14s %16s\n", "State Table", "Total", "Rate"); 586846a6e8fSKristof Provost printf(" %-25s %14ju %14s\n", "current entries", s->states, ""); 58780078d9dSKristof Provost TAILQ_FOREACH(c, &s->fcounters, entry) { 588846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 5893b3a8eb9SGleb Smirnoff if (runtime > 0) 5903b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 59180078d9dSKristof Provost (double)c->counter / (double)runtime); 5923b3a8eb9SGleb Smirnoff else 5933b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 5943b3a8eb9SGleb Smirnoff } 5953b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 5963b3a8eb9SGleb Smirnoff printf("Source Tracking Table\n"); 597846a6e8fSKristof Provost printf(" %-25s %14ju %14s\n", "current entries", 5983b3a8eb9SGleb Smirnoff s->src_nodes, ""); 59980078d9dSKristof Provost TAILQ_FOREACH(c, &s->scounters, entry) { 600846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 6013b3a8eb9SGleb Smirnoff if (runtime > 0) 6023b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 60380078d9dSKristof Provost (double)c->counter / (double)runtime); 6043b3a8eb9SGleb Smirnoff else 6053b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6063b3a8eb9SGleb Smirnoff } 6073b3a8eb9SGleb Smirnoff } 6083b3a8eb9SGleb Smirnoff printf("Counters\n"); 60980078d9dSKristof Provost TAILQ_FOREACH(c, &s->counters, entry) { 610846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 6113b3a8eb9SGleb Smirnoff if (runtime > 0) 6123b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 61380078d9dSKristof Provost (double)c->counter / (double)runtime); 6143b3a8eb9SGleb Smirnoff else 6153b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6163b3a8eb9SGleb Smirnoff } 6173b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 6183b3a8eb9SGleb Smirnoff printf("Limit Counters\n"); 61980078d9dSKristof Provost TAILQ_FOREACH(c, &s->lcounters, entry) { 620846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 6213b3a8eb9SGleb Smirnoff if (runtime > 0) 6223b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 62380078d9dSKristof Provost (double)c->counter / (double)runtime); 6243b3a8eb9SGleb Smirnoff else 6253b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6263b3a8eb9SGleb Smirnoff } 627c69121c4SKristof Provost 628c69121c4SKristof Provost printf("Syncookies\n"); 6295062afffSKristof Provost assert(cookies->mode <= PFCTL_SYNCOOKIES_ADAPTIVE); 630c69121c4SKristof Provost printf(" %-25s %s\n", "mode", 6315062afffSKristof Provost PFCTL_SYNCOOKIES_MODE_NAMES[cookies->mode]); 632444a77caSKristof Provost printf(" %-25s %s\n", "active", 633444a77caSKristof Provost s->syncookies_active ? "active" : "inactive"); 634a6173e94SKristof Provost if (opts & PF_OPT_VERBOSE2) { 635a6173e94SKristof Provost printf(" %-25s %d %%\n", "highwater", cookies->highwater); 636a6173e94SKristof Provost printf(" %-25s %d %%\n", "lowwater", cookies->lowwater); 637a6173e94SKristof Provost printf(" %-25s %d\n", "halfopen states", cookies->halfopen_states); 638a6173e94SKristof Provost } 63939282ef3SKajetan Staszkiewicz printf("Reassemble %24s %s\n", 64039282ef3SKajetan Staszkiewicz s->reass & PF_REASS_ENABLED ? "yes" : "no", 64139282ef3SKajetan Staszkiewicz s->reass & PF_REASS_NODF ? "no-df" : "" 64239282ef3SKajetan Staszkiewicz ); 6433b3a8eb9SGleb Smirnoff } 6443b3a8eb9SGleb Smirnoff } 6453b3a8eb9SGleb Smirnoff 6463b3a8eb9SGleb Smirnoff void 64780078d9dSKristof Provost print_running(struct pfctl_status *status) 648fa1d4439SKristof Provost { 649fa1d4439SKristof Provost printf("%s\n", status->running ? "Enabled" : "Disabled"); 650fa1d4439SKristof Provost } 651fa1d4439SKristof Provost 652fa1d4439SKristof Provost void 6539c125336SKristof Provost print_src_node(struct pfctl_src_node *sn, int opts) 6543b3a8eb9SGleb Smirnoff { 6553b3a8eb9SGleb Smirnoff struct pf_addr_wrap aw; 6569c125336SKristof Provost uint64_t min, sec; 6573b3a8eb9SGleb Smirnoff 6583b3a8eb9SGleb Smirnoff memset(&aw, 0, sizeof(aw)); 6593b3a8eb9SGleb Smirnoff if (sn->af == AF_INET) 6603b3a8eb9SGleb Smirnoff aw.v.a.mask.addr32[0] = 0xffffffff; 6613b3a8eb9SGleb Smirnoff else 6623b3a8eb9SGleb Smirnoff memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask)); 6633b3a8eb9SGleb Smirnoff 6643b3a8eb9SGleb Smirnoff aw.v.a.addr = sn->addr; 6653b3a8eb9SGleb Smirnoff print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); 6663b3a8eb9SGleb Smirnoff printf(" -> "); 6673b3a8eb9SGleb Smirnoff aw.v.a.addr = sn->raddr; 668aa69fdf1SKristof Provost print_addr(&aw, sn->naf ? sn->naf : sn->af, opts & PF_OPT_VERBOSE2); 6693b3a8eb9SGleb Smirnoff printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states, 6703b3a8eb9SGleb Smirnoff sn->conn, sn->conn_rate.count / 1000, 6713b3a8eb9SGleb Smirnoff (sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds); 6723b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 6733b3a8eb9SGleb Smirnoff sec = sn->creation % 60; 6743b3a8eb9SGleb Smirnoff sn->creation /= 60; 6753b3a8eb9SGleb Smirnoff min = sn->creation % 60; 6763b3a8eb9SGleb Smirnoff sn->creation /= 60; 6779c125336SKristof Provost printf(" age %.2" PRIu64 ":%.2" PRIu64 ":%.2" PRIu64, 6789c125336SKristof Provost sn->creation, min, sec); 6793b3a8eb9SGleb Smirnoff if (sn->states == 0) { 6803b3a8eb9SGleb Smirnoff sec = sn->expire % 60; 6813b3a8eb9SGleb Smirnoff sn->expire /= 60; 6823b3a8eb9SGleb Smirnoff min = sn->expire % 60; 6833b3a8eb9SGleb Smirnoff sn->expire /= 60; 6849c125336SKristof Provost printf(", expires in %.2" PRIu64 ":%.2" PRIu64 ":%.2" PRIu64, 6853b3a8eb9SGleb Smirnoff sn->expire, min, sec); 6863b3a8eb9SGleb Smirnoff } 6879c125336SKristof Provost printf(", %" PRIu64 " pkts, %" PRIu64 " bytes", 6883b3a8eb9SGleb Smirnoff sn->packets[0] + sn->packets[1], 6893b3a8eb9SGleb Smirnoff sn->bytes[0] + sn->bytes[1]); 6903b3a8eb9SGleb Smirnoff switch (sn->ruletype) { 6913b3a8eb9SGleb Smirnoff case PF_NAT: 6929c125336SKristof Provost if (sn->rule != -1) 6939c125336SKristof Provost printf(", nat rule %u", sn->rule); 6943b3a8eb9SGleb Smirnoff break; 6953b3a8eb9SGleb Smirnoff case PF_RDR: 6969c125336SKristof Provost if (sn->rule != -1) 6979c125336SKristof Provost printf(", rdr rule %u", sn->rule); 6983b3a8eb9SGleb Smirnoff break; 6993b3a8eb9SGleb Smirnoff case PF_PASS: 70039282ef3SKajetan Staszkiewicz case PF_MATCH: 7019c125336SKristof Provost if (sn->rule != -1) 7029c125336SKristof Provost printf(", filter rule %u", sn->rule); 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" }; 840d7e9df4fSKristof Provost int i, ropts; 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++ ? ", " : ""); 919f3ab00c2SKristof Provost if (r->log & PF_LOG_MATCHES) 920f3ab00c2SKristof Provost printf("%smatches", count++ ? ", " : ""); 9213b3a8eb9SGleb Smirnoff if (r->log & PF_LOG_SOCKET_LOOKUP) 9223b3a8eb9SGleb Smirnoff printf("%suser", count++ ? ", " : ""); 9233b3a8eb9SGleb Smirnoff if (r->logif) 9243b3a8eb9SGleb Smirnoff printf("%sto pflog%u", count++ ? ", " : "", 9253b3a8eb9SGleb Smirnoff r->logif); 9263b3a8eb9SGleb Smirnoff printf(")"); 9273b3a8eb9SGleb Smirnoff } 9283b3a8eb9SGleb Smirnoff } 9293b3a8eb9SGleb Smirnoff if (r->quick) 9303b3a8eb9SGleb Smirnoff printf(" quick"); 9313b3a8eb9SGleb Smirnoff if (r->ifname[0]) { 9323b3a8eb9SGleb Smirnoff if (r->ifnot) 9333b3a8eb9SGleb Smirnoff printf(" on ! %s", r->ifname); 9343b3a8eb9SGleb Smirnoff else 9353b3a8eb9SGleb Smirnoff printf(" on %s", r->ifname); 9363b3a8eb9SGleb Smirnoff } 9373b3a8eb9SGleb Smirnoff if (r->rt) { 9383b3a8eb9SGleb Smirnoff if (r->rt == PF_ROUTETO) 9393b3a8eb9SGleb Smirnoff printf(" route-to"); 9403b3a8eb9SGleb Smirnoff else if (r->rt == PF_REPLYTO) 9413b3a8eb9SGleb Smirnoff printf(" reply-to"); 9423b3a8eb9SGleb Smirnoff else if (r->rt == PF_DUPTO) 9433b3a8eb9SGleb Smirnoff printf(" dup-to"); 9443b3a8eb9SGleb Smirnoff printf(" "); 945096efeb6SKristof Provost print_pool(&r->rdr, 0, 0, r->af, PF_PASS); 946ca0e6934SKristof Provost print_pool(&r->route, 0, 0, 947*7a372bdeSKristof Provost r->rule_flag & PFRULE_AFTO && r->rt != PF_REPLYTO ? r->naf : r->af, 948*7a372bdeSKristof Provost PF_PASS); 9493b3a8eb9SGleb Smirnoff } 9503b3a8eb9SGleb Smirnoff if (r->af) { 9513b3a8eb9SGleb Smirnoff if (r->af == AF_INET) 9523b3a8eb9SGleb Smirnoff printf(" inet"); 9533b3a8eb9SGleb Smirnoff else 9543b3a8eb9SGleb Smirnoff printf(" inet6"); 9553b3a8eb9SGleb Smirnoff } 9563b3a8eb9SGleb Smirnoff if (r->proto) { 957858937beSMateusz Guzik const char *protoname; 9583b3a8eb9SGleb Smirnoff 959858937beSMateusz Guzik if ((protoname = pfctl_proto2name(r->proto)) != NULL) 960858937beSMateusz Guzik printf(" proto %s", protoname); 9613b3a8eb9SGleb Smirnoff else 9623b3a8eb9SGleb Smirnoff printf(" proto %u", r->proto); 9633b3a8eb9SGleb Smirnoff } 9643b3a8eb9SGleb Smirnoff print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto, 9653b3a8eb9SGleb Smirnoff verbose, numeric); 9662339ead6SKristof Provost if (r->rcv_ifname[0]) 9672339ead6SKristof Provost printf(" received-on %s", r->rcv_ifname); 9683b3a8eb9SGleb Smirnoff if (r->uid.op) 9693b3a8eb9SGleb Smirnoff print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user", 9703b3a8eb9SGleb Smirnoff UID_MAX); 9713b3a8eb9SGleb Smirnoff if (r->gid.op) 9723b3a8eb9SGleb Smirnoff print_ugid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group", 9733b3a8eb9SGleb Smirnoff GID_MAX); 9743b3a8eb9SGleb Smirnoff if (r->flags || r->flagset) { 9753b3a8eb9SGleb Smirnoff printf(" flags "); 9763b3a8eb9SGleb Smirnoff print_flags(r->flags); 9773b3a8eb9SGleb Smirnoff printf("/"); 9783b3a8eb9SGleb Smirnoff print_flags(r->flagset); 97939282ef3SKajetan Staszkiewicz } else if ((r->action == PF_PASS || r->action == PF_MATCH) && 9803b3a8eb9SGleb Smirnoff (!r->proto || r->proto == IPPROTO_TCP) && 9813b3a8eb9SGleb Smirnoff !(r->rule_flag & PFRULE_FRAGMENT) && 9823b3a8eb9SGleb Smirnoff !anchor_call[0] && r->keep_state) 9833b3a8eb9SGleb Smirnoff printf(" flags any"); 9843b3a8eb9SGleb Smirnoff if (r->type) { 9853b3a8eb9SGleb Smirnoff const struct icmptypeent *it; 9863b3a8eb9SGleb Smirnoff 9873b3a8eb9SGleb Smirnoff it = geticmptypebynumber(r->type-1, r->af); 9883b3a8eb9SGleb Smirnoff if (r->af != AF_INET6) 9893b3a8eb9SGleb Smirnoff printf(" icmp-type"); 9903b3a8eb9SGleb Smirnoff else 9913b3a8eb9SGleb Smirnoff printf(" icmp6-type"); 9923b3a8eb9SGleb Smirnoff if (it != NULL) 9933b3a8eb9SGleb Smirnoff printf(" %s", it->name); 9943b3a8eb9SGleb Smirnoff else 9953b3a8eb9SGleb Smirnoff printf(" %u", r->type-1); 9963b3a8eb9SGleb Smirnoff if (r->code) { 9973b3a8eb9SGleb Smirnoff const struct icmpcodeent *ic; 9983b3a8eb9SGleb Smirnoff 9993b3a8eb9SGleb Smirnoff ic = geticmpcodebynumber(r->type-1, r->code-1, r->af); 10003b3a8eb9SGleb Smirnoff if (ic != NULL) 10013b3a8eb9SGleb Smirnoff printf(" code %s", ic->name); 10023b3a8eb9SGleb Smirnoff else 10033b3a8eb9SGleb Smirnoff printf(" code %u", r->code-1); 10043b3a8eb9SGleb Smirnoff } 10053b3a8eb9SGleb Smirnoff } 10063b3a8eb9SGleb Smirnoff if (r->tos) 10073b3a8eb9SGleb Smirnoff printf(" tos 0x%2.2x", r->tos); 10083e248e0fSKristof Provost if (r->prio) 10093e248e0fSKristof Provost printf(" prio %u", r->prio == PF_PRIO_ZERO ? 0 : r->prio); 10103e248e0fSKristof Provost if (r->scrub_flags & PFSTATE_SETMASK) { 10113e248e0fSKristof Provost char *comma = ""; 10123e248e0fSKristof Provost printf(" set ("); 10133e248e0fSKristof Provost if (r->scrub_flags & PFSTATE_SETPRIO) { 10143e248e0fSKristof Provost if (r->set_prio[0] == r->set_prio[1]) 10153e248e0fSKristof Provost printf("%s prio %u", comma, r->set_prio[0]); 10163e248e0fSKristof Provost else 10173e248e0fSKristof Provost printf("%s prio(%u, %u)", comma, r->set_prio[0], 10183e248e0fSKristof Provost r->set_prio[1]); 10193e248e0fSKristof Provost comma = ","; 10203e248e0fSKristof Provost } 102139282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_SETTOS) { 102239282ef3SKajetan Staszkiewicz printf("%s tos 0x%2.2x", comma, r->set_tos); 102339282ef3SKajetan Staszkiewicz comma = ","; 102439282ef3SKajetan Staszkiewicz } 10253e248e0fSKristof Provost printf(" )"); 10263e248e0fSKristof Provost } 10273b3a8eb9SGleb Smirnoff if (!r->keep_state && r->action == PF_PASS && !anchor_call[0]) 10283b3a8eb9SGleb Smirnoff printf(" no state"); 10293b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_NORMAL) 10303b3a8eb9SGleb Smirnoff printf(" keep state"); 10313b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_MODULATE) 10323b3a8eb9SGleb Smirnoff printf(" modulate state"); 10333b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_SYNPROXY) 10343b3a8eb9SGleb Smirnoff printf(" synproxy state"); 10353b3a8eb9SGleb Smirnoff if (r->prob) { 10363b3a8eb9SGleb Smirnoff char buf[20]; 10373b3a8eb9SGleb Smirnoff 10383b3a8eb9SGleb Smirnoff snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0)); 10393b3a8eb9SGleb Smirnoff for (i = strlen(buf)-1; i > 0; i--) { 10403b3a8eb9SGleb Smirnoff if (buf[i] == '0') 10413b3a8eb9SGleb Smirnoff buf[i] = '\0'; 10423b3a8eb9SGleb Smirnoff else { 10433b3a8eb9SGleb Smirnoff if (buf[i] == '.') 10443b3a8eb9SGleb Smirnoff buf[i] = '\0'; 10453b3a8eb9SGleb Smirnoff break; 10463b3a8eb9SGleb Smirnoff } 10473b3a8eb9SGleb Smirnoff } 10483b3a8eb9SGleb Smirnoff printf(" probability %s%%", buf); 10493b3a8eb9SGleb Smirnoff } 1050d7e9df4fSKristof Provost ropts = 0; 10513b3a8eb9SGleb Smirnoff if (r->max_states || r->max_src_nodes || r->max_src_states) 1052d7e9df4fSKristof Provost ropts = 1; 10533b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NOSYNC) 1054d7e9df4fSKristof Provost ropts = 1; 10553b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SRCTRACK) 1056d7e9df4fSKristof Provost ropts = 1; 10573b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_IFBOUND) 1058d7e9df4fSKristof Provost ropts = 1; 10593b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY) 1060d7e9df4fSKristof Provost ropts = 1; 1061baf9b6d0SKristof Provost if (r->rule_flag & PFRULE_PFLOW) 1062d7e9df4fSKristof Provost ropts = 1; 1063d7e9df4fSKristof Provost for (i = 0; !ropts && i < PFTM_MAX; ++i) 10643b3a8eb9SGleb Smirnoff if (r->timeout[i]) 1065d7e9df4fSKristof Provost ropts = 1; 1066d7e9df4fSKristof Provost if (ropts) { 10673b3a8eb9SGleb Smirnoff printf(" ("); 10683b3a8eb9SGleb Smirnoff if (r->max_states) { 10693b3a8eb9SGleb Smirnoff printf("max %u", r->max_states); 1070d7e9df4fSKristof Provost ropts = 0; 10713b3a8eb9SGleb Smirnoff } 10723b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NOSYNC) { 1073d7e9df4fSKristof Provost if (!ropts) 10743b3a8eb9SGleb Smirnoff printf(", "); 10753b3a8eb9SGleb Smirnoff printf("no-sync"); 1076d7e9df4fSKristof Provost ropts = 0; 10773b3a8eb9SGleb Smirnoff } 10783b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SRCTRACK) { 1079d7e9df4fSKristof Provost if (!ropts) 10803b3a8eb9SGleb Smirnoff printf(", "); 10813b3a8eb9SGleb Smirnoff printf("source-track"); 10823b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RULESRCTRACK) 10833b3a8eb9SGleb Smirnoff printf(" rule"); 10843b3a8eb9SGleb Smirnoff else 10853b3a8eb9SGleb Smirnoff printf(" global"); 1086d7e9df4fSKristof Provost ropts = 0; 10873b3a8eb9SGleb Smirnoff } 10883b3a8eb9SGleb Smirnoff if (r->max_src_states) { 1089d7e9df4fSKristof Provost if (!ropts) 10903b3a8eb9SGleb Smirnoff printf(", "); 10913b3a8eb9SGleb Smirnoff printf("max-src-states %u", r->max_src_states); 1092d7e9df4fSKristof Provost ropts = 0; 10933b3a8eb9SGleb Smirnoff } 10943b3a8eb9SGleb Smirnoff if (r->max_src_conn) { 1095d7e9df4fSKristof Provost if (!ropts) 10963b3a8eb9SGleb Smirnoff printf(", "); 10973b3a8eb9SGleb Smirnoff printf("max-src-conn %u", r->max_src_conn); 1098d7e9df4fSKristof Provost ropts = 0; 10993b3a8eb9SGleb Smirnoff } 11003b3a8eb9SGleb Smirnoff if (r->max_src_conn_rate.limit) { 1101d7e9df4fSKristof Provost if (!ropts) 11023b3a8eb9SGleb Smirnoff printf(", "); 11033b3a8eb9SGleb Smirnoff printf("max-src-conn-rate %u/%u", 11043b3a8eb9SGleb Smirnoff r->max_src_conn_rate.limit, 11053b3a8eb9SGleb Smirnoff r->max_src_conn_rate.seconds); 1106d7e9df4fSKristof Provost ropts = 0; 11073b3a8eb9SGleb Smirnoff } 11083b3a8eb9SGleb Smirnoff if (r->max_src_nodes) { 1109d7e9df4fSKristof Provost if (!ropts) 11103b3a8eb9SGleb Smirnoff printf(", "); 11113b3a8eb9SGleb Smirnoff printf("max-src-nodes %u", r->max_src_nodes); 1112d7e9df4fSKristof Provost ropts = 0; 11133b3a8eb9SGleb Smirnoff } 11143b3a8eb9SGleb Smirnoff if (r->overload_tblname[0]) { 1115d7e9df4fSKristof Provost if (!ropts) 11163b3a8eb9SGleb Smirnoff printf(", "); 11173b3a8eb9SGleb Smirnoff printf("overload <%s>", r->overload_tblname); 11183b3a8eb9SGleb Smirnoff if (r->flush) 11193b3a8eb9SGleb Smirnoff printf(" flush"); 11203b3a8eb9SGleb Smirnoff if (r->flush & PF_FLUSH_GLOBAL) 11213b3a8eb9SGleb Smirnoff printf(" global"); 11223b3a8eb9SGleb Smirnoff } 11233b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_IFBOUND) { 1124d7e9df4fSKristof Provost if (!ropts) 11253b3a8eb9SGleb Smirnoff printf(", "); 11263b3a8eb9SGleb Smirnoff printf("if-bound"); 1127d7e9df4fSKristof Provost ropts = 0; 11283b3a8eb9SGleb Smirnoff } 11293b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY) { 1130d7e9df4fSKristof Provost if (!ropts) 11313b3a8eb9SGleb Smirnoff printf(", "); 11323b3a8eb9SGleb Smirnoff printf("sloppy"); 1133d7e9df4fSKristof Provost ropts = 0; 11343b3a8eb9SGleb Smirnoff } 1135baf9b6d0SKristof Provost if (r->rule_flag & PFRULE_PFLOW) { 1136d7e9df4fSKristof Provost if (!ropts) 1137baf9b6d0SKristof Provost printf(", "); 1138baf9b6d0SKristof Provost printf("pflow"); 1139d7e9df4fSKristof Provost ropts = 0; 1140baf9b6d0SKristof Provost } 11413b3a8eb9SGleb Smirnoff for (i = 0; i < PFTM_MAX; ++i) 11423b3a8eb9SGleb Smirnoff if (r->timeout[i]) { 11433b3a8eb9SGleb Smirnoff int j; 11443b3a8eb9SGleb Smirnoff 1145d7e9df4fSKristof Provost if (!ropts) 11463b3a8eb9SGleb Smirnoff printf(", "); 1147d7e9df4fSKristof Provost ropts = 0; 11483b3a8eb9SGleb Smirnoff for (j = 0; pf_timeouts[j].name != NULL; 11493b3a8eb9SGleb Smirnoff ++j) 11503b3a8eb9SGleb Smirnoff if (pf_timeouts[j].timeout == i) 11513b3a8eb9SGleb Smirnoff break; 11523b3a8eb9SGleb Smirnoff printf("%s %u", pf_timeouts[j].name == NULL ? 11533b3a8eb9SGleb Smirnoff "inv.timeout" : pf_timeouts[j].name, 11543b3a8eb9SGleb Smirnoff r->timeout[i]); 11553b3a8eb9SGleb Smirnoff } 11563b3a8eb9SGleb Smirnoff printf(")"); 11573b3a8eb9SGleb Smirnoff } 115839282ef3SKajetan Staszkiewicz if (r->allow_opts) 115939282ef3SKajetan Staszkiewicz printf(" allow-opts"); 11603b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_FRAGMENT) 11613b3a8eb9SGleb Smirnoff printf(" fragment"); 116239282ef3SKajetan Staszkiewicz if (r->action == PF_SCRUB) { 116339282ef3SKajetan Staszkiewicz /* Scrub flags for old-style scrub. */ 11643b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NODF) 11653b3a8eb9SGleb Smirnoff printf(" no-df"); 11663b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RANDOMID) 11673b3a8eb9SGleb Smirnoff printf(" random-id"); 11683b3a8eb9SGleb Smirnoff if (r->min_ttl) 11693b3a8eb9SGleb Smirnoff printf(" min-ttl %d", r->min_ttl); 11703b3a8eb9SGleb Smirnoff if (r->max_mss) 11713b3a8eb9SGleb Smirnoff printf(" max-mss %d", r->max_mss); 11723b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SET_TOS) 11733b3a8eb9SGleb Smirnoff printf(" set-tos 0x%2.2x", r->set_tos); 11743b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_REASSEMBLE_TCP) 11753b3a8eb9SGleb Smirnoff printf(" reassemble tcp"); 117639282ef3SKajetan Staszkiewicz /* The PFRULE_FRAGMENT_NOREASS is set on all rules by default! */ 117757e047e5SKristof Provost printf(" fragment %sreassemble", 117857e047e5SKristof Provost r->rule_flag & PFRULE_FRAGMENT_NOREASS ? "no " : ""); 117939282ef3SKajetan Staszkiewicz } else if (r->scrub_flags & PFSTATE_SCRUBMASK || r->min_ttl || r->max_mss) { 118039282ef3SKajetan Staszkiewicz /* Scrub actions on normal rules. */ 118139282ef3SKajetan Staszkiewicz printf(" scrub("); 118239282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_NODF) 118339282ef3SKajetan Staszkiewicz printf(" no-df"); 118439282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_RANDOMID) 118539282ef3SKajetan Staszkiewicz printf(" random-id"); 118639282ef3SKajetan Staszkiewicz if (r->min_ttl) 118739282ef3SKajetan Staszkiewicz printf(" min-ttl %d", r->min_ttl); 118839282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_SETTOS) 118939282ef3SKajetan Staszkiewicz printf(" set-tos 0x%2.2x", r->set_tos); 119039282ef3SKajetan Staszkiewicz if (r->scrub_flags & PFSTATE_SCRUB_TCP) 119139282ef3SKajetan Staszkiewicz printf(" reassemble tcp"); 119239282ef3SKajetan Staszkiewicz if (r->max_mss) 119339282ef3SKajetan Staszkiewicz printf(" max-mss %d", r->max_mss); 119439282ef3SKajetan Staszkiewicz printf(")"); 11953b3a8eb9SGleb Smirnoff } 11966fcc8e04SKristof Provost i = 0; 11976fcc8e04SKristof Provost while (r->label[i][0]) 11986fcc8e04SKristof Provost printf(" label \"%s\"", r->label[i++]); 119976c5eeccSKristof Provost if (r->ridentifier) 120076c5eeccSKristof Provost printf(" ridentifier %u", r->ridentifier); 120163b3c1c7SKristof Provost /* Only dnrpipe as we might do (0, 42) to only queue return traffic. */ 120263b3c1c7SKristof Provost if (r->dnrpipe) 120363b3c1c7SKristof Provost printf(" %s(%d, %d)", 120463b3c1c7SKristof Provost r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", 120563b3c1c7SKristof Provost r->dnpipe, r->dnrpipe); 120663b3c1c7SKristof Provost else if (r->dnpipe) 120763b3c1c7SKristof Provost printf(" %s %d", 120863b3c1c7SKristof Provost r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", 120963b3c1c7SKristof Provost r->dnpipe); 12103b3a8eb9SGleb Smirnoff if (r->qname[0] && r->pqname[0]) 12113b3a8eb9SGleb Smirnoff printf(" queue(%s, %s)", r->qname, r->pqname); 12123b3a8eb9SGleb Smirnoff else if (r->qname[0]) 12133b3a8eb9SGleb Smirnoff printf(" queue %s", r->qname); 12143b3a8eb9SGleb Smirnoff if (r->tagname[0]) 12153b3a8eb9SGleb Smirnoff printf(" tag %s", r->tagname); 12163b3a8eb9SGleb Smirnoff if (r->match_tagname[0]) { 12173b3a8eb9SGleb Smirnoff if (r->match_tag_not) 12183b3a8eb9SGleb Smirnoff printf(" !"); 12193b3a8eb9SGleb Smirnoff printf(" tagged %s", r->match_tagname); 12203b3a8eb9SGleb Smirnoff } 12213b3a8eb9SGleb Smirnoff if (r->rtableid != -1) 12223b3a8eb9SGleb Smirnoff printf(" rtable %u", r->rtableid); 12233b3a8eb9SGleb Smirnoff if (r->divert.port) { 12243b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 12253b3a8eb9SGleb Smirnoff printf(" divert-to %u", ntohs(r->divert.port)); 12263b3a8eb9SGleb Smirnoff #else 12273b3a8eb9SGleb Smirnoff if (PF_AZERO(&r->divert.addr, r->af)) { 12283b3a8eb9SGleb Smirnoff printf(" divert-reply"); 12293b3a8eb9SGleb Smirnoff } else { 12303b3a8eb9SGleb Smirnoff /* XXX cut&paste from print_addr */ 12313b3a8eb9SGleb Smirnoff char buf[48]; 12323b3a8eb9SGleb Smirnoff 12333b3a8eb9SGleb Smirnoff printf(" divert-to "); 12343b3a8eb9SGleb Smirnoff if (inet_ntop(r->af, &r->divert.addr, buf, 12353b3a8eb9SGleb Smirnoff sizeof(buf)) == NULL) 12363b3a8eb9SGleb Smirnoff printf("?"); 12373b3a8eb9SGleb Smirnoff else 12383b3a8eb9SGleb Smirnoff printf("%s", buf); 12393b3a8eb9SGleb Smirnoff printf(" port %u", ntohs(r->divert.port)); 12403b3a8eb9SGleb Smirnoff } 12413b3a8eb9SGleb Smirnoff #endif 12423b3a8eb9SGleb Smirnoff } 1243aa69fdf1SKristof Provost if (!anchor_call[0] && ! TAILQ_EMPTY(&r->nat.list) && 1244f88019e8SKristof Provost r->rule_flag & PFRULE_AFTO) { 1245aa69fdf1SKristof Provost printf(" af-to %s from ", r->naf == AF_INET ? "inet" : "inet6"); 1246aa69fdf1SKristof Provost print_pool(&r->nat, r->nat.proxy_port[0], r->nat.proxy_port[1], 1247aa69fdf1SKristof Provost r->naf ? r->naf : r->af, PF_NAT); 1248aa69fdf1SKristof Provost if (r->rdr.cur != NULL && !TAILQ_EMPTY(&r->rdr.list)) { 1249aa69fdf1SKristof Provost printf(" to "); 1250aa69fdf1SKristof Provost print_pool(&r->rdr, r->rdr.proxy_port[0], 1251aa69fdf1SKristof Provost r->rdr.proxy_port[1], r->naf ? r->naf : r->af, 1252aa69fdf1SKristof Provost PF_RDR); 1253aa69fdf1SKristof Provost } 1254aa69fdf1SKristof Provost } 1255aa69fdf1SKristof Provost if (!anchor_call[0] && 1256aa69fdf1SKristof Provost (r->action == PF_NAT || r->action == PF_BINAT || 1257aa69fdf1SKristof Provost r->action == PF_RDR)) { 12583b3a8eb9SGleb Smirnoff printf(" -> "); 1259096efeb6SKristof Provost print_pool(&r->rdr, r->rdr.proxy_port[0], 1260096efeb6SKristof Provost r->rdr.proxy_port[1], r->af, r->action); 12613b3a8eb9SGleb Smirnoff } 12623b3a8eb9SGleb Smirnoff } 12633b3a8eb9SGleb Smirnoff 12643b3a8eb9SGleb Smirnoff void 12653b3a8eb9SGleb Smirnoff print_tabledef(const char *name, int flags, int addrs, 12663b3a8eb9SGleb Smirnoff struct node_tinithead *nodes) 12673b3a8eb9SGleb Smirnoff { 12683b3a8eb9SGleb Smirnoff struct node_tinit *ti, *nti; 12693b3a8eb9SGleb Smirnoff struct node_host *h; 12703b3a8eb9SGleb Smirnoff 12713b3a8eb9SGleb Smirnoff printf("table <%s>", name); 12723b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_CONST) 12733b3a8eb9SGleb Smirnoff printf(" const"); 12743b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_PERSIST) 12753b3a8eb9SGleb Smirnoff printf(" persist"); 12763b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_COUNTERS) 12773b3a8eb9SGleb Smirnoff printf(" counters"); 12783b3a8eb9SGleb Smirnoff SIMPLEQ_FOREACH(ti, nodes, entries) { 12793b3a8eb9SGleb Smirnoff if (ti->file) { 12803b3a8eb9SGleb Smirnoff printf(" file \"%s\"", ti->file); 12813b3a8eb9SGleb Smirnoff continue; 12823b3a8eb9SGleb Smirnoff } 12833b3a8eb9SGleb Smirnoff printf(" {"); 12843b3a8eb9SGleb Smirnoff for (;;) { 12853b3a8eb9SGleb Smirnoff for (h = ti->host; h != NULL; h = h->next) { 12863b3a8eb9SGleb Smirnoff printf(h->not ? " !" : " "); 12873b3a8eb9SGleb Smirnoff print_addr(&h->addr, h->af, 0); 12883b3a8eb9SGleb Smirnoff } 12893b3a8eb9SGleb Smirnoff nti = SIMPLEQ_NEXT(ti, entries); 12903b3a8eb9SGleb Smirnoff if (nti != NULL && nti->file == NULL) 12913b3a8eb9SGleb Smirnoff ti = nti; /* merge lists */ 12923b3a8eb9SGleb Smirnoff else 12933b3a8eb9SGleb Smirnoff break; 12943b3a8eb9SGleb Smirnoff } 12953b3a8eb9SGleb Smirnoff printf(" }"); 12963b3a8eb9SGleb Smirnoff } 12973b3a8eb9SGleb Smirnoff if (addrs && SIMPLEQ_EMPTY(nodes)) 12983b3a8eb9SGleb Smirnoff printf(" { }"); 12993b3a8eb9SGleb Smirnoff printf("\n"); 13003b3a8eb9SGleb Smirnoff } 13013b3a8eb9SGleb Smirnoff 13023b3a8eb9SGleb Smirnoff int 13033b3a8eb9SGleb Smirnoff parse_flags(char *s) 13043b3a8eb9SGleb Smirnoff { 13053b3a8eb9SGleb Smirnoff char *p, *q; 1306347dd053SRichard Scheffenegger uint16_t f = 0; 13073b3a8eb9SGleb Smirnoff 13083b3a8eb9SGleb Smirnoff for (p = s; *p; p++) { 13093b3a8eb9SGleb Smirnoff if ((q = strchr(tcpflags, *p)) == NULL) 13103b3a8eb9SGleb Smirnoff return -1; 13113b3a8eb9SGleb Smirnoff else 13123b3a8eb9SGleb Smirnoff f |= 1 << (q - tcpflags); 13133b3a8eb9SGleb Smirnoff } 1314347dd053SRichard Scheffenegger return (f ? f : TH_FLAGS); 13153b3a8eb9SGleb Smirnoff } 13163b3a8eb9SGleb Smirnoff 13173b3a8eb9SGleb Smirnoff void 13183b3a8eb9SGleb Smirnoff set_ipmask(struct node_host *h, u_int8_t b) 13193b3a8eb9SGleb Smirnoff { 13203b3a8eb9SGleb Smirnoff struct pf_addr *m, *n; 13213b3a8eb9SGleb Smirnoff int i, j = 0; 13223b3a8eb9SGleb Smirnoff 13233b3a8eb9SGleb Smirnoff m = &h->addr.v.a.mask; 13243b3a8eb9SGleb Smirnoff memset(m, 0, sizeof(*m)); 13253b3a8eb9SGleb Smirnoff 13263b3a8eb9SGleb Smirnoff while (b >= 32) { 13273b3a8eb9SGleb Smirnoff m->addr32[j++] = 0xffffffff; 13283b3a8eb9SGleb Smirnoff b -= 32; 13293b3a8eb9SGleb Smirnoff } 13303b3a8eb9SGleb Smirnoff for (i = 31; i > 31-b; --i) 13313b3a8eb9SGleb Smirnoff m->addr32[j] |= (1 << i); 13323b3a8eb9SGleb Smirnoff if (b) 13333b3a8eb9SGleb Smirnoff m->addr32[j] = htonl(m->addr32[j]); 13343b3a8eb9SGleb Smirnoff 13353b3a8eb9SGleb Smirnoff /* Mask off bits of the address that will never be used. */ 13363b3a8eb9SGleb Smirnoff n = &h->addr.v.a.addr; 13373b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_ADDRMASK) 13383b3a8eb9SGleb Smirnoff for (i = 0; i < 4; i++) 13393b3a8eb9SGleb Smirnoff n->addr32[i] = n->addr32[i] & m->addr32[i]; 13403b3a8eb9SGleb Smirnoff } 13413b3a8eb9SGleb Smirnoff 13423b3a8eb9SGleb Smirnoff int 13433b3a8eb9SGleb Smirnoff check_netmask(struct node_host *h, sa_family_t af) 13443b3a8eb9SGleb Smirnoff { 13453b3a8eb9SGleb Smirnoff struct node_host *n = NULL; 13463b3a8eb9SGleb Smirnoff struct pf_addr *m; 13473b3a8eb9SGleb Smirnoff 13483b3a8eb9SGleb Smirnoff for (n = h; n != NULL; n = n->next) { 13493b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_TABLE) 13503b3a8eb9SGleb Smirnoff continue; 13513b3a8eb9SGleb Smirnoff m = &h->addr.v.a.mask; 13523b3a8eb9SGleb Smirnoff /* netmasks > 32 bit are invalid on v4 */ 13533b3a8eb9SGleb Smirnoff if (af == AF_INET && 13543b3a8eb9SGleb Smirnoff (m->addr32[1] || m->addr32[2] || m->addr32[3])) { 13553b3a8eb9SGleb Smirnoff fprintf(stderr, "netmask %u invalid for IPv4 address\n", 13563b3a8eb9SGleb Smirnoff unmask(m, AF_INET6)); 13573b3a8eb9SGleb Smirnoff return (1); 13583b3a8eb9SGleb Smirnoff } 13593b3a8eb9SGleb Smirnoff } 13603b3a8eb9SGleb Smirnoff return (0); 13613b3a8eb9SGleb Smirnoff } 13623b3a8eb9SGleb Smirnoff 13637ce98cf2SKristof Provost struct node_host * 13647ce98cf2SKristof Provost gen_dynnode(struct node_host *h, sa_family_t af) 13657ce98cf2SKristof Provost { 13667ce98cf2SKristof Provost struct node_host *n; 13677ce98cf2SKristof Provost struct pf_addr *m; 13687ce98cf2SKristof Provost 13697ce98cf2SKristof Provost if (h->addr.type != PF_ADDR_DYNIFTL) 13707ce98cf2SKristof Provost return (NULL); 13717ce98cf2SKristof Provost 13727ce98cf2SKristof Provost if ((n = calloc(1, sizeof(*n))) == NULL) 13737ce98cf2SKristof Provost return (NULL); 13747ce98cf2SKristof Provost bcopy(h, n, sizeof(*n)); 13757ce98cf2SKristof Provost n->ifname = NULL; 13767ce98cf2SKristof Provost n->next = NULL; 13777ce98cf2SKristof Provost n->tail = NULL; 13787ce98cf2SKristof Provost 13797ce98cf2SKristof Provost /* fix up netmask */ 13807ce98cf2SKristof Provost m = &n->addr.v.a.mask; 13817ce98cf2SKristof Provost if (af == AF_INET && unmask(m, AF_INET6) > 32) 13827ce98cf2SKristof Provost set_ipmask(n, 32); 13837ce98cf2SKristof Provost 13847ce98cf2SKristof Provost return (n); 13857ce98cf2SKristof Provost } 13867ce98cf2SKristof Provost 13873b3a8eb9SGleb Smirnoff /* interface lookup routines */ 13883b3a8eb9SGleb Smirnoff 138913cfafabSKristof Provost static struct node_host *iftab; 13903b3a8eb9SGleb Smirnoff 13911d34c9daSPatrick Kelsey /* 13921d34c9daSPatrick Kelsey * Retrieve the list of groups this interface is a member of and make sure 13931d34c9daSPatrick Kelsey * each group is in the group map. 13941d34c9daSPatrick Kelsey */ 13951d34c9daSPatrick Kelsey static void 13961d34c9daSPatrick Kelsey ifa_add_groups_to_map(char *ifa_name) 13971d34c9daSPatrick Kelsey { 13981d34c9daSPatrick Kelsey int s, len; 13991d34c9daSPatrick Kelsey struct ifgroupreq ifgr; 14001d34c9daSPatrick Kelsey struct ifg_req *ifg; 14011d34c9daSPatrick Kelsey 14021d34c9daSPatrick Kelsey s = get_query_socket(); 14031d34c9daSPatrick Kelsey 14041d34c9daSPatrick Kelsey /* Get size of group list for this interface */ 14051d34c9daSPatrick Kelsey memset(&ifgr, 0, sizeof(ifgr)); 14061d34c9daSPatrick Kelsey strlcpy(ifgr.ifgr_name, ifa_name, IFNAMSIZ); 14071d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 14081d34c9daSPatrick Kelsey err(1, "SIOCGIFGROUP"); 14091d34c9daSPatrick Kelsey 14101d34c9daSPatrick Kelsey /* Retrieve group list for this interface */ 14111d34c9daSPatrick Kelsey len = ifgr.ifgr_len; 14121d34c9daSPatrick Kelsey ifgr.ifgr_groups = 14131d34c9daSPatrick Kelsey (struct ifg_req *)calloc(len / sizeof(struct ifg_req), 14141d34c9daSPatrick Kelsey sizeof(struct ifg_req)); 14151d34c9daSPatrick Kelsey if (ifgr.ifgr_groups == NULL) 14161d34c9daSPatrick Kelsey err(1, "calloc"); 14171d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 14181d34c9daSPatrick Kelsey err(1, "SIOCGIFGROUP"); 14191d34c9daSPatrick Kelsey 14201d34c9daSPatrick Kelsey ifg = ifgr.ifgr_groups; 14211d34c9daSPatrick Kelsey for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 14221d34c9daSPatrick Kelsey len -= sizeof(struct ifg_req); 14231d34c9daSPatrick Kelsey if (strcmp(ifg->ifgrq_group, "all")) { 14241d34c9daSPatrick Kelsey ENTRY item; 14251d34c9daSPatrick Kelsey ENTRY *ret_item; 14261d34c9daSPatrick Kelsey int *answer; 14271d34c9daSPatrick Kelsey 14281d34c9daSPatrick Kelsey item.key = ifg->ifgrq_group; 14291d34c9daSPatrick Kelsey if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) { 14301d34c9daSPatrick Kelsey struct ifgroupreq ifgr2; 14311d34c9daSPatrick Kelsey 14321d34c9daSPatrick Kelsey /* Don't know the answer yet */ 14331d34c9daSPatrick Kelsey if ((answer = malloc(sizeof(int))) == NULL) 14341d34c9daSPatrick Kelsey err(1, "malloc"); 14351d34c9daSPatrick Kelsey 14361d34c9daSPatrick Kelsey bzero(&ifgr2, sizeof(ifgr2)); 14371d34c9daSPatrick Kelsey strlcpy(ifgr2.ifgr_name, ifg->ifgrq_group, 14381d34c9daSPatrick Kelsey sizeof(ifgr2.ifgr_name)); 14391d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr2) == 0) 14401d34c9daSPatrick Kelsey *answer = ifgr2.ifgr_len; 14411d34c9daSPatrick Kelsey else 14421d34c9daSPatrick Kelsey *answer = 0; 14431d34c9daSPatrick Kelsey 14441d34c9daSPatrick Kelsey item.key = strdup(ifg->ifgrq_group); 14451d34c9daSPatrick Kelsey item.data = answer; 14461d34c9daSPatrick Kelsey if (hsearch_r(item, ENTER, &ret_item, 14471d34c9daSPatrick Kelsey &isgroup_map) == 0) 14481d34c9daSPatrick Kelsey err(1, "interface group query response" 14491d34c9daSPatrick Kelsey " map insert"); 14501d34c9daSPatrick Kelsey } 14511d34c9daSPatrick Kelsey } 14521d34c9daSPatrick Kelsey } 14531d34c9daSPatrick Kelsey free(ifgr.ifgr_groups); 14541d34c9daSPatrick Kelsey } 14551d34c9daSPatrick Kelsey 14563b3a8eb9SGleb Smirnoff void 14573b3a8eb9SGleb Smirnoff ifa_load(void) 14583b3a8eb9SGleb Smirnoff { 14593b3a8eb9SGleb Smirnoff struct ifaddrs *ifap, *ifa; 14603b3a8eb9SGleb Smirnoff struct node_host *n = NULL, *h = NULL; 14613b3a8eb9SGleb Smirnoff 14623b3a8eb9SGleb Smirnoff if (getifaddrs(&ifap) < 0) 14633b3a8eb9SGleb Smirnoff err(1, "getifaddrs"); 14643b3a8eb9SGleb Smirnoff 14653b3a8eb9SGleb Smirnoff for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 14663b3a8eb9SGleb Smirnoff if (!(ifa->ifa_addr->sa_family == AF_INET || 14673b3a8eb9SGleb Smirnoff ifa->ifa_addr->sa_family == AF_INET6 || 14683b3a8eb9SGleb Smirnoff ifa->ifa_addr->sa_family == AF_LINK)) 14693b3a8eb9SGleb Smirnoff continue; 14703b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 14713b3a8eb9SGleb Smirnoff if (n == NULL) 14723b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 14733b3a8eb9SGleb Smirnoff n->af = ifa->ifa_addr->sa_family; 14743b3a8eb9SGleb Smirnoff n->ifa_flags = ifa->ifa_flags; 14753b3a8eb9SGleb Smirnoff #ifdef __KAME__ 14763b3a8eb9SGleb Smirnoff if (n->af == AF_INET6 && 14773b3a8eb9SGleb Smirnoff IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) 14783b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_addr) && 14793b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 14803b3a8eb9SGleb Smirnoff 0) { 14813b3a8eb9SGleb Smirnoff struct sockaddr_in6 *sin6; 14823b3a8eb9SGleb Smirnoff 14833b3a8eb9SGleb Smirnoff sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 14843b3a8eb9SGleb Smirnoff sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | 14853b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[3]; 14863b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[2] = 0; 14873b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[3] = 0; 14883b3a8eb9SGleb Smirnoff } 14893b3a8eb9SGleb Smirnoff #endif 14903b3a8eb9SGleb Smirnoff n->ifindex = 0; 14913b3a8eb9SGleb Smirnoff if (n->af == AF_INET) { 14923b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) 14933b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin_addr.s_addr, 14943b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 14953b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) 14963b3a8eb9SGleb Smirnoff ifa->ifa_netmask)->sin_addr.s_addr, 14973b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 14983b3a8eb9SGleb Smirnoff if (ifa->ifa_broadaddr != NULL) 14993b3a8eb9SGleb Smirnoff memcpy(&n->bcast, &((struct sockaddr_in *) 15003b3a8eb9SGleb Smirnoff ifa->ifa_broadaddr)->sin_addr.s_addr, 15013b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 15023b3a8eb9SGleb Smirnoff if (ifa->ifa_dstaddr != NULL) 15033b3a8eb9SGleb Smirnoff memcpy(&n->peer, &((struct sockaddr_in *) 15043b3a8eb9SGleb Smirnoff ifa->ifa_dstaddr)->sin_addr.s_addr, 15053b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 15063b3a8eb9SGleb Smirnoff } else if (n->af == AF_INET6) { 15073b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) 15083b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_addr.s6_addr, 15093b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 15103b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) 15113b3a8eb9SGleb Smirnoff ifa->ifa_netmask)->sin6_addr.s6_addr, 15123b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 15133b3a8eb9SGleb Smirnoff if (ifa->ifa_broadaddr != NULL) 15143b3a8eb9SGleb Smirnoff memcpy(&n->bcast, &((struct sockaddr_in6 *) 15153b3a8eb9SGleb Smirnoff ifa->ifa_broadaddr)->sin6_addr.s6_addr, 15163b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 15173b3a8eb9SGleb Smirnoff if (ifa->ifa_dstaddr != NULL) 15183b3a8eb9SGleb Smirnoff memcpy(&n->peer, &((struct sockaddr_in6 *) 15193b3a8eb9SGleb Smirnoff ifa->ifa_dstaddr)->sin6_addr.s6_addr, 15203b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 15213b3a8eb9SGleb Smirnoff n->ifindex = ((struct sockaddr_in6 *) 15223b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_scope_id; 15231d34c9daSPatrick Kelsey } else if (n->af == AF_LINK) { 15241d34c9daSPatrick Kelsey ifa_add_groups_to_map(ifa->ifa_name); 15253b3a8eb9SGleb Smirnoff } 15263b3a8eb9SGleb Smirnoff if ((n->ifname = strdup(ifa->ifa_name)) == NULL) 15273b3a8eb9SGleb Smirnoff err(1, "ifa_load: strdup"); 15283b3a8eb9SGleb Smirnoff n->next = NULL; 15293b3a8eb9SGleb Smirnoff n->tail = n; 15303b3a8eb9SGleb Smirnoff if (h == NULL) 15313b3a8eb9SGleb Smirnoff h = n; 15323b3a8eb9SGleb Smirnoff else { 15333b3a8eb9SGleb Smirnoff h->tail->next = n; 15343b3a8eb9SGleb Smirnoff h->tail = n; 15353b3a8eb9SGleb Smirnoff } 15363b3a8eb9SGleb Smirnoff } 15373b3a8eb9SGleb Smirnoff 15383b3a8eb9SGleb Smirnoff iftab = h; 15393b3a8eb9SGleb Smirnoff freeifaddrs(ifap); 15403b3a8eb9SGleb Smirnoff } 15413b3a8eb9SGleb Smirnoff 15421d34c9daSPatrick Kelsey static int 1543f870cb7fSBjoern A. Zeeb get_socket_domain(void) 1544f870cb7fSBjoern A. Zeeb { 1545f870cb7fSBjoern A. Zeeb int sdom; 1546f870cb7fSBjoern A. Zeeb 1547f870cb7fSBjoern A. Zeeb sdom = AF_UNSPEC; 1548f870cb7fSBjoern A. Zeeb #ifdef WITH_INET6 1549f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC && feature_present("inet6")) 1550f870cb7fSBjoern A. Zeeb sdom = AF_INET6; 1551f870cb7fSBjoern A. Zeeb #endif 1552f870cb7fSBjoern A. Zeeb #ifdef WITH_INET 1553f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC && feature_present("inet")) 1554f870cb7fSBjoern A. Zeeb sdom = AF_INET; 1555f870cb7fSBjoern A. Zeeb #endif 1556f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC) 1557f870cb7fSBjoern A. Zeeb sdom = AF_LINK; 1558f870cb7fSBjoern A. Zeeb 1559f870cb7fSBjoern A. Zeeb return (sdom); 1560f870cb7fSBjoern A. Zeeb } 1561f870cb7fSBjoern A. Zeeb 15621d34c9daSPatrick Kelsey int 15631d34c9daSPatrick Kelsey get_query_socket(void) 15641d34c9daSPatrick Kelsey { 15651d34c9daSPatrick Kelsey static int s = -1; 15661d34c9daSPatrick Kelsey 15671d34c9daSPatrick Kelsey if (s == -1) { 15681d34c9daSPatrick Kelsey if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) 15691d34c9daSPatrick Kelsey err(1, "socket"); 15701d34c9daSPatrick Kelsey } 15711d34c9daSPatrick Kelsey 15721d34c9daSPatrick Kelsey return (s); 15731d34c9daSPatrick Kelsey } 15741d34c9daSPatrick Kelsey 15751d34c9daSPatrick Kelsey /* 15761d34c9daSPatrick Kelsey * Returns the response len if the name is a group, otherwise returns 0. 15771d34c9daSPatrick Kelsey */ 15781d34c9daSPatrick Kelsey static int 15791d34c9daSPatrick Kelsey is_a_group(char *name) 15801d34c9daSPatrick Kelsey { 15811d34c9daSPatrick Kelsey ENTRY item; 15821d34c9daSPatrick Kelsey ENTRY *ret_item; 15831d34c9daSPatrick Kelsey 15841d34c9daSPatrick Kelsey item.key = name; 15851d34c9daSPatrick Kelsey if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) 15861d34c9daSPatrick Kelsey return (0); 15871d34c9daSPatrick Kelsey 15881d34c9daSPatrick Kelsey return (*(int *)ret_item->data); 15891d34c9daSPatrick Kelsey } 15901d34c9daSPatrick Kelsey 15913b3a8eb9SGleb Smirnoff struct node_host * 15921d34c9daSPatrick Kelsey ifa_exists(char *ifa_name) 15933b3a8eb9SGleb Smirnoff { 15943b3a8eb9SGleb Smirnoff struct node_host *n; 15953b3a8eb9SGleb Smirnoff 15963b3a8eb9SGleb Smirnoff if (iftab == NULL) 15973b3a8eb9SGleb Smirnoff ifa_load(); 15983b3a8eb9SGleb Smirnoff 15991d34c9daSPatrick Kelsey /* check whether this is a group */ 16001d34c9daSPatrick Kelsey if (is_a_group(ifa_name)) { 16013b3a8eb9SGleb Smirnoff /* fake a node_host */ 16023b3a8eb9SGleb Smirnoff if ((n = calloc(1, sizeof(*n))) == NULL) 16033b3a8eb9SGleb Smirnoff err(1, "calloc"); 16043b3a8eb9SGleb Smirnoff if ((n->ifname = strdup(ifa_name)) == NULL) 16053b3a8eb9SGleb Smirnoff err(1, "strdup"); 16063b3a8eb9SGleb Smirnoff return (n); 16073b3a8eb9SGleb Smirnoff } 16083b3a8eb9SGleb Smirnoff 16093b3a8eb9SGleb Smirnoff for (n = iftab; n; n = n->next) { 16103b3a8eb9SGleb Smirnoff if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) 16113b3a8eb9SGleb Smirnoff return (n); 16123b3a8eb9SGleb Smirnoff } 16133b3a8eb9SGleb Smirnoff 16143b3a8eb9SGleb Smirnoff return (NULL); 16153b3a8eb9SGleb Smirnoff } 16163b3a8eb9SGleb Smirnoff 16173b3a8eb9SGleb Smirnoff struct node_host * 16181d34c9daSPatrick Kelsey ifa_grouplookup(char *ifa_name, int flags) 16193b3a8eb9SGleb Smirnoff { 16203b3a8eb9SGleb Smirnoff struct ifg_req *ifg; 16213b3a8eb9SGleb Smirnoff struct ifgroupreq ifgr; 16223b3a8eb9SGleb Smirnoff int s, len; 16233b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 16243b3a8eb9SGleb Smirnoff 16251d34c9daSPatrick Kelsey s = get_query_socket(); 16261d34c9daSPatrick Kelsey len = is_a_group(ifa_name); 16271d34c9daSPatrick Kelsey if (len == 0) 16281d34c9daSPatrick Kelsey return (NULL); 16293b3a8eb9SGleb Smirnoff bzero(&ifgr, sizeof(ifgr)); 16303b3a8eb9SGleb Smirnoff strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); 16314c8fb952SKristof Provost ifgr.ifgr_len = len; 16323b3a8eb9SGleb Smirnoff if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 16333b3a8eb9SGleb Smirnoff err(1, "calloc"); 16343b3a8eb9SGleb Smirnoff if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 16353b3a8eb9SGleb Smirnoff err(1, "SIOCGIFGMEMB"); 16363b3a8eb9SGleb Smirnoff 16373b3a8eb9SGleb Smirnoff for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req); 16383b3a8eb9SGleb Smirnoff ifg++) { 16393b3a8eb9SGleb Smirnoff len -= sizeof(struct ifg_req); 1640d5b08e13SKristof Provost if ((n = ifa_lookup(ifg->ifgrq_member, flags)) == NULL) 16413b3a8eb9SGleb Smirnoff continue; 16423b3a8eb9SGleb Smirnoff if (h == NULL) 16433b3a8eb9SGleb Smirnoff h = n; 16443b3a8eb9SGleb Smirnoff else { 16453b3a8eb9SGleb Smirnoff h->tail->next = n; 16463b3a8eb9SGleb Smirnoff h->tail = n->tail; 16473b3a8eb9SGleb Smirnoff } 16483b3a8eb9SGleb Smirnoff } 16493b3a8eb9SGleb Smirnoff free(ifgr.ifgr_groups); 16503b3a8eb9SGleb Smirnoff 16513b3a8eb9SGleb Smirnoff return (h); 16523b3a8eb9SGleb Smirnoff } 16533b3a8eb9SGleb Smirnoff 16543b3a8eb9SGleb Smirnoff struct node_host * 16551d34c9daSPatrick Kelsey ifa_lookup(char *ifa_name, int flags) 16563b3a8eb9SGleb Smirnoff { 16573b3a8eb9SGleb Smirnoff struct node_host *p = NULL, *h = NULL, *n = NULL; 16583b3a8eb9SGleb Smirnoff int got4 = 0, got6 = 0; 16593b3a8eb9SGleb Smirnoff const char *last_if = NULL; 16603b3a8eb9SGleb Smirnoff 16618fd675d8SKristof Provost /* first load iftab and isgroup_map */ 16628fd675d8SKristof Provost if (iftab == NULL) 16638fd675d8SKristof Provost ifa_load(); 16648fd675d8SKristof Provost 16653b3a8eb9SGleb Smirnoff if ((h = ifa_grouplookup(ifa_name, flags)) != NULL) 16663b3a8eb9SGleb Smirnoff return (h); 16673b3a8eb9SGleb Smirnoff 16683b3a8eb9SGleb Smirnoff if (!strncmp(ifa_name, "self", IFNAMSIZ)) 16693b3a8eb9SGleb Smirnoff ifa_name = NULL; 16703b3a8eb9SGleb Smirnoff 16713b3a8eb9SGleb Smirnoff for (p = iftab; p; p = p->next) { 16723b3a8eb9SGleb Smirnoff if (ifa_skip_if(ifa_name, p)) 16733b3a8eb9SGleb Smirnoff continue; 16743b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET) 16753b3a8eb9SGleb Smirnoff continue; 16763b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_BROADCAST) && 16773b3a8eb9SGleb Smirnoff !(p->ifa_flags & IFF_BROADCAST)) 16783b3a8eb9SGleb Smirnoff continue; 16793b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_PEER) && 16803b3a8eb9SGleb Smirnoff !(p->ifa_flags & IFF_POINTOPOINT)) 16813b3a8eb9SGleb Smirnoff continue; 16823b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NETWORK) && p->ifindex > 0) 16833b3a8eb9SGleb Smirnoff continue; 16843b3a8eb9SGleb Smirnoff if (last_if == NULL || strcmp(last_if, p->ifname)) 16853b3a8eb9SGleb Smirnoff got4 = got6 = 0; 16863b3a8eb9SGleb Smirnoff last_if = p->ifname; 16873b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET && got4) 16883b3a8eb9SGleb Smirnoff continue; 168999eb0055SKristof Provost if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && 169099eb0055SKristof Provost IN6_IS_ADDR_LINKLOCAL(&p->addr.v.a.addr.v6)) 169199eb0055SKristof Provost continue; 16923b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && got6) 16933b3a8eb9SGleb Smirnoff continue; 16943b3a8eb9SGleb Smirnoff if (p->af == AF_INET) 16953b3a8eb9SGleb Smirnoff got4 = 1; 16963b3a8eb9SGleb Smirnoff else 16973b3a8eb9SGleb Smirnoff got6 = 1; 16983b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 16993b3a8eb9SGleb Smirnoff if (n == NULL) 17003b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 17013b3a8eb9SGleb Smirnoff n->af = p->af; 17023b3a8eb9SGleb Smirnoff if (flags & PFI_AFLAG_BROADCAST) 17033b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->bcast, 17043b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 17053b3a8eb9SGleb Smirnoff else if (flags & PFI_AFLAG_PEER) 17063b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->peer, 17073b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 17083b3a8eb9SGleb Smirnoff else 17093b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, 17103b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 17113b3a8eb9SGleb Smirnoff if (flags & PFI_AFLAG_NETWORK) 17123b3a8eb9SGleb Smirnoff set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); 17133b3a8eb9SGleb Smirnoff else { 17143b3a8eb9SGleb Smirnoff if (n->af == AF_INET) { 17153b3a8eb9SGleb Smirnoff if (p->ifa_flags & IFF_LOOPBACK && 17163b3a8eb9SGleb Smirnoff p->ifa_flags & IFF_LINK1) 17173b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, 17183b3a8eb9SGleb Smirnoff &p->addr.v.a.mask, 17193b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 17203b3a8eb9SGleb Smirnoff else 17213b3a8eb9SGleb Smirnoff set_ipmask(n, 32); 17223b3a8eb9SGleb Smirnoff } else 17233b3a8eb9SGleb Smirnoff set_ipmask(n, 128); 17243b3a8eb9SGleb Smirnoff } 17253b3a8eb9SGleb Smirnoff n->ifindex = p->ifindex; 17260f9e47a9SKristof Provost n->ifname = strdup(p->ifname); 17273b3a8eb9SGleb Smirnoff 17283b3a8eb9SGleb Smirnoff n->next = NULL; 17293b3a8eb9SGleb Smirnoff n->tail = n; 17303b3a8eb9SGleb Smirnoff if (h == NULL) 17313b3a8eb9SGleb Smirnoff h = n; 17323b3a8eb9SGleb Smirnoff else { 17333b3a8eb9SGleb Smirnoff h->tail->next = n; 17343b3a8eb9SGleb Smirnoff h->tail = n; 17353b3a8eb9SGleb Smirnoff } 17363b3a8eb9SGleb Smirnoff } 17373b3a8eb9SGleb Smirnoff return (h); 17383b3a8eb9SGleb Smirnoff } 17393b3a8eb9SGleb Smirnoff 17403b3a8eb9SGleb Smirnoff int 17413b3a8eb9SGleb Smirnoff ifa_skip_if(const char *filter, struct node_host *p) 17423b3a8eb9SGleb Smirnoff { 17433b3a8eb9SGleb Smirnoff int n; 17443b3a8eb9SGleb Smirnoff 17453b3a8eb9SGleb Smirnoff if (p->af != AF_INET && p->af != AF_INET6) 17463b3a8eb9SGleb Smirnoff return (1); 17473b3a8eb9SGleb Smirnoff if (filter == NULL || !*filter) 17483b3a8eb9SGleb Smirnoff return (0); 17493b3a8eb9SGleb Smirnoff if (!strcmp(p->ifname, filter)) 17503b3a8eb9SGleb Smirnoff return (0); /* exact match */ 17513b3a8eb9SGleb Smirnoff n = strlen(filter); 17523b3a8eb9SGleb Smirnoff if (n < 1 || n >= IFNAMSIZ) 17533b3a8eb9SGleb Smirnoff return (1); /* sanity check */ 17543b3a8eb9SGleb Smirnoff if (filter[n-1] >= '0' && filter[n-1] <= '9') 17553b3a8eb9SGleb Smirnoff return (1); /* only do exact match in that case */ 17563b3a8eb9SGleb Smirnoff if (strncmp(p->ifname, filter, n)) 17573b3a8eb9SGleb Smirnoff return (1); /* prefix doesn't match */ 17583b3a8eb9SGleb Smirnoff return (p->ifname[n] < '0' || p->ifname[n] > '9'); 17593b3a8eb9SGleb Smirnoff } 17603b3a8eb9SGleb Smirnoff 17613b3a8eb9SGleb Smirnoff 17623b3a8eb9SGleb Smirnoff struct node_host * 17633b3a8eb9SGleb Smirnoff host(const char *s) 17643b3a8eb9SGleb Smirnoff { 17653b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 17663b3a8eb9SGleb Smirnoff int mask, v4mask, v6mask, cont = 1; 17673b3a8eb9SGleb Smirnoff char *p, *q, *ps; 17683b3a8eb9SGleb Smirnoff 17693b3a8eb9SGleb Smirnoff if ((p = strrchr(s, '/')) != NULL) { 17703b3a8eb9SGleb Smirnoff mask = strtol(p+1, &q, 0); 17713b3a8eb9SGleb Smirnoff if (!q || *q || mask > 128 || q == (p+1)) { 17723b3a8eb9SGleb Smirnoff fprintf(stderr, "invalid netmask '%s'\n", p); 17733b3a8eb9SGleb Smirnoff return (NULL); 17743b3a8eb9SGleb Smirnoff } 17753b3a8eb9SGleb Smirnoff if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 17763b3a8eb9SGleb Smirnoff err(1, "host: malloc"); 17773b3a8eb9SGleb Smirnoff strlcpy(ps, s, strlen(s) - strlen(p) + 1); 17783b3a8eb9SGleb Smirnoff v4mask = v6mask = mask; 17793b3a8eb9SGleb Smirnoff } else { 17803b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 17813b3a8eb9SGleb Smirnoff err(1, "host: strdup"); 17823b3a8eb9SGleb Smirnoff v4mask = 32; 17833b3a8eb9SGleb Smirnoff v6mask = 128; 17843b3a8eb9SGleb Smirnoff mask = -1; 17853b3a8eb9SGleb Smirnoff } 17863b3a8eb9SGleb Smirnoff 17873b3a8eb9SGleb Smirnoff /* IPv4 address? */ 17883b3a8eb9SGleb Smirnoff if (cont && (h = host_v4(s, mask)) != NULL) 17893b3a8eb9SGleb Smirnoff cont = 0; 17903b3a8eb9SGleb Smirnoff 17913b3a8eb9SGleb Smirnoff /* IPv6 address? */ 17923b3a8eb9SGleb Smirnoff if (cont && (h = host_v6(ps, v6mask)) != NULL) 17933b3a8eb9SGleb Smirnoff cont = 0; 17943b3a8eb9SGleb Smirnoff 1795d2568b02SKristof Provost /* interface with this name exists? */ 1796d2568b02SKristof Provost /* expensive with thousands of interfaces - prioritze IPv4/6 check */ 179728b64169SFranco Fichtner if (cont && (h = host_if(ps, mask, &cont)) != NULL) 1798d2568b02SKristof Provost cont = 0; 1799d2568b02SKristof Provost 18003b3a8eb9SGleb Smirnoff /* dns lookup */ 18013b3a8eb9SGleb Smirnoff if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL) 18023b3a8eb9SGleb Smirnoff cont = 0; 18033b3a8eb9SGleb Smirnoff free(ps); 18043b3a8eb9SGleb Smirnoff 18053b3a8eb9SGleb Smirnoff if (h == NULL || cont == 1) { 18063b3a8eb9SGleb Smirnoff fprintf(stderr, "no IP address found for %s\n", s); 18073b3a8eb9SGleb Smirnoff return (NULL); 18083b3a8eb9SGleb Smirnoff } 18093b3a8eb9SGleb Smirnoff return (h); 18103b3a8eb9SGleb Smirnoff } 18113b3a8eb9SGleb Smirnoff 18123b3a8eb9SGleb Smirnoff struct node_host * 181328b64169SFranco Fichtner host_if(const char *s, int mask, int *cont) 18143b3a8eb9SGleb Smirnoff { 18153b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 18163b3a8eb9SGleb Smirnoff char *p, *ps; 18173b3a8eb9SGleb Smirnoff int flags = 0; 18183b3a8eb9SGleb Smirnoff 18193b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 18203b3a8eb9SGleb Smirnoff err(1, "host_if: strdup"); 18213b3a8eb9SGleb Smirnoff while ((p = strrchr(ps, ':')) != NULL) { 18223b3a8eb9SGleb Smirnoff if (!strcmp(p+1, "network")) 18233b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NETWORK; 18243b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "broadcast")) 18253b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_BROADCAST; 18263b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "peer")) 18273b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_PEER; 18283b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "0")) 18293b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NOALIAS; 18303b3a8eb9SGleb Smirnoff else { 18313b3a8eb9SGleb Smirnoff free(ps); 18323b3a8eb9SGleb Smirnoff return (NULL); 18333b3a8eb9SGleb Smirnoff } 18343b3a8eb9SGleb Smirnoff *p = '\0'; 183528b64169SFranco Fichtner *cont = 0; 18363b3a8eb9SGleb Smirnoff } 18373b3a8eb9SGleb Smirnoff if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */ 18383b3a8eb9SGleb Smirnoff fprintf(stderr, "illegal combination of interface modifiers\n"); 18393b3a8eb9SGleb Smirnoff free(ps); 18403b3a8eb9SGleb Smirnoff return (NULL); 18413b3a8eb9SGleb Smirnoff } 18423b3a8eb9SGleb Smirnoff if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) { 18433b3a8eb9SGleb Smirnoff fprintf(stderr, "network or broadcast lookup, but " 18443b3a8eb9SGleb Smirnoff "extra netmask given\n"); 18453b3a8eb9SGleb Smirnoff free(ps); 18463b3a8eb9SGleb Smirnoff return (NULL); 18473b3a8eb9SGleb Smirnoff } 18483b3a8eb9SGleb Smirnoff if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) { 18493b3a8eb9SGleb Smirnoff /* interface with this name exists */ 18503b3a8eb9SGleb Smirnoff h = ifa_lookup(ps, flags); 18513b3a8eb9SGleb Smirnoff for (n = h; n != NULL && mask > -1; n = n->next) 18523b3a8eb9SGleb Smirnoff set_ipmask(n, mask); 18533b3a8eb9SGleb Smirnoff } 18543b3a8eb9SGleb Smirnoff 18553b3a8eb9SGleb Smirnoff free(ps); 18563b3a8eb9SGleb Smirnoff return (h); 18573b3a8eb9SGleb Smirnoff } 18583b3a8eb9SGleb Smirnoff 18593b3a8eb9SGleb Smirnoff struct node_host * 18603b3a8eb9SGleb Smirnoff host_v4(const char *s, int mask) 18613b3a8eb9SGleb Smirnoff { 18623b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 18633b3a8eb9SGleb Smirnoff struct in_addr ina; 18643b3a8eb9SGleb Smirnoff int bits = 32; 18653b3a8eb9SGleb Smirnoff 18663b3a8eb9SGleb Smirnoff memset(&ina, 0, sizeof(struct in_addr)); 18673b3a8eb9SGleb Smirnoff if (strrchr(s, '/') != NULL) { 18683b3a8eb9SGleb Smirnoff if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 18693b3a8eb9SGleb Smirnoff return (NULL); 18703b3a8eb9SGleb Smirnoff } else { 18713b3a8eb9SGleb Smirnoff if (inet_pton(AF_INET, s, &ina) != 1) 18723b3a8eb9SGleb Smirnoff return (NULL); 18733b3a8eb9SGleb Smirnoff } 18743b3a8eb9SGleb Smirnoff 18753b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(struct node_host)); 18763b3a8eb9SGleb Smirnoff if (h == NULL) 18773b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 18783b3a8eb9SGleb Smirnoff h->ifname = NULL; 18793b3a8eb9SGleb Smirnoff h->af = AF_INET; 18803b3a8eb9SGleb Smirnoff h->addr.v.a.addr.addr32[0] = ina.s_addr; 18813b3a8eb9SGleb Smirnoff set_ipmask(h, bits); 18823b3a8eb9SGleb Smirnoff h->next = NULL; 18833b3a8eb9SGleb Smirnoff h->tail = h; 18843b3a8eb9SGleb Smirnoff 18853b3a8eb9SGleb Smirnoff return (h); 18863b3a8eb9SGleb Smirnoff } 18873b3a8eb9SGleb Smirnoff 18883b3a8eb9SGleb Smirnoff struct node_host * 18893b3a8eb9SGleb Smirnoff host_v6(const char *s, int mask) 18903b3a8eb9SGleb Smirnoff { 18913b3a8eb9SGleb Smirnoff struct addrinfo hints, *res; 18923b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 18933b3a8eb9SGleb Smirnoff 18943b3a8eb9SGleb Smirnoff memset(&hints, 0, sizeof(hints)); 18953b3a8eb9SGleb Smirnoff hints.ai_family = AF_INET6; 18963b3a8eb9SGleb Smirnoff hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 18973b3a8eb9SGleb Smirnoff hints.ai_flags = AI_NUMERICHOST; 18983b3a8eb9SGleb Smirnoff if (getaddrinfo(s, "0", &hints, &res) == 0) { 18993b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(struct node_host)); 19003b3a8eb9SGleb Smirnoff if (h == NULL) 19013b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 19023b3a8eb9SGleb Smirnoff h->ifname = NULL; 19033b3a8eb9SGleb Smirnoff h->af = AF_INET6; 19043b3a8eb9SGleb Smirnoff memcpy(&h->addr.v.a.addr, 19053b3a8eb9SGleb Smirnoff &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 19063b3a8eb9SGleb Smirnoff sizeof(h->addr.v.a.addr)); 19073b3a8eb9SGleb Smirnoff h->ifindex = 19083b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 19093b3a8eb9SGleb Smirnoff set_ipmask(h, mask); 19103b3a8eb9SGleb Smirnoff freeaddrinfo(res); 19113b3a8eb9SGleb Smirnoff h->next = NULL; 19123b3a8eb9SGleb Smirnoff h->tail = h; 19133b3a8eb9SGleb Smirnoff } 19143b3a8eb9SGleb Smirnoff 19153b3a8eb9SGleb Smirnoff return (h); 19163b3a8eb9SGleb Smirnoff } 19173b3a8eb9SGleb Smirnoff 19183b3a8eb9SGleb Smirnoff struct node_host * 19193b3a8eb9SGleb Smirnoff host_dns(const char *s, int v4mask, int v6mask) 19203b3a8eb9SGleb Smirnoff { 19213b3a8eb9SGleb Smirnoff struct addrinfo hints, *res0, *res; 19223b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 19233b3a8eb9SGleb Smirnoff int error, noalias = 0; 19243b3a8eb9SGleb Smirnoff int got4 = 0, got6 = 0; 19253b3a8eb9SGleb Smirnoff char *p, *ps; 19263b3a8eb9SGleb Smirnoff 19273b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 19283b3a8eb9SGleb Smirnoff err(1, "host_dns: strdup"); 19293b3a8eb9SGleb Smirnoff if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) { 19303b3a8eb9SGleb Smirnoff noalias = 1; 19313b3a8eb9SGleb Smirnoff *p = '\0'; 19323b3a8eb9SGleb Smirnoff } 19333b3a8eb9SGleb Smirnoff memset(&hints, 0, sizeof(hints)); 19343b3a8eb9SGleb Smirnoff hints.ai_family = PF_UNSPEC; 19353b3a8eb9SGleb Smirnoff hints.ai_socktype = SOCK_STREAM; /* DUMMY */ 19363b3a8eb9SGleb Smirnoff error = getaddrinfo(ps, NULL, &hints, &res0); 19373b3a8eb9SGleb Smirnoff if (error) { 19383b3a8eb9SGleb Smirnoff free(ps); 19393b3a8eb9SGleb Smirnoff return (h); 19403b3a8eb9SGleb Smirnoff } 19413b3a8eb9SGleb Smirnoff 19423b3a8eb9SGleb Smirnoff for (res = res0; res; res = res->ai_next) { 19433b3a8eb9SGleb Smirnoff if (res->ai_family != AF_INET && 19443b3a8eb9SGleb Smirnoff res->ai_family != AF_INET6) 19453b3a8eb9SGleb Smirnoff continue; 19463b3a8eb9SGleb Smirnoff if (noalias) { 19473b3a8eb9SGleb Smirnoff if (res->ai_family == AF_INET) { 19483b3a8eb9SGleb Smirnoff if (got4) 19493b3a8eb9SGleb Smirnoff continue; 19503b3a8eb9SGleb Smirnoff got4 = 1; 19513b3a8eb9SGleb Smirnoff } else { 19523b3a8eb9SGleb Smirnoff if (got6) 19533b3a8eb9SGleb Smirnoff continue; 19543b3a8eb9SGleb Smirnoff got6 = 1; 19553b3a8eb9SGleb Smirnoff } 19563b3a8eb9SGleb Smirnoff } 19573b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 19583b3a8eb9SGleb Smirnoff if (n == NULL) 19593b3a8eb9SGleb Smirnoff err(1, "host_dns: calloc"); 19603b3a8eb9SGleb Smirnoff n->ifname = NULL; 19613b3a8eb9SGleb Smirnoff n->af = res->ai_family; 19623b3a8eb9SGleb Smirnoff if (res->ai_family == AF_INET) { 19633b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, 19643b3a8eb9SGleb Smirnoff &((struct sockaddr_in *) 19653b3a8eb9SGleb Smirnoff res->ai_addr)->sin_addr.s_addr, 19663b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 19673b3a8eb9SGleb Smirnoff set_ipmask(n, v4mask); 19683b3a8eb9SGleb Smirnoff } else { 19693b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, 19703b3a8eb9SGleb Smirnoff &((struct sockaddr_in6 *) 19713b3a8eb9SGleb Smirnoff res->ai_addr)->sin6_addr.s6_addr, 19723b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 19733b3a8eb9SGleb Smirnoff n->ifindex = 19743b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *) 19753b3a8eb9SGleb Smirnoff res->ai_addr)->sin6_scope_id; 19763b3a8eb9SGleb Smirnoff set_ipmask(n, v6mask); 19773b3a8eb9SGleb Smirnoff } 19783b3a8eb9SGleb Smirnoff n->next = NULL; 19793b3a8eb9SGleb Smirnoff n->tail = n; 19803b3a8eb9SGleb Smirnoff if (h == NULL) 19813b3a8eb9SGleb Smirnoff h = n; 19823b3a8eb9SGleb Smirnoff else { 19833b3a8eb9SGleb Smirnoff h->tail->next = n; 19843b3a8eb9SGleb Smirnoff h->tail = n; 19853b3a8eb9SGleb Smirnoff } 19863b3a8eb9SGleb Smirnoff } 19873b3a8eb9SGleb Smirnoff freeaddrinfo(res0); 19883b3a8eb9SGleb Smirnoff free(ps); 19893b3a8eb9SGleb Smirnoff 19903b3a8eb9SGleb Smirnoff return (h); 19913b3a8eb9SGleb Smirnoff } 19923b3a8eb9SGleb Smirnoff 19933b3a8eb9SGleb Smirnoff /* 19943b3a8eb9SGleb Smirnoff * convert a hostname to a list of addresses and put them in the given buffer. 19953b3a8eb9SGleb Smirnoff * test: 19963b3a8eb9SGleb Smirnoff * if set to 1, only simple addresses are accepted (no netblock, no "!"). 19973b3a8eb9SGleb Smirnoff */ 19983b3a8eb9SGleb Smirnoff int 19993b3a8eb9SGleb Smirnoff append_addr(struct pfr_buffer *b, char *s, int test) 20003b3a8eb9SGleb Smirnoff { 20013b3a8eb9SGleb Smirnoff char *r; 20023b3a8eb9SGleb Smirnoff struct node_host *h, *n; 20033b3a8eb9SGleb Smirnoff int rv, not = 0; 20043b3a8eb9SGleb Smirnoff 20053b3a8eb9SGleb Smirnoff for (r = s; *r == '!'; r++) 20063b3a8eb9SGleb Smirnoff not = !not; 20073b3a8eb9SGleb Smirnoff if ((n = host(r)) == NULL) { 20083b3a8eb9SGleb Smirnoff errno = 0; 20093b3a8eb9SGleb Smirnoff return (-1); 20103b3a8eb9SGleb Smirnoff } 20113b3a8eb9SGleb Smirnoff rv = append_addr_host(b, n, test, not); 20123b3a8eb9SGleb Smirnoff do { 20133b3a8eb9SGleb Smirnoff h = n; 20143b3a8eb9SGleb Smirnoff n = n->next; 20153b3a8eb9SGleb Smirnoff free(h); 20163b3a8eb9SGleb Smirnoff } while (n != NULL); 20173b3a8eb9SGleb Smirnoff return (rv); 20183b3a8eb9SGleb Smirnoff } 20193b3a8eb9SGleb Smirnoff 20203b3a8eb9SGleb Smirnoff /* 20213b3a8eb9SGleb Smirnoff * same as previous function, but with a pre-parsed input and the ability 20223b3a8eb9SGleb Smirnoff * to "negate" the result. Does not free the node_host list. 20233b3a8eb9SGleb Smirnoff * not: 20243b3a8eb9SGleb Smirnoff * setting it to 1 is equivalent to adding "!" in front of parameter s. 20253b3a8eb9SGleb Smirnoff */ 20263b3a8eb9SGleb Smirnoff int 20273b3a8eb9SGleb Smirnoff append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not) 20283b3a8eb9SGleb Smirnoff { 20293b3a8eb9SGleb Smirnoff int bits; 20303b3a8eb9SGleb Smirnoff struct pfr_addr addr; 20313b3a8eb9SGleb Smirnoff 20323b3a8eb9SGleb Smirnoff do { 20333b3a8eb9SGleb Smirnoff bzero(&addr, sizeof(addr)); 20343b3a8eb9SGleb Smirnoff addr.pfra_not = n->not ^ not; 20353b3a8eb9SGleb Smirnoff addr.pfra_af = n->af; 20363b3a8eb9SGleb Smirnoff addr.pfra_net = unmask(&n->addr.v.a.mask, n->af); 20373b3a8eb9SGleb Smirnoff switch (n->af) { 20383b3a8eb9SGleb Smirnoff case AF_INET: 20393b3a8eb9SGleb Smirnoff addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0]; 20403b3a8eb9SGleb Smirnoff bits = 32; 20413b3a8eb9SGleb Smirnoff break; 20423b3a8eb9SGleb Smirnoff case AF_INET6: 20433b3a8eb9SGleb Smirnoff memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6, 20443b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 20453b3a8eb9SGleb Smirnoff bits = 128; 20463b3a8eb9SGleb Smirnoff break; 20473b3a8eb9SGleb Smirnoff default: 20483b3a8eb9SGleb Smirnoff errno = EINVAL; 20493b3a8eb9SGleb Smirnoff return (-1); 20503b3a8eb9SGleb Smirnoff } 20513b3a8eb9SGleb Smirnoff if ((test && (not || addr.pfra_net != bits)) || 20523b3a8eb9SGleb Smirnoff addr.pfra_net > bits) { 20533b3a8eb9SGleb Smirnoff errno = EINVAL; 20543b3a8eb9SGleb Smirnoff return (-1); 20553b3a8eb9SGleb Smirnoff } 20563b3a8eb9SGleb Smirnoff if (pfr_buf_add(b, &addr)) 20573b3a8eb9SGleb Smirnoff return (-1); 20583b3a8eb9SGleb Smirnoff } while ((n = n->next) != NULL); 20593b3a8eb9SGleb Smirnoff 20603b3a8eb9SGleb Smirnoff return (0); 20613b3a8eb9SGleb Smirnoff } 20623b3a8eb9SGleb Smirnoff 20633b3a8eb9SGleb Smirnoff int 20643b3a8eb9SGleb Smirnoff pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor) 20653b3a8eb9SGleb Smirnoff { 20663b3a8eb9SGleb Smirnoff struct pfioc_trans_e trans; 20673b3a8eb9SGleb Smirnoff 20683b3a8eb9SGleb Smirnoff bzero(&trans, sizeof(trans)); 20693b3a8eb9SGleb Smirnoff trans.rs_num = rs_num; 20703b3a8eb9SGleb Smirnoff if (strlcpy(trans.anchor, anchor, 20713b3a8eb9SGleb Smirnoff sizeof(trans.anchor)) >= sizeof(trans.anchor)) 20723b3a8eb9SGleb Smirnoff errx(1, "pfctl_add_trans: strlcpy"); 20733b3a8eb9SGleb Smirnoff 20743b3a8eb9SGleb Smirnoff return pfr_buf_add(buf, &trans); 20753b3a8eb9SGleb Smirnoff } 20763b3a8eb9SGleb Smirnoff 20773b3a8eb9SGleb Smirnoff u_int32_t 20783b3a8eb9SGleb Smirnoff pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor) 20793b3a8eb9SGleb Smirnoff { 20803b3a8eb9SGleb Smirnoff struct pfioc_trans_e *p; 20813b3a8eb9SGleb Smirnoff 20823b3a8eb9SGleb Smirnoff PFRB_FOREACH(p, buf) 20833b3a8eb9SGleb Smirnoff if (rs_num == p->rs_num && !strcmp(anchor, p->anchor)) 20843b3a8eb9SGleb Smirnoff return (p->ticket); 20853b3a8eb9SGleb Smirnoff errx(1, "pfctl_get_ticket: assertion failed"); 20863b3a8eb9SGleb Smirnoff } 20873b3a8eb9SGleb Smirnoff 20883b3a8eb9SGleb Smirnoff int 20893b3a8eb9SGleb Smirnoff pfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from) 20903b3a8eb9SGleb Smirnoff { 20913b3a8eb9SGleb Smirnoff struct pfioc_trans trans; 20923b3a8eb9SGleb Smirnoff 20933b3a8eb9SGleb Smirnoff bzero(&trans, sizeof(trans)); 20943b3a8eb9SGleb Smirnoff trans.size = buf->pfrb_size - from; 20953b3a8eb9SGleb Smirnoff trans.esize = sizeof(struct pfioc_trans_e); 20963b3a8eb9SGleb Smirnoff trans.array = ((struct pfioc_trans_e *)buf->pfrb_caddr) + from; 20973b3a8eb9SGleb Smirnoff return ioctl(dev, cmd, &trans); 20983b3a8eb9SGleb Smirnoff } 2099