13b3a8eb9SGleb Smirnoff /* $OpenBSD: pfctl_parser.c,v 1.240 2008/06/10 20:55:02 mcbride Exp $ */ 23b3a8eb9SGleb Smirnoff 31de7b4b8SPedro F. Giffuni /*- 41de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause 51de7b4b8SPedro F. Giffuni * 63b3a8eb9SGleb Smirnoff * Copyright (c) 2001 Daniel Hartmeier 73b3a8eb9SGleb Smirnoff * Copyright (c) 2002,2003 Henning Brauer 83b3a8eb9SGleb Smirnoff * All rights reserved. 93b3a8eb9SGleb Smirnoff * 103b3a8eb9SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 113b3a8eb9SGleb Smirnoff * modification, are permitted provided that the following conditions 123b3a8eb9SGleb Smirnoff * are met: 133b3a8eb9SGleb Smirnoff * 143b3a8eb9SGleb Smirnoff * - Redistributions of source code must retain the above copyright 153b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 163b3a8eb9SGleb Smirnoff * - Redistributions in binary form must reproduce the above 173b3a8eb9SGleb Smirnoff * copyright notice, this list of conditions and the following 183b3a8eb9SGleb Smirnoff * disclaimer in the documentation and/or other materials provided 193b3a8eb9SGleb Smirnoff * with the distribution. 203b3a8eb9SGleb Smirnoff * 213b3a8eb9SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 223b3a8eb9SGleb Smirnoff * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 233b3a8eb9SGleb Smirnoff * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 243b3a8eb9SGleb Smirnoff * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 253b3a8eb9SGleb Smirnoff * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 263b3a8eb9SGleb Smirnoff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 273b3a8eb9SGleb Smirnoff * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 283b3a8eb9SGleb Smirnoff * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 293b3a8eb9SGleb Smirnoff * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 303b3a8eb9SGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 313b3a8eb9SGleb Smirnoff * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 323b3a8eb9SGleb Smirnoff * POSSIBILITY OF SUCH DAMAGE. 333b3a8eb9SGleb Smirnoff * 343b3a8eb9SGleb Smirnoff */ 353b3a8eb9SGleb Smirnoff 363b3a8eb9SGleb Smirnoff #include <sys/cdefs.h> 373b3a8eb9SGleb Smirnoff __FBSDID("$FreeBSD$"); 383b3a8eb9SGleb Smirnoff 393b3a8eb9SGleb Smirnoff #include <sys/types.h> 403b3a8eb9SGleb Smirnoff #include <sys/ioctl.h> 413b3a8eb9SGleb Smirnoff #include <sys/socket.h> 423b3a8eb9SGleb Smirnoff #include <sys/param.h> 433b3a8eb9SGleb Smirnoff #include <sys/proc.h> 443b3a8eb9SGleb Smirnoff #include <net/if.h> 453b3a8eb9SGleb Smirnoff #include <netinet/in.h> 463b3a8eb9SGleb Smirnoff #include <netinet/in_systm.h> 473b3a8eb9SGleb Smirnoff #include <netinet/ip.h> 483b3a8eb9SGleb Smirnoff #include <netinet/ip_icmp.h> 493b3a8eb9SGleb Smirnoff #include <netinet/icmp6.h> 503b3a8eb9SGleb Smirnoff #include <net/pfvar.h> 513b3a8eb9SGleb Smirnoff #include <arpa/inet.h> 523b3a8eb9SGleb Smirnoff 535062afffSKristof Provost #include <assert.h> 541d34c9daSPatrick Kelsey #include <search.h> 553b3a8eb9SGleb Smirnoff #include <stdio.h> 563b3a8eb9SGleb Smirnoff #include <stdlib.h> 573b3a8eb9SGleb Smirnoff #include <string.h> 583b3a8eb9SGleb Smirnoff #include <ctype.h> 593b3a8eb9SGleb Smirnoff #include <netdb.h> 603b3a8eb9SGleb Smirnoff #include <stdarg.h> 613b3a8eb9SGleb Smirnoff #include <errno.h> 623b3a8eb9SGleb Smirnoff #include <err.h> 633b3a8eb9SGleb Smirnoff #include <ifaddrs.h> 643b3a8eb9SGleb Smirnoff #include <unistd.h> 653b3a8eb9SGleb Smirnoff 663b3a8eb9SGleb Smirnoff #include "pfctl_parser.h" 673b3a8eb9SGleb Smirnoff #include "pfctl.h" 683b3a8eb9SGleb Smirnoff 693b3a8eb9SGleb Smirnoff void print_op (u_int8_t, const char *, const char *); 703b3a8eb9SGleb Smirnoff void print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int); 713b3a8eb9SGleb Smirnoff void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned); 723b3a8eb9SGleb Smirnoff void print_flags (u_int8_t); 733b3a8eb9SGleb Smirnoff void print_fromto(struct pf_rule_addr *, pf_osfp_t, 743b3a8eb9SGleb Smirnoff struct pf_rule_addr *, u_int8_t, u_int8_t, int, int); 753b3a8eb9SGleb Smirnoff int ifa_skip_if(const char *filter, struct node_host *p); 763b3a8eb9SGleb Smirnoff 773b3a8eb9SGleb Smirnoff struct node_host *host_if(const char *, int); 783b3a8eb9SGleb Smirnoff struct node_host *host_v4(const char *, int); 793b3a8eb9SGleb Smirnoff struct node_host *host_v6(const char *, int); 803b3a8eb9SGleb Smirnoff struct node_host *host_dns(const char *, int, int); 813b3a8eb9SGleb Smirnoff 8272a3cf0fSKristof Provost const char * const tcpflags = "FSRPAUEW"; 833b3a8eb9SGleb Smirnoff 843b3a8eb9SGleb Smirnoff static const struct icmptypeent icmp_type[] = { 853b3a8eb9SGleb Smirnoff { "echoreq", ICMP_ECHO }, 863b3a8eb9SGleb Smirnoff { "echorep", ICMP_ECHOREPLY }, 873b3a8eb9SGleb Smirnoff { "unreach", ICMP_UNREACH }, 883b3a8eb9SGleb Smirnoff { "squench", ICMP_SOURCEQUENCH }, 893b3a8eb9SGleb Smirnoff { "redir", ICMP_REDIRECT }, 903b3a8eb9SGleb Smirnoff { "althost", ICMP_ALTHOSTADDR }, 913b3a8eb9SGleb Smirnoff { "routeradv", ICMP_ROUTERADVERT }, 923b3a8eb9SGleb Smirnoff { "routersol", ICMP_ROUTERSOLICIT }, 933b3a8eb9SGleb Smirnoff { "timex", ICMP_TIMXCEED }, 943b3a8eb9SGleb Smirnoff { "paramprob", ICMP_PARAMPROB }, 953b3a8eb9SGleb Smirnoff { "timereq", ICMP_TSTAMP }, 963b3a8eb9SGleb Smirnoff { "timerep", ICMP_TSTAMPREPLY }, 973b3a8eb9SGleb Smirnoff { "inforeq", ICMP_IREQ }, 983b3a8eb9SGleb Smirnoff { "inforep", ICMP_IREQREPLY }, 993b3a8eb9SGleb Smirnoff { "maskreq", ICMP_MASKREQ }, 1003b3a8eb9SGleb Smirnoff { "maskrep", ICMP_MASKREPLY }, 1013b3a8eb9SGleb Smirnoff { "trace", ICMP_TRACEROUTE }, 1023b3a8eb9SGleb Smirnoff { "dataconv", ICMP_DATACONVERR }, 1033b3a8eb9SGleb Smirnoff { "mobredir", ICMP_MOBILE_REDIRECT }, 1043b3a8eb9SGleb Smirnoff { "ipv6-where", ICMP_IPV6_WHEREAREYOU }, 1053b3a8eb9SGleb Smirnoff { "ipv6-here", ICMP_IPV6_IAMHERE }, 1063b3a8eb9SGleb Smirnoff { "mobregreq", ICMP_MOBILE_REGREQUEST }, 1073b3a8eb9SGleb Smirnoff { "mobregrep", ICMP_MOBILE_REGREPLY }, 1083b3a8eb9SGleb Smirnoff { "skip", ICMP_SKIP }, 1093b3a8eb9SGleb Smirnoff { "photuris", ICMP_PHOTURIS } 1103b3a8eb9SGleb Smirnoff }; 1113b3a8eb9SGleb Smirnoff 1123b3a8eb9SGleb Smirnoff static const struct icmptypeent icmp6_type[] = { 1133b3a8eb9SGleb Smirnoff { "unreach", ICMP6_DST_UNREACH }, 1143b3a8eb9SGleb Smirnoff { "toobig", ICMP6_PACKET_TOO_BIG }, 1153b3a8eb9SGleb Smirnoff { "timex", ICMP6_TIME_EXCEEDED }, 1163b3a8eb9SGleb Smirnoff { "paramprob", ICMP6_PARAM_PROB }, 1173b3a8eb9SGleb Smirnoff { "echoreq", ICMP6_ECHO_REQUEST }, 1183b3a8eb9SGleb Smirnoff { "echorep", ICMP6_ECHO_REPLY }, 1193b3a8eb9SGleb Smirnoff { "groupqry", ICMP6_MEMBERSHIP_QUERY }, 1203b3a8eb9SGleb Smirnoff { "listqry", MLD_LISTENER_QUERY }, 1213b3a8eb9SGleb Smirnoff { "grouprep", ICMP6_MEMBERSHIP_REPORT }, 1223b3a8eb9SGleb Smirnoff { "listenrep", MLD_LISTENER_REPORT }, 1233b3a8eb9SGleb Smirnoff { "groupterm", ICMP6_MEMBERSHIP_REDUCTION }, 1243b3a8eb9SGleb Smirnoff { "listendone", MLD_LISTENER_DONE }, 1253b3a8eb9SGleb Smirnoff { "routersol", ND_ROUTER_SOLICIT }, 1263b3a8eb9SGleb Smirnoff { "routeradv", ND_ROUTER_ADVERT }, 1273b3a8eb9SGleb Smirnoff { "neighbrsol", ND_NEIGHBOR_SOLICIT }, 1283b3a8eb9SGleb Smirnoff { "neighbradv", ND_NEIGHBOR_ADVERT }, 1293b3a8eb9SGleb Smirnoff { "redir", ND_REDIRECT }, 1303b3a8eb9SGleb Smirnoff { "routrrenum", ICMP6_ROUTER_RENUMBERING }, 1313b3a8eb9SGleb Smirnoff { "wrureq", ICMP6_WRUREQUEST }, 1323b3a8eb9SGleb Smirnoff { "wrurep", ICMP6_WRUREPLY }, 1333b3a8eb9SGleb Smirnoff { "fqdnreq", ICMP6_FQDN_QUERY }, 1343b3a8eb9SGleb Smirnoff { "fqdnrep", ICMP6_FQDN_REPLY }, 1353b3a8eb9SGleb Smirnoff { "niqry", ICMP6_NI_QUERY }, 1363b3a8eb9SGleb Smirnoff { "nirep", ICMP6_NI_REPLY }, 1373b3a8eb9SGleb Smirnoff { "mtraceresp", MLD_MTRACE_RESP }, 1383b3a8eb9SGleb Smirnoff { "mtrace", MLD_MTRACE } 1393b3a8eb9SGleb Smirnoff }; 1403b3a8eb9SGleb Smirnoff 1413b3a8eb9SGleb Smirnoff static const struct icmpcodeent icmp_code[] = { 1423b3a8eb9SGleb Smirnoff { "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET }, 1433b3a8eb9SGleb Smirnoff { "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST }, 1443b3a8eb9SGleb Smirnoff { "proto-unr", ICMP_UNREACH, ICMP_UNREACH_PROTOCOL }, 1453b3a8eb9SGleb Smirnoff { "port-unr", ICMP_UNREACH, ICMP_UNREACH_PORT }, 1463b3a8eb9SGleb Smirnoff { "needfrag", ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG }, 1473b3a8eb9SGleb Smirnoff { "srcfail", ICMP_UNREACH, ICMP_UNREACH_SRCFAIL }, 1483b3a8eb9SGleb Smirnoff { "net-unk", ICMP_UNREACH, ICMP_UNREACH_NET_UNKNOWN }, 1493b3a8eb9SGleb Smirnoff { "host-unk", ICMP_UNREACH, ICMP_UNREACH_HOST_UNKNOWN }, 1503b3a8eb9SGleb Smirnoff { "isolate", ICMP_UNREACH, ICMP_UNREACH_ISOLATED }, 1513b3a8eb9SGleb Smirnoff { "net-prohib", ICMP_UNREACH, ICMP_UNREACH_NET_PROHIB }, 1523b3a8eb9SGleb Smirnoff { "host-prohib", ICMP_UNREACH, ICMP_UNREACH_HOST_PROHIB }, 1533b3a8eb9SGleb Smirnoff { "net-tos", ICMP_UNREACH, ICMP_UNREACH_TOSNET }, 1543b3a8eb9SGleb Smirnoff { "host-tos", ICMP_UNREACH, ICMP_UNREACH_TOSHOST }, 1553b3a8eb9SGleb Smirnoff { "filter-prohib", ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB }, 1563b3a8eb9SGleb Smirnoff { "host-preced", ICMP_UNREACH, ICMP_UNREACH_HOST_PRECEDENCE }, 1573b3a8eb9SGleb Smirnoff { "cutoff-preced", ICMP_UNREACH, ICMP_UNREACH_PRECEDENCE_CUTOFF }, 1583b3a8eb9SGleb Smirnoff { "redir-net", ICMP_REDIRECT, ICMP_REDIRECT_NET }, 1593b3a8eb9SGleb Smirnoff { "redir-host", ICMP_REDIRECT, ICMP_REDIRECT_HOST }, 1603b3a8eb9SGleb Smirnoff { "redir-tos-net", ICMP_REDIRECT, ICMP_REDIRECT_TOSNET }, 1613b3a8eb9SGleb Smirnoff { "redir-tos-host", ICMP_REDIRECT, ICMP_REDIRECT_TOSHOST }, 1623b3a8eb9SGleb Smirnoff { "normal-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL }, 1633b3a8eb9SGleb Smirnoff { "common-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON }, 1643b3a8eb9SGleb Smirnoff { "transit", ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS }, 1653b3a8eb9SGleb Smirnoff { "reassemb", ICMP_TIMXCEED, ICMP_TIMXCEED_REASS }, 1663b3a8eb9SGleb Smirnoff { "badhead", ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR }, 1673b3a8eb9SGleb Smirnoff { "optmiss", ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT }, 1683b3a8eb9SGleb Smirnoff { "badlen", ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH }, 1693b3a8eb9SGleb Smirnoff { "unknown-ind", ICMP_PHOTURIS, ICMP_PHOTURIS_UNKNOWN_INDEX }, 1703b3a8eb9SGleb Smirnoff { "auth-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_AUTH_FAILED }, 1713b3a8eb9SGleb Smirnoff { "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED } 1723b3a8eb9SGleb Smirnoff }; 1733b3a8eb9SGleb Smirnoff 1743b3a8eb9SGleb Smirnoff static const struct icmpcodeent icmp6_code[] = { 1753b3a8eb9SGleb Smirnoff { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN }, 1763b3a8eb9SGleb Smirnoff { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE }, 1773b3a8eb9SGleb Smirnoff { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR }, 1783b3a8eb9SGleb Smirnoff { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE }, 1793b3a8eb9SGleb Smirnoff { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR }, 1803b3a8eb9SGleb Smirnoff { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT }, 1813b3a8eb9SGleb Smirnoff { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT }, 1823b3a8eb9SGleb Smirnoff { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY }, 1833b3a8eb9SGleb Smirnoff { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER }, 1843b3a8eb9SGleb Smirnoff { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER }, 1853b3a8eb9SGleb Smirnoff { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK }, 1863b3a8eb9SGleb Smirnoff { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER } 1873b3a8eb9SGleb Smirnoff }; 1883b3a8eb9SGleb Smirnoff 1893b3a8eb9SGleb Smirnoff const struct pf_timeout pf_timeouts[] = { 1903b3a8eb9SGleb Smirnoff { "tcp.first", PFTM_TCP_FIRST_PACKET }, 1913b3a8eb9SGleb Smirnoff { "tcp.opening", PFTM_TCP_OPENING }, 1923b3a8eb9SGleb Smirnoff { "tcp.established", PFTM_TCP_ESTABLISHED }, 1933b3a8eb9SGleb Smirnoff { "tcp.closing", PFTM_TCP_CLOSING }, 1943b3a8eb9SGleb Smirnoff { "tcp.finwait", PFTM_TCP_FIN_WAIT }, 1953b3a8eb9SGleb Smirnoff { "tcp.closed", PFTM_TCP_CLOSED }, 1963b3a8eb9SGleb Smirnoff { "tcp.tsdiff", PFTM_TS_DIFF }, 1973b3a8eb9SGleb Smirnoff { "udp.first", PFTM_UDP_FIRST_PACKET }, 1983b3a8eb9SGleb Smirnoff { "udp.single", PFTM_UDP_SINGLE }, 1993b3a8eb9SGleb Smirnoff { "udp.multiple", PFTM_UDP_MULTIPLE }, 2003b3a8eb9SGleb Smirnoff { "icmp.first", PFTM_ICMP_FIRST_PACKET }, 2013b3a8eb9SGleb Smirnoff { "icmp.error", PFTM_ICMP_ERROR_REPLY }, 2023b3a8eb9SGleb Smirnoff { "other.first", PFTM_OTHER_FIRST_PACKET }, 2033b3a8eb9SGleb Smirnoff { "other.single", PFTM_OTHER_SINGLE }, 2043b3a8eb9SGleb Smirnoff { "other.multiple", PFTM_OTHER_MULTIPLE }, 2053b3a8eb9SGleb Smirnoff { "frag", PFTM_FRAG }, 2063b3a8eb9SGleb Smirnoff { "interval", PFTM_INTERVAL }, 2073b3a8eb9SGleb Smirnoff { "adaptive.start", PFTM_ADAPTIVE_START }, 2083b3a8eb9SGleb Smirnoff { "adaptive.end", PFTM_ADAPTIVE_END }, 2093b3a8eb9SGleb Smirnoff { "src.track", PFTM_SRC_NODE }, 2103b3a8eb9SGleb Smirnoff { NULL, 0 } 2113b3a8eb9SGleb Smirnoff }; 2123b3a8eb9SGleb Smirnoff 2131d34c9daSPatrick Kelsey static struct hsearch_data isgroup_map; 2141d34c9daSPatrick Kelsey 2151d34c9daSPatrick Kelsey static __attribute__((constructor)) void 2161d34c9daSPatrick Kelsey pfctl_parser_init(void) 2171d34c9daSPatrick Kelsey { 2181d34c9daSPatrick Kelsey /* 2191d34c9daSPatrick Kelsey * As hdestroy() will never be called on these tables, it will be 2201d34c9daSPatrick Kelsey * safe to use references into the stored data as keys. 2211d34c9daSPatrick Kelsey */ 2221d34c9daSPatrick Kelsey if (hcreate_r(0, &isgroup_map) == 0) 2231d34c9daSPatrick Kelsey err(1, "Failed to create interface group query response map"); 2241d34c9daSPatrick Kelsey } 2251d34c9daSPatrick Kelsey 2263b3a8eb9SGleb Smirnoff const struct icmptypeent * 2273b3a8eb9SGleb Smirnoff geticmptypebynumber(u_int8_t type, sa_family_t af) 2283b3a8eb9SGleb Smirnoff { 2293b3a8eb9SGleb Smirnoff unsigned int i; 2303b3a8eb9SGleb Smirnoff 2313b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 232c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_type); i++) { 2333b3a8eb9SGleb Smirnoff if (type == icmp_type[i].type) 2343b3a8eb9SGleb Smirnoff return (&icmp_type[i]); 2353b3a8eb9SGleb Smirnoff } 2363b3a8eb9SGleb Smirnoff } else { 237c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_type); i++) { 2383b3a8eb9SGleb Smirnoff if (type == icmp6_type[i].type) 2393b3a8eb9SGleb Smirnoff return (&icmp6_type[i]); 2403b3a8eb9SGleb Smirnoff } 2413b3a8eb9SGleb Smirnoff } 2423b3a8eb9SGleb Smirnoff return (NULL); 2433b3a8eb9SGleb Smirnoff } 2443b3a8eb9SGleb Smirnoff 2453b3a8eb9SGleb Smirnoff const struct icmptypeent * 2463b3a8eb9SGleb Smirnoff geticmptypebyname(char *w, sa_family_t af) 2473b3a8eb9SGleb Smirnoff { 2483b3a8eb9SGleb Smirnoff unsigned int i; 2493b3a8eb9SGleb Smirnoff 2503b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 251c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_type); i++) { 2523b3a8eb9SGleb Smirnoff if (!strcmp(w, icmp_type[i].name)) 2533b3a8eb9SGleb Smirnoff return (&icmp_type[i]); 2543b3a8eb9SGleb Smirnoff } 2553b3a8eb9SGleb Smirnoff } else { 256c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_type); i++) { 2573b3a8eb9SGleb Smirnoff if (!strcmp(w, icmp6_type[i].name)) 2583b3a8eb9SGleb Smirnoff return (&icmp6_type[i]); 2593b3a8eb9SGleb Smirnoff } 2603b3a8eb9SGleb Smirnoff } 2613b3a8eb9SGleb Smirnoff return (NULL); 2623b3a8eb9SGleb Smirnoff } 2633b3a8eb9SGleb Smirnoff 2643b3a8eb9SGleb Smirnoff const struct icmpcodeent * 2653b3a8eb9SGleb Smirnoff geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af) 2663b3a8eb9SGleb Smirnoff { 2673b3a8eb9SGleb Smirnoff unsigned int i; 2683b3a8eb9SGleb Smirnoff 2693b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 270c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_code); i++) { 2713b3a8eb9SGleb Smirnoff if (type == icmp_code[i].type && 2723b3a8eb9SGleb Smirnoff code == icmp_code[i].code) 2733b3a8eb9SGleb Smirnoff return (&icmp_code[i]); 2743b3a8eb9SGleb Smirnoff } 2753b3a8eb9SGleb Smirnoff } else { 276c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_code); i++) { 2773b3a8eb9SGleb Smirnoff if (type == icmp6_code[i].type && 2783b3a8eb9SGleb Smirnoff code == icmp6_code[i].code) 2793b3a8eb9SGleb Smirnoff return (&icmp6_code[i]); 2803b3a8eb9SGleb Smirnoff } 2813b3a8eb9SGleb Smirnoff } 2823b3a8eb9SGleb Smirnoff return (NULL); 2833b3a8eb9SGleb Smirnoff } 2843b3a8eb9SGleb Smirnoff 2853b3a8eb9SGleb Smirnoff const struct icmpcodeent * 2863b3a8eb9SGleb Smirnoff geticmpcodebyname(u_long type, char *w, sa_family_t af) 2873b3a8eb9SGleb Smirnoff { 2883b3a8eb9SGleb Smirnoff unsigned int i; 2893b3a8eb9SGleb Smirnoff 2903b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 291c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_code); i++) { 2923b3a8eb9SGleb Smirnoff if (type == icmp_code[i].type && 2933b3a8eb9SGleb Smirnoff !strcmp(w, icmp_code[i].name)) 2943b3a8eb9SGleb Smirnoff return (&icmp_code[i]); 2953b3a8eb9SGleb Smirnoff } 2963b3a8eb9SGleb Smirnoff } else { 297c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_code); i++) { 2983b3a8eb9SGleb Smirnoff if (type == icmp6_code[i].type && 2993b3a8eb9SGleb Smirnoff !strcmp(w, icmp6_code[i].name)) 3003b3a8eb9SGleb Smirnoff return (&icmp6_code[i]); 3013b3a8eb9SGleb Smirnoff } 3023b3a8eb9SGleb Smirnoff } 3033b3a8eb9SGleb Smirnoff return (NULL); 3043b3a8eb9SGleb Smirnoff } 3053b3a8eb9SGleb Smirnoff 3063b3a8eb9SGleb Smirnoff void 3073b3a8eb9SGleb Smirnoff print_op(u_int8_t op, const char *a1, const char *a2) 3083b3a8eb9SGleb Smirnoff { 3093b3a8eb9SGleb Smirnoff if (op == PF_OP_IRG) 3103b3a8eb9SGleb Smirnoff printf(" %s >< %s", a1, a2); 3113b3a8eb9SGleb Smirnoff else if (op == PF_OP_XRG) 3123b3a8eb9SGleb Smirnoff printf(" %s <> %s", a1, a2); 3133b3a8eb9SGleb Smirnoff else if (op == PF_OP_EQ) 3143b3a8eb9SGleb Smirnoff printf(" = %s", a1); 3153b3a8eb9SGleb Smirnoff else if (op == PF_OP_NE) 3163b3a8eb9SGleb Smirnoff printf(" != %s", a1); 3173b3a8eb9SGleb Smirnoff else if (op == PF_OP_LT) 3183b3a8eb9SGleb Smirnoff printf(" < %s", a1); 3193b3a8eb9SGleb Smirnoff else if (op == PF_OP_LE) 3203b3a8eb9SGleb Smirnoff printf(" <= %s", a1); 3213b3a8eb9SGleb Smirnoff else if (op == PF_OP_GT) 3223b3a8eb9SGleb Smirnoff printf(" > %s", a1); 3233b3a8eb9SGleb Smirnoff else if (op == PF_OP_GE) 3243b3a8eb9SGleb Smirnoff printf(" >= %s", a1); 3253b3a8eb9SGleb Smirnoff else if (op == PF_OP_RRG) 3263b3a8eb9SGleb Smirnoff printf(" %s:%s", a1, a2); 3273b3a8eb9SGleb Smirnoff } 3283b3a8eb9SGleb Smirnoff 3293b3a8eb9SGleb Smirnoff void 3303b3a8eb9SGleb Smirnoff print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int numeric) 3313b3a8eb9SGleb Smirnoff { 3323b3a8eb9SGleb Smirnoff char a1[6], a2[6]; 3333b3a8eb9SGleb Smirnoff struct servent *s; 3343b3a8eb9SGleb Smirnoff 3353b3a8eb9SGleb Smirnoff if (!numeric) 3363b3a8eb9SGleb Smirnoff s = getservbyport(p1, proto); 3373b3a8eb9SGleb Smirnoff else 3383b3a8eb9SGleb Smirnoff s = NULL; 3393b3a8eb9SGleb Smirnoff p1 = ntohs(p1); 3403b3a8eb9SGleb Smirnoff p2 = ntohs(p2); 3413b3a8eb9SGleb Smirnoff snprintf(a1, sizeof(a1), "%u", p1); 3423b3a8eb9SGleb Smirnoff snprintf(a2, sizeof(a2), "%u", p2); 3433b3a8eb9SGleb Smirnoff printf(" port"); 3443b3a8eb9SGleb Smirnoff if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE)) 3453b3a8eb9SGleb Smirnoff print_op(op, s->s_name, a2); 3463b3a8eb9SGleb Smirnoff else 3473b3a8eb9SGleb Smirnoff print_op(op, a1, a2); 3483b3a8eb9SGleb Smirnoff } 3493b3a8eb9SGleb Smirnoff 3503b3a8eb9SGleb Smirnoff void 3513b3a8eb9SGleb Smirnoff print_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax) 3523b3a8eb9SGleb Smirnoff { 3533b3a8eb9SGleb Smirnoff char a1[11], a2[11]; 3543b3a8eb9SGleb Smirnoff 3553b3a8eb9SGleb Smirnoff snprintf(a1, sizeof(a1), "%u", u1); 3563b3a8eb9SGleb Smirnoff snprintf(a2, sizeof(a2), "%u", u2); 3573b3a8eb9SGleb Smirnoff printf(" %s", t); 3583b3a8eb9SGleb Smirnoff if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE)) 3593b3a8eb9SGleb Smirnoff print_op(op, "unknown", a2); 3603b3a8eb9SGleb Smirnoff else 3613b3a8eb9SGleb Smirnoff print_op(op, a1, a2); 3623b3a8eb9SGleb Smirnoff } 3633b3a8eb9SGleb Smirnoff 3643b3a8eb9SGleb Smirnoff void 3653b3a8eb9SGleb Smirnoff print_flags(u_int8_t f) 3663b3a8eb9SGleb Smirnoff { 3673b3a8eb9SGleb Smirnoff int i; 3683b3a8eb9SGleb Smirnoff 3693b3a8eb9SGleb Smirnoff for (i = 0; tcpflags[i]; ++i) 3703b3a8eb9SGleb Smirnoff if (f & (1 << i)) 3713b3a8eb9SGleb Smirnoff printf("%c", tcpflags[i]); 3723b3a8eb9SGleb Smirnoff } 3733b3a8eb9SGleb Smirnoff 3743b3a8eb9SGleb Smirnoff void 3753b3a8eb9SGleb Smirnoff print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, 3763b3a8eb9SGleb Smirnoff sa_family_t af, u_int8_t proto, int verbose, int numeric) 3773b3a8eb9SGleb Smirnoff { 3783b3a8eb9SGleb Smirnoff char buf[PF_OSFP_LEN*3]; 3793b3a8eb9SGleb Smirnoff if (src->addr.type == PF_ADDR_ADDRMASK && 3803b3a8eb9SGleb Smirnoff dst->addr.type == PF_ADDR_ADDRMASK && 3813b3a8eb9SGleb Smirnoff PF_AZERO(&src->addr.v.a.addr, AF_INET6) && 3823b3a8eb9SGleb Smirnoff PF_AZERO(&src->addr.v.a.mask, AF_INET6) && 3833b3a8eb9SGleb Smirnoff PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && 3843b3a8eb9SGleb Smirnoff PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && 3853b3a8eb9SGleb Smirnoff !src->neg && !dst->neg && 3863b3a8eb9SGleb Smirnoff !src->port_op && !dst->port_op && 3873b3a8eb9SGleb Smirnoff osfp == PF_OSFP_ANY) 3883b3a8eb9SGleb Smirnoff printf(" all"); 3893b3a8eb9SGleb Smirnoff else { 3903b3a8eb9SGleb Smirnoff printf(" from "); 3913b3a8eb9SGleb Smirnoff if (src->neg) 3923b3a8eb9SGleb Smirnoff printf("! "); 3933b3a8eb9SGleb Smirnoff print_addr(&src->addr, af, verbose); 3943b3a8eb9SGleb Smirnoff if (src->port_op) 3953b3a8eb9SGleb Smirnoff print_port(src->port_op, src->port[0], 3963b3a8eb9SGleb Smirnoff src->port[1], 3973b3a8eb9SGleb Smirnoff proto == IPPROTO_TCP ? "tcp" : "udp", 3983b3a8eb9SGleb Smirnoff numeric); 3993b3a8eb9SGleb Smirnoff if (osfp != PF_OSFP_ANY) 4003b3a8eb9SGleb Smirnoff printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf, 4013b3a8eb9SGleb Smirnoff sizeof(buf))); 4023b3a8eb9SGleb Smirnoff 4033b3a8eb9SGleb Smirnoff printf(" to "); 4043b3a8eb9SGleb Smirnoff if (dst->neg) 4053b3a8eb9SGleb Smirnoff printf("! "); 4063b3a8eb9SGleb Smirnoff print_addr(&dst->addr, af, verbose); 4073b3a8eb9SGleb Smirnoff if (dst->port_op) 4083b3a8eb9SGleb Smirnoff print_port(dst->port_op, dst->port[0], 4093b3a8eb9SGleb Smirnoff dst->port[1], 4103b3a8eb9SGleb Smirnoff proto == IPPROTO_TCP ? "tcp" : "udp", 4113b3a8eb9SGleb Smirnoff numeric); 4123b3a8eb9SGleb Smirnoff } 4133b3a8eb9SGleb Smirnoff } 4143b3a8eb9SGleb Smirnoff 4153b3a8eb9SGleb Smirnoff void 416600bd6ceSKurosawa Takahiro print_pool(struct pfctl_pool *pool, u_int16_t p1, u_int16_t p2, 4173b3a8eb9SGleb Smirnoff sa_family_t af, int id) 4183b3a8eb9SGleb Smirnoff { 4193b3a8eb9SGleb Smirnoff struct pf_pooladdr *pooladdr; 4203b3a8eb9SGleb Smirnoff 4213b3a8eb9SGleb Smirnoff if ((TAILQ_FIRST(&pool->list) != NULL) && 4223b3a8eb9SGleb Smirnoff TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4233b3a8eb9SGleb Smirnoff printf("{ "); 4243b3a8eb9SGleb Smirnoff TAILQ_FOREACH(pooladdr, &pool->list, entries){ 4253b3a8eb9SGleb Smirnoff switch (id) { 4263b3a8eb9SGleb Smirnoff case PF_NAT: 4273b3a8eb9SGleb Smirnoff case PF_RDR: 4283b3a8eb9SGleb Smirnoff case PF_BINAT: 4293b3a8eb9SGleb Smirnoff print_addr(&pooladdr->addr, af, 0); 4303b3a8eb9SGleb Smirnoff break; 4313b3a8eb9SGleb Smirnoff case PF_PASS: 4323b3a8eb9SGleb Smirnoff if (PF_AZERO(&pooladdr->addr.v.a.addr, af)) 4333b3a8eb9SGleb Smirnoff printf("%s", pooladdr->ifname); 4343b3a8eb9SGleb Smirnoff else { 4353b3a8eb9SGleb Smirnoff printf("(%s ", pooladdr->ifname); 4363b3a8eb9SGleb Smirnoff print_addr(&pooladdr->addr, af, 0); 4373b3a8eb9SGleb Smirnoff printf(")"); 4383b3a8eb9SGleb Smirnoff } 4393b3a8eb9SGleb Smirnoff break; 4403b3a8eb9SGleb Smirnoff default: 4413b3a8eb9SGleb Smirnoff break; 4423b3a8eb9SGleb Smirnoff } 4433b3a8eb9SGleb Smirnoff if (TAILQ_NEXT(pooladdr, entries) != NULL) 4443b3a8eb9SGleb Smirnoff printf(", "); 4453b3a8eb9SGleb Smirnoff else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4463b3a8eb9SGleb Smirnoff printf(" }"); 4473b3a8eb9SGleb Smirnoff } 4483b3a8eb9SGleb Smirnoff switch (id) { 4493b3a8eb9SGleb Smirnoff case PF_NAT: 4503b3a8eb9SGleb Smirnoff if ((p1 != PF_NAT_PROXY_PORT_LOW || 4513b3a8eb9SGleb Smirnoff p2 != PF_NAT_PROXY_PORT_HIGH) && (p1 != 0 || p2 != 0)) { 4523b3a8eb9SGleb Smirnoff if (p1 == p2) 4533b3a8eb9SGleb Smirnoff printf(" port %u", p1); 4543b3a8eb9SGleb Smirnoff else 4553b3a8eb9SGleb Smirnoff printf(" port %u:%u", p1, p2); 4563b3a8eb9SGleb Smirnoff } 4573b3a8eb9SGleb Smirnoff break; 4583b3a8eb9SGleb Smirnoff case PF_RDR: 4593b3a8eb9SGleb Smirnoff if (p1) { 4603b3a8eb9SGleb Smirnoff printf(" port %u", p1); 4613b3a8eb9SGleb Smirnoff if (p2 && (p2 != p1)) 4623b3a8eb9SGleb Smirnoff printf(":%u", p2); 4633b3a8eb9SGleb Smirnoff } 4643b3a8eb9SGleb Smirnoff break; 4653b3a8eb9SGleb Smirnoff default: 4663b3a8eb9SGleb Smirnoff break; 4673b3a8eb9SGleb Smirnoff } 4683b3a8eb9SGleb Smirnoff switch (pool->opts & PF_POOL_TYPEMASK) { 4693b3a8eb9SGleb Smirnoff case PF_POOL_NONE: 4703b3a8eb9SGleb Smirnoff break; 4713b3a8eb9SGleb Smirnoff case PF_POOL_BITMASK: 4723b3a8eb9SGleb Smirnoff printf(" bitmask"); 4733b3a8eb9SGleb Smirnoff break; 4743b3a8eb9SGleb Smirnoff case PF_POOL_RANDOM: 4753b3a8eb9SGleb Smirnoff printf(" random"); 4763b3a8eb9SGleb Smirnoff break; 4773b3a8eb9SGleb Smirnoff case PF_POOL_SRCHASH: 4783b3a8eb9SGleb Smirnoff printf(" source-hash 0x%08x%08x%08x%08x", 4793b3a8eb9SGleb Smirnoff pool->key.key32[0], pool->key.key32[1], 4803b3a8eb9SGleb Smirnoff pool->key.key32[2], pool->key.key32[3]); 4813b3a8eb9SGleb Smirnoff break; 4823b3a8eb9SGleb Smirnoff case PF_POOL_ROUNDROBIN: 4833b3a8eb9SGleb Smirnoff printf(" round-robin"); 4843b3a8eb9SGleb Smirnoff break; 4853b3a8eb9SGleb Smirnoff } 4863b3a8eb9SGleb Smirnoff if (pool->opts & PF_POOL_STICKYADDR) 4873b3a8eb9SGleb Smirnoff printf(" sticky-address"); 4883b3a8eb9SGleb Smirnoff if (id == PF_NAT && p1 == 0 && p2 == 0) 4893b3a8eb9SGleb Smirnoff printf(" static-port"); 4902aa21096SKurosawa Takahiro if (pool->mape.offset > 0) 4912aa21096SKurosawa Takahiro printf(" map-e-portset %u/%u/%u", 4922aa21096SKurosawa Takahiro pool->mape.offset, pool->mape.psidlen, pool->mape.psid); 4933b3a8eb9SGleb Smirnoff } 4943b3a8eb9SGleb Smirnoff 49572a3cf0fSKristof Provost const char * const pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 49672a3cf0fSKristof Provost const char * const pf_lcounters[LCNT_MAX+1] = LCNT_NAMES; 49772a3cf0fSKristof Provost const char * const pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 49872a3cf0fSKristof Provost const char * const pf_scounters[FCNT_MAX+1] = FCNT_NAMES; 4993b3a8eb9SGleb Smirnoff 5003b3a8eb9SGleb Smirnoff void 50180078d9dSKristof Provost print_status(struct pfctl_status *s, struct pfctl_syncookies *cookies, int opts) 5023b3a8eb9SGleb Smirnoff { 50380078d9dSKristof Provost struct pfctl_status_counter *c; 5043b3a8eb9SGleb Smirnoff char statline[80], *running; 5053b3a8eb9SGleb Smirnoff time_t runtime; 5063b3a8eb9SGleb Smirnoff int i; 5073b3a8eb9SGleb Smirnoff char buf[PF_MD5_DIGEST_LENGTH * 2 + 1]; 5083b3a8eb9SGleb Smirnoff static const char hex[] = "0123456789abcdef"; 5093b3a8eb9SGleb Smirnoff 5103b3a8eb9SGleb Smirnoff runtime = time(NULL) - s->since; 5113b3a8eb9SGleb Smirnoff running = s->running ? "Enabled" : "Disabled"; 5123b3a8eb9SGleb Smirnoff 5133b3a8eb9SGleb Smirnoff if (s->since) { 5143b3a8eb9SGleb Smirnoff unsigned int sec, min, hrs, day = runtime; 5153b3a8eb9SGleb Smirnoff 5163b3a8eb9SGleb Smirnoff sec = day % 60; 5173b3a8eb9SGleb Smirnoff day /= 60; 5183b3a8eb9SGleb Smirnoff min = day % 60; 5193b3a8eb9SGleb Smirnoff day /= 60; 5203b3a8eb9SGleb Smirnoff hrs = day % 24; 5213b3a8eb9SGleb Smirnoff day /= 24; 5223b3a8eb9SGleb Smirnoff snprintf(statline, sizeof(statline), 5233b3a8eb9SGleb Smirnoff "Status: %s for %u days %.2u:%.2u:%.2u", 5243b3a8eb9SGleb Smirnoff running, day, hrs, min, sec); 5253b3a8eb9SGleb Smirnoff } else 5263b3a8eb9SGleb Smirnoff snprintf(statline, sizeof(statline), "Status: %s", running); 5273b3a8eb9SGleb Smirnoff printf("%-44s", statline); 5283b3a8eb9SGleb Smirnoff switch (s->debug) { 5293b3a8eb9SGleb Smirnoff case PF_DEBUG_NONE: 5303b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: None"); 5313b3a8eb9SGleb Smirnoff break; 5323b3a8eb9SGleb Smirnoff case PF_DEBUG_URGENT: 5333b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Urgent"); 5343b3a8eb9SGleb Smirnoff break; 5353b3a8eb9SGleb Smirnoff case PF_DEBUG_MISC: 5363b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Misc"); 5373b3a8eb9SGleb Smirnoff break; 5383b3a8eb9SGleb Smirnoff case PF_DEBUG_NOISY: 5393b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Loud"); 5403b3a8eb9SGleb Smirnoff break; 5413b3a8eb9SGleb Smirnoff } 5423b3a8eb9SGleb Smirnoff 5433b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 544735748f3SKristof Provost printf("Hostid: 0x%08x\n", s->hostid); 5453b3a8eb9SGleb Smirnoff 5463b3a8eb9SGleb Smirnoff for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) { 5473b3a8eb9SGleb Smirnoff buf[i + i] = hex[s->pf_chksum[i] >> 4]; 5483b3a8eb9SGleb Smirnoff buf[i + i + 1] = hex[s->pf_chksum[i] & 0x0f]; 5493b3a8eb9SGleb Smirnoff } 5503b3a8eb9SGleb Smirnoff buf[i + i] = '\0'; 5513b3a8eb9SGleb Smirnoff printf("Checksum: 0x%s\n\n", buf); 5523b3a8eb9SGleb Smirnoff } 5533b3a8eb9SGleb Smirnoff 5543b3a8eb9SGleb Smirnoff if (s->ifname[0] != 0) { 5553b3a8eb9SGleb Smirnoff printf("Interface Stats for %-16s %5s %16s\n", 5563b3a8eb9SGleb Smirnoff s->ifname, "IPv4", "IPv6"); 5573b3a8eb9SGleb Smirnoff printf(" %-25s %14llu %16llu\n", "Bytes In", 5583b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[0][0], 5593b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[1][0]); 5603b3a8eb9SGleb Smirnoff printf(" %-25s %14llu %16llu\n", "Bytes Out", 5613b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[0][1], 5623b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[1][1]); 5633b3a8eb9SGleb Smirnoff printf(" Packets In\n"); 5643b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Passed", 5653b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][0][PF_PASS], 5663b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][0][PF_PASS]); 5673b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Blocked", 5683b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][0][PF_DROP], 5693b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][0][PF_DROP]); 5703b3a8eb9SGleb Smirnoff printf(" Packets Out\n"); 5713b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Passed", 5723b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][1][PF_PASS], 5733b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][1][PF_PASS]); 5743b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n\n", "Blocked", 5753b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][1][PF_DROP], 5763b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][1][PF_DROP]); 5773b3a8eb9SGleb Smirnoff } 5783b3a8eb9SGleb Smirnoff printf("%-27s %14s %16s\n", "State Table", "Total", "Rate"); 579846a6e8fSKristof Provost printf(" %-25s %14ju %14s\n", "current entries", s->states, ""); 58080078d9dSKristof Provost TAILQ_FOREACH(c, &s->fcounters, entry) { 581846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 5823b3a8eb9SGleb Smirnoff if (runtime > 0) 5833b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 58480078d9dSKristof Provost (double)c->counter / (double)runtime); 5853b3a8eb9SGleb Smirnoff else 5863b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 5873b3a8eb9SGleb Smirnoff } 5883b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 5893b3a8eb9SGleb Smirnoff printf("Source Tracking Table\n"); 590846a6e8fSKristof Provost printf(" %-25s %14ju %14s\n", "current entries", 5913b3a8eb9SGleb Smirnoff s->src_nodes, ""); 59280078d9dSKristof Provost TAILQ_FOREACH(c, &s->scounters, entry) { 593846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 5943b3a8eb9SGleb Smirnoff if (runtime > 0) 5953b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 59680078d9dSKristof Provost (double)c->counter / (double)runtime); 5973b3a8eb9SGleb Smirnoff else 5983b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 5993b3a8eb9SGleb Smirnoff } 6003b3a8eb9SGleb Smirnoff } 6013b3a8eb9SGleb Smirnoff printf("Counters\n"); 60280078d9dSKristof Provost TAILQ_FOREACH(c, &s->counters, entry) { 603846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 6043b3a8eb9SGleb Smirnoff if (runtime > 0) 6053b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 60680078d9dSKristof Provost (double)c->counter / (double)runtime); 6073b3a8eb9SGleb Smirnoff else 6083b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6093b3a8eb9SGleb Smirnoff } 6103b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 6113b3a8eb9SGleb Smirnoff printf("Limit Counters\n"); 61280078d9dSKristof Provost TAILQ_FOREACH(c, &s->lcounters, entry) { 613846a6e8fSKristof Provost printf(" %-25s %14ju ", c->name, c->counter); 6143b3a8eb9SGleb Smirnoff if (runtime > 0) 6153b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 61680078d9dSKristof Provost (double)c->counter / (double)runtime); 6173b3a8eb9SGleb Smirnoff else 6183b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6193b3a8eb9SGleb Smirnoff } 620c69121c4SKristof Provost 621c69121c4SKristof Provost printf("Syncookies\n"); 6225062afffSKristof Provost assert(cookies->mode <= PFCTL_SYNCOOKIES_ADAPTIVE); 623c69121c4SKristof Provost printf(" %-25s %s\n", "mode", 6245062afffSKristof Provost PFCTL_SYNCOOKIES_MODE_NAMES[cookies->mode]); 6253b3a8eb9SGleb Smirnoff } 6263b3a8eb9SGleb Smirnoff } 6273b3a8eb9SGleb Smirnoff 6283b3a8eb9SGleb Smirnoff void 62980078d9dSKristof Provost print_running(struct pfctl_status *status) 630fa1d4439SKristof Provost { 631fa1d4439SKristof Provost printf("%s\n", status->running ? "Enabled" : "Disabled"); 632fa1d4439SKristof Provost } 633fa1d4439SKristof Provost 634fa1d4439SKristof Provost void 6353b3a8eb9SGleb Smirnoff print_src_node(struct pf_src_node *sn, int opts) 6363b3a8eb9SGleb Smirnoff { 6373b3a8eb9SGleb Smirnoff struct pf_addr_wrap aw; 6383b3a8eb9SGleb Smirnoff int min, sec; 6393b3a8eb9SGleb Smirnoff 6403b3a8eb9SGleb Smirnoff memset(&aw, 0, sizeof(aw)); 6413b3a8eb9SGleb Smirnoff if (sn->af == AF_INET) 6423b3a8eb9SGleb Smirnoff aw.v.a.mask.addr32[0] = 0xffffffff; 6433b3a8eb9SGleb Smirnoff else 6443b3a8eb9SGleb Smirnoff memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask)); 6453b3a8eb9SGleb Smirnoff 6463b3a8eb9SGleb Smirnoff aw.v.a.addr = sn->addr; 6473b3a8eb9SGleb Smirnoff print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); 6483b3a8eb9SGleb Smirnoff printf(" -> "); 6493b3a8eb9SGleb Smirnoff aw.v.a.addr = sn->raddr; 6503b3a8eb9SGleb Smirnoff print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); 6513b3a8eb9SGleb Smirnoff printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states, 6523b3a8eb9SGleb Smirnoff sn->conn, sn->conn_rate.count / 1000, 6533b3a8eb9SGleb Smirnoff (sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds); 6543b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 6553b3a8eb9SGleb Smirnoff sec = sn->creation % 60; 6563b3a8eb9SGleb Smirnoff sn->creation /= 60; 6573b3a8eb9SGleb Smirnoff min = sn->creation % 60; 6583b3a8eb9SGleb Smirnoff sn->creation /= 60; 6593b3a8eb9SGleb Smirnoff printf(" age %.2u:%.2u:%.2u", sn->creation, min, sec); 6603b3a8eb9SGleb Smirnoff if (sn->states == 0) { 6613b3a8eb9SGleb Smirnoff sec = sn->expire % 60; 6623b3a8eb9SGleb Smirnoff sn->expire /= 60; 6633b3a8eb9SGleb Smirnoff min = sn->expire % 60; 6643b3a8eb9SGleb Smirnoff sn->expire /= 60; 6653b3a8eb9SGleb Smirnoff printf(", expires in %.2u:%.2u:%.2u", 6663b3a8eb9SGleb Smirnoff sn->expire, min, sec); 6673b3a8eb9SGleb Smirnoff } 6683b3a8eb9SGleb Smirnoff printf(", %llu pkts, %llu bytes", 6693b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 6703b3a8eb9SGleb Smirnoff (unsigned long long)(sn->packets[0] + sn->packets[1]), 6713b3a8eb9SGleb Smirnoff (unsigned long long)(sn->bytes[0] + sn->bytes[1])); 6723b3a8eb9SGleb Smirnoff #else 6733b3a8eb9SGleb Smirnoff sn->packets[0] + sn->packets[1], 6743b3a8eb9SGleb Smirnoff sn->bytes[0] + sn->bytes[1]); 6753b3a8eb9SGleb Smirnoff #endif 6763b3a8eb9SGleb Smirnoff switch (sn->ruletype) { 6773b3a8eb9SGleb Smirnoff case PF_NAT: 6783b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 6793b3a8eb9SGleb Smirnoff printf(", nat rule %u", sn->rule.nr); 6803b3a8eb9SGleb Smirnoff break; 6813b3a8eb9SGleb Smirnoff case PF_RDR: 6823b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 6833b3a8eb9SGleb Smirnoff printf(", rdr rule %u", sn->rule.nr); 6843b3a8eb9SGleb Smirnoff break; 6853b3a8eb9SGleb Smirnoff case PF_PASS: 6863b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 6873b3a8eb9SGleb Smirnoff printf(", filter rule %u", sn->rule.nr); 6883b3a8eb9SGleb Smirnoff break; 6893b3a8eb9SGleb Smirnoff } 6903b3a8eb9SGleb Smirnoff printf("\n"); 6913b3a8eb9SGleb Smirnoff } 6923b3a8eb9SGleb Smirnoff } 6933b3a8eb9SGleb Smirnoff 6942b29ceb8SKristof Provost static void 6952b29ceb8SKristof Provost print_eth_addr(const struct pfctl_eth_addr *a) 6962b29ceb8SKristof Provost { 697b590f17aSKristof Provost int i, masklen = ETHER_ADDR_LEN * 8; 698b590f17aSKristof Provost bool seen_unset = false; 699b590f17aSKristof Provost 700c696d5c7SKristof Provost for (i = 0; i < ETHER_ADDR_LEN; i++) { 701c696d5c7SKristof Provost if (a->addr[i] != 0) 702c696d5c7SKristof Provost break; 703c696d5c7SKristof Provost } 704c696d5c7SKristof Provost 705c696d5c7SKristof Provost /* Unset, so don't print anything. */ 706c696d5c7SKristof Provost if (i == ETHER_ADDR_LEN) 707c696d5c7SKristof Provost return; 708c696d5c7SKristof Provost 7092b29ceb8SKristof Provost printf("%s%02x:%02x:%02x:%02x:%02x:%02x", a->neg ? "! " : "", 7102b29ceb8SKristof Provost a->addr[0], a->addr[1], a->addr[2], a->addr[3], a->addr[4], 7112b29ceb8SKristof Provost a->addr[5]); 712b590f17aSKristof Provost 713b590f17aSKristof Provost for (i = 0; i < (ETHER_ADDR_LEN * 8); i++) { 714b590f17aSKristof Provost bool isset = a->mask[i / 8] & (1 << i % 8); 715b590f17aSKristof Provost 716b590f17aSKristof Provost if (! seen_unset) { 717b590f17aSKristof Provost if (isset) 718b590f17aSKristof Provost continue; 719b590f17aSKristof Provost seen_unset = true; 720b590f17aSKristof Provost masklen = i; 721b590f17aSKristof Provost } else { 722b590f17aSKristof Provost /* Not actually a continuous mask, so print the whole 723b590f17aSKristof Provost * thing. */ 724b590f17aSKristof Provost if (isset) 725b590f17aSKristof Provost break; 726b590f17aSKristof Provost continue; 727b590f17aSKristof Provost } 728b590f17aSKristof Provost } 729b590f17aSKristof Provost 730b590f17aSKristof Provost if (masklen == (ETHER_ADDR_LEN * 8)) 731b590f17aSKristof Provost return; 732b590f17aSKristof Provost 733b590f17aSKristof Provost if (i == (ETHER_ADDR_LEN * 8)) { 734b590f17aSKristof Provost printf("/%d", masklen); 735b590f17aSKristof Provost return; 736b590f17aSKristof Provost } 737b590f17aSKristof Provost 738b590f17aSKristof Provost printf("&%02x:%02x:%02x:%02x:%02x:%02x", 739b590f17aSKristof Provost a->mask[0], a->mask[1], a->mask[2], a->mask[3], a->mask[4], 740b590f17aSKristof Provost a->mask[5]); 7412b29ceb8SKristof Provost } 7422b29ceb8SKristof Provost 7432b29ceb8SKristof Provost void 744c5131afeSKristof Provost print_eth_rule(struct pfctl_eth_rule *r, const char *anchor_call, 745c5131afeSKristof Provost int rule_numbers) 7462b29ceb8SKristof Provost { 7472b29ceb8SKristof Provost static const char *actiontypes[] = { "pass", "block" }; 7482b29ceb8SKristof Provost 7492b29ceb8SKristof Provost if (rule_numbers) 7502b29ceb8SKristof Provost printf("@%u ", r->nr); 7512b29ceb8SKristof Provost 752c5131afeSKristof Provost printf("ether "); 753c5131afeSKristof Provost if (anchor_call[0]) { 754c5131afeSKristof Provost if (anchor_call[0] == '_') { 755c5131afeSKristof Provost printf("anchor"); 756c5131afeSKristof Provost } else 757c5131afeSKristof Provost printf("anchor \"%s\"", anchor_call); 758c5131afeSKristof Provost } else { 759c5131afeSKristof Provost printf("%s", actiontypes[r->action]); 760c5131afeSKristof Provost } 7612b29ceb8SKristof Provost if (r->direction == PF_IN) 7622b29ceb8SKristof Provost printf(" in"); 7632b29ceb8SKristof Provost else if (r->direction == PF_OUT) 7642b29ceb8SKristof Provost printf(" out"); 7652b29ceb8SKristof Provost 7662b29ceb8SKristof Provost if (r->quick) 7672b29ceb8SKristof Provost printf(" quick"); 7682b29ceb8SKristof Provost if (r->ifname[0]) { 7692b29ceb8SKristof Provost if (r->ifnot) 7702b29ceb8SKristof Provost printf(" on ! %s", r->ifname); 7712b29ceb8SKristof Provost else 7722b29ceb8SKristof Provost printf(" on %s", r->ifname); 7732b29ceb8SKristof Provost } 7742b29ceb8SKristof Provost if (r->proto) 7752b29ceb8SKristof Provost printf(" proto 0x%04x", r->proto); 7762b29ceb8SKristof Provost 777c696d5c7SKristof Provost if (r->src.isset) { 7782b29ceb8SKristof Provost printf(" from "); 7792b29ceb8SKristof Provost print_eth_addr(&r->src); 780c696d5c7SKristof Provost } 781c696d5c7SKristof Provost if (r->dst.isset) { 7822b29ceb8SKristof Provost printf(" to "); 7832b29ceb8SKristof Provost print_eth_addr(&r->dst); 784c696d5c7SKristof Provost } 785*8a42005dSKristof Provost if (r->proto == ETHERTYPE_IP || r->proto == ETHERTYPE_IPV6) { 786*8a42005dSKristof Provost printf(" l3"); 787*8a42005dSKristof Provost print_fromto(&r->ipsrc, PF_OSFP_ANY, &r->ipdst, 788*8a42005dSKristof Provost r->proto == ETHERTYPE_IP ? AF_INET : AF_INET6, 0, 789*8a42005dSKristof Provost 0, 0); 790*8a42005dSKristof Provost } 7912b29ceb8SKristof Provost if (r->qname[0]) 7922b29ceb8SKristof Provost printf(" queue %s", r->qname); 7932b29ceb8SKristof Provost if (r->tagname[0]) 7942b29ceb8SKristof Provost printf(" tag %s", r->tagname); 795fb330f39SKristof Provost if (r->dnpipe) 796fb330f39SKristof Provost printf(" %s %d", 797fb330f39SKristof Provost r->dnflags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", 798fb330f39SKristof Provost r->dnpipe); 7992b29ceb8SKristof Provost } 8002b29ceb8SKristof Provost 8013b3a8eb9SGleb Smirnoff void 802e9eb0941SKristof Provost print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numeric) 8033b3a8eb9SGleb Smirnoff { 8043b3a8eb9SGleb Smirnoff static const char *actiontypes[] = { "pass", "block", "scrub", 8053b3a8eb9SGleb Smirnoff "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" }; 8063b3a8eb9SGleb Smirnoff static const char *anchortypes[] = { "anchor", "anchor", "anchor", 8073b3a8eb9SGleb Smirnoff "anchor", "nat-anchor", "nat-anchor", "binat-anchor", 8083b3a8eb9SGleb Smirnoff "binat-anchor", "rdr-anchor", "rdr-anchor" }; 8093b3a8eb9SGleb Smirnoff int i, opts; 8103b3a8eb9SGleb Smirnoff 8113b3a8eb9SGleb Smirnoff if (verbose) 8123b3a8eb9SGleb Smirnoff printf("@%d ", r->nr); 813ef950daaSKristof Provost if (r->action == PF_MATCH) 814ef950daaSKristof Provost printf("match"); 815ef950daaSKristof Provost else if (r->action > PF_NORDR) 8163b3a8eb9SGleb Smirnoff printf("action(%d)", r->action); 8173b3a8eb9SGleb Smirnoff else if (anchor_call[0]) { 8183b3a8eb9SGleb Smirnoff if (anchor_call[0] == '_') { 8193b3a8eb9SGleb Smirnoff printf("%s", anchortypes[r->action]); 8203b3a8eb9SGleb Smirnoff } else 8213b3a8eb9SGleb Smirnoff printf("%s \"%s\"", anchortypes[r->action], 8223b3a8eb9SGleb Smirnoff anchor_call); 8233b3a8eb9SGleb Smirnoff } else { 8243b3a8eb9SGleb Smirnoff printf("%s", actiontypes[r->action]); 8253b3a8eb9SGleb Smirnoff if (r->natpass) 8263b3a8eb9SGleb Smirnoff printf(" pass"); 8273b3a8eb9SGleb Smirnoff } 8283b3a8eb9SGleb Smirnoff if (r->action == PF_DROP) { 8293b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RETURN) 8303b3a8eb9SGleb Smirnoff printf(" return"); 8313b3a8eb9SGleb Smirnoff else if (r->rule_flag & PFRULE_RETURNRST) { 8323b3a8eb9SGleb Smirnoff if (!r->return_ttl) 8333b3a8eb9SGleb Smirnoff printf(" return-rst"); 8343b3a8eb9SGleb Smirnoff else 8353b3a8eb9SGleb Smirnoff printf(" return-rst(ttl %d)", r->return_ttl); 8363b3a8eb9SGleb Smirnoff } else if (r->rule_flag & PFRULE_RETURNICMP) { 8373b3a8eb9SGleb Smirnoff const struct icmpcodeent *ic, *ic6; 8383b3a8eb9SGleb Smirnoff 8393b3a8eb9SGleb Smirnoff ic = geticmpcodebynumber(r->return_icmp >> 8, 8403b3a8eb9SGleb Smirnoff r->return_icmp & 255, AF_INET); 8413b3a8eb9SGleb Smirnoff ic6 = geticmpcodebynumber(r->return_icmp6 >> 8, 8423b3a8eb9SGleb Smirnoff r->return_icmp6 & 255, AF_INET6); 8433b3a8eb9SGleb Smirnoff 8443b3a8eb9SGleb Smirnoff switch (r->af) { 8453b3a8eb9SGleb Smirnoff case AF_INET: 8463b3a8eb9SGleb Smirnoff printf(" return-icmp"); 8473b3a8eb9SGleb Smirnoff if (ic == NULL) 8483b3a8eb9SGleb Smirnoff printf("(%u)", r->return_icmp & 255); 8493b3a8eb9SGleb Smirnoff else 8503b3a8eb9SGleb Smirnoff printf("(%s)", ic->name); 8513b3a8eb9SGleb Smirnoff break; 8523b3a8eb9SGleb Smirnoff case AF_INET6: 8533b3a8eb9SGleb Smirnoff printf(" return-icmp6"); 8543b3a8eb9SGleb Smirnoff if (ic6 == NULL) 8553b3a8eb9SGleb Smirnoff printf("(%u)", r->return_icmp6 & 255); 8563b3a8eb9SGleb Smirnoff else 8573b3a8eb9SGleb Smirnoff printf("(%s)", ic6->name); 8583b3a8eb9SGleb Smirnoff break; 8593b3a8eb9SGleb Smirnoff default: 8603b3a8eb9SGleb Smirnoff printf(" return-icmp"); 8613b3a8eb9SGleb Smirnoff if (ic == NULL) 8623b3a8eb9SGleb Smirnoff printf("(%u, ", r->return_icmp & 255); 8633b3a8eb9SGleb Smirnoff else 8643b3a8eb9SGleb Smirnoff printf("(%s, ", ic->name); 8653b3a8eb9SGleb Smirnoff if (ic6 == NULL) 8663b3a8eb9SGleb Smirnoff printf("%u)", r->return_icmp6 & 255); 8673b3a8eb9SGleb Smirnoff else 8683b3a8eb9SGleb Smirnoff printf("%s)", ic6->name); 8693b3a8eb9SGleb Smirnoff break; 8703b3a8eb9SGleb Smirnoff } 8713b3a8eb9SGleb Smirnoff } else 8723b3a8eb9SGleb Smirnoff printf(" drop"); 8733b3a8eb9SGleb Smirnoff } 8743b3a8eb9SGleb Smirnoff if (r->direction == PF_IN) 8753b3a8eb9SGleb Smirnoff printf(" in"); 8763b3a8eb9SGleb Smirnoff else if (r->direction == PF_OUT) 8773b3a8eb9SGleb Smirnoff printf(" out"); 8783b3a8eb9SGleb Smirnoff if (r->log) { 8793b3a8eb9SGleb Smirnoff printf(" log"); 8803b3a8eb9SGleb Smirnoff if (r->log & ~PF_LOG || r->logif) { 8813b3a8eb9SGleb Smirnoff int count = 0; 8823b3a8eb9SGleb Smirnoff 8833b3a8eb9SGleb Smirnoff printf(" ("); 8843b3a8eb9SGleb Smirnoff if (r->log & PF_LOG_ALL) 8853b3a8eb9SGleb Smirnoff printf("%sall", count++ ? ", " : ""); 8863b3a8eb9SGleb Smirnoff if (r->log & PF_LOG_SOCKET_LOOKUP) 8873b3a8eb9SGleb Smirnoff printf("%suser", count++ ? ", " : ""); 8883b3a8eb9SGleb Smirnoff if (r->logif) 8893b3a8eb9SGleb Smirnoff printf("%sto pflog%u", count++ ? ", " : "", 8903b3a8eb9SGleb Smirnoff r->logif); 8913b3a8eb9SGleb Smirnoff printf(")"); 8923b3a8eb9SGleb Smirnoff } 8933b3a8eb9SGleb Smirnoff } 8943b3a8eb9SGleb Smirnoff if (r->quick) 8953b3a8eb9SGleb Smirnoff printf(" quick"); 8963b3a8eb9SGleb Smirnoff if (r->ifname[0]) { 8973b3a8eb9SGleb Smirnoff if (r->ifnot) 8983b3a8eb9SGleb Smirnoff printf(" on ! %s", r->ifname); 8993b3a8eb9SGleb Smirnoff else 9003b3a8eb9SGleb Smirnoff printf(" on %s", r->ifname); 9013b3a8eb9SGleb Smirnoff } 9023b3a8eb9SGleb Smirnoff if (r->rt) { 9033b3a8eb9SGleb Smirnoff if (r->rt == PF_ROUTETO) 9043b3a8eb9SGleb Smirnoff printf(" route-to"); 9053b3a8eb9SGleb Smirnoff else if (r->rt == PF_REPLYTO) 9063b3a8eb9SGleb Smirnoff printf(" reply-to"); 9073b3a8eb9SGleb Smirnoff else if (r->rt == PF_DUPTO) 9083b3a8eb9SGleb Smirnoff printf(" dup-to"); 9093b3a8eb9SGleb Smirnoff printf(" "); 9103b3a8eb9SGleb Smirnoff print_pool(&r->rpool, 0, 0, r->af, PF_PASS); 9113b3a8eb9SGleb Smirnoff } 9123b3a8eb9SGleb Smirnoff if (r->af) { 9133b3a8eb9SGleb Smirnoff if (r->af == AF_INET) 9143b3a8eb9SGleb Smirnoff printf(" inet"); 9153b3a8eb9SGleb Smirnoff else 9163b3a8eb9SGleb Smirnoff printf(" inet6"); 9173b3a8eb9SGleb Smirnoff } 9183b3a8eb9SGleb Smirnoff if (r->proto) { 919858937beSMateusz Guzik const char *protoname; 9203b3a8eb9SGleb Smirnoff 921858937beSMateusz Guzik if ((protoname = pfctl_proto2name(r->proto)) != NULL) 922858937beSMateusz Guzik printf(" proto %s", protoname); 9233b3a8eb9SGleb Smirnoff else 9243b3a8eb9SGleb Smirnoff printf(" proto %u", r->proto); 9253b3a8eb9SGleb Smirnoff } 9263b3a8eb9SGleb Smirnoff print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto, 9273b3a8eb9SGleb Smirnoff verbose, numeric); 9283b3a8eb9SGleb Smirnoff if (r->uid.op) 9293b3a8eb9SGleb Smirnoff print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user", 9303b3a8eb9SGleb Smirnoff UID_MAX); 9313b3a8eb9SGleb Smirnoff if (r->gid.op) 9323b3a8eb9SGleb Smirnoff print_ugid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group", 9333b3a8eb9SGleb Smirnoff GID_MAX); 9343b3a8eb9SGleb Smirnoff if (r->flags || r->flagset) { 9353b3a8eb9SGleb Smirnoff printf(" flags "); 9363b3a8eb9SGleb Smirnoff print_flags(r->flags); 9373b3a8eb9SGleb Smirnoff printf("/"); 9383b3a8eb9SGleb Smirnoff print_flags(r->flagset); 9393b3a8eb9SGleb Smirnoff } else if (r->action == PF_PASS && 9403b3a8eb9SGleb Smirnoff (!r->proto || r->proto == IPPROTO_TCP) && 9413b3a8eb9SGleb Smirnoff !(r->rule_flag & PFRULE_FRAGMENT) && 9423b3a8eb9SGleb Smirnoff !anchor_call[0] && r->keep_state) 9433b3a8eb9SGleb Smirnoff printf(" flags any"); 9443b3a8eb9SGleb Smirnoff if (r->type) { 9453b3a8eb9SGleb Smirnoff const struct icmptypeent *it; 9463b3a8eb9SGleb Smirnoff 9473b3a8eb9SGleb Smirnoff it = geticmptypebynumber(r->type-1, r->af); 9483b3a8eb9SGleb Smirnoff if (r->af != AF_INET6) 9493b3a8eb9SGleb Smirnoff printf(" icmp-type"); 9503b3a8eb9SGleb Smirnoff else 9513b3a8eb9SGleb Smirnoff printf(" icmp6-type"); 9523b3a8eb9SGleb Smirnoff if (it != NULL) 9533b3a8eb9SGleb Smirnoff printf(" %s", it->name); 9543b3a8eb9SGleb Smirnoff else 9553b3a8eb9SGleb Smirnoff printf(" %u", r->type-1); 9563b3a8eb9SGleb Smirnoff if (r->code) { 9573b3a8eb9SGleb Smirnoff const struct icmpcodeent *ic; 9583b3a8eb9SGleb Smirnoff 9593b3a8eb9SGleb Smirnoff ic = geticmpcodebynumber(r->type-1, r->code-1, r->af); 9603b3a8eb9SGleb Smirnoff if (ic != NULL) 9613b3a8eb9SGleb Smirnoff printf(" code %s", ic->name); 9623b3a8eb9SGleb Smirnoff else 9633b3a8eb9SGleb Smirnoff printf(" code %u", r->code-1); 9643b3a8eb9SGleb Smirnoff } 9653b3a8eb9SGleb Smirnoff } 9663b3a8eb9SGleb Smirnoff if (r->tos) 9673b3a8eb9SGleb Smirnoff printf(" tos 0x%2.2x", r->tos); 9683e248e0fSKristof Provost if (r->prio) 9693e248e0fSKristof Provost printf(" prio %u", r->prio == PF_PRIO_ZERO ? 0 : r->prio); 9703e248e0fSKristof Provost if (r->scrub_flags & PFSTATE_SETMASK) { 9713e248e0fSKristof Provost char *comma = ""; 9723e248e0fSKristof Provost printf(" set ("); 9733e248e0fSKristof Provost if (r->scrub_flags & PFSTATE_SETPRIO) { 9743e248e0fSKristof Provost if (r->set_prio[0] == r->set_prio[1]) 9753e248e0fSKristof Provost printf("%s prio %u", comma, r->set_prio[0]); 9763e248e0fSKristof Provost else 9773e248e0fSKristof Provost printf("%s prio(%u, %u)", comma, r->set_prio[0], 9783e248e0fSKristof Provost r->set_prio[1]); 9793e248e0fSKristof Provost comma = ","; 9803e248e0fSKristof Provost } 9813e248e0fSKristof Provost printf(" )"); 9823e248e0fSKristof Provost } 9833b3a8eb9SGleb Smirnoff if (!r->keep_state && r->action == PF_PASS && !anchor_call[0]) 9843b3a8eb9SGleb Smirnoff printf(" no state"); 9853b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_NORMAL) 9863b3a8eb9SGleb Smirnoff printf(" keep state"); 9873b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_MODULATE) 9883b3a8eb9SGleb Smirnoff printf(" modulate state"); 9893b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_SYNPROXY) 9903b3a8eb9SGleb Smirnoff printf(" synproxy state"); 9913b3a8eb9SGleb Smirnoff if (r->prob) { 9923b3a8eb9SGleb Smirnoff char buf[20]; 9933b3a8eb9SGleb Smirnoff 9943b3a8eb9SGleb Smirnoff snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0)); 9953b3a8eb9SGleb Smirnoff for (i = strlen(buf)-1; i > 0; i--) { 9963b3a8eb9SGleb Smirnoff if (buf[i] == '0') 9973b3a8eb9SGleb Smirnoff buf[i] = '\0'; 9983b3a8eb9SGleb Smirnoff else { 9993b3a8eb9SGleb Smirnoff if (buf[i] == '.') 10003b3a8eb9SGleb Smirnoff buf[i] = '\0'; 10013b3a8eb9SGleb Smirnoff break; 10023b3a8eb9SGleb Smirnoff } 10033b3a8eb9SGleb Smirnoff } 10043b3a8eb9SGleb Smirnoff printf(" probability %s%%", buf); 10053b3a8eb9SGleb Smirnoff } 10063b3a8eb9SGleb Smirnoff opts = 0; 10073b3a8eb9SGleb Smirnoff if (r->max_states || r->max_src_nodes || r->max_src_states) 10083b3a8eb9SGleb Smirnoff opts = 1; 10093b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NOSYNC) 10103b3a8eb9SGleb Smirnoff opts = 1; 10113b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SRCTRACK) 10123b3a8eb9SGleb Smirnoff opts = 1; 10133b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_IFBOUND) 10143b3a8eb9SGleb Smirnoff opts = 1; 10153b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY) 10163b3a8eb9SGleb Smirnoff opts = 1; 10173b3a8eb9SGleb Smirnoff for (i = 0; !opts && i < PFTM_MAX; ++i) 10183b3a8eb9SGleb Smirnoff if (r->timeout[i]) 10193b3a8eb9SGleb Smirnoff opts = 1; 10203b3a8eb9SGleb Smirnoff if (opts) { 10213b3a8eb9SGleb Smirnoff printf(" ("); 10223b3a8eb9SGleb Smirnoff if (r->max_states) { 10233b3a8eb9SGleb Smirnoff printf("max %u", r->max_states); 10243b3a8eb9SGleb Smirnoff opts = 0; 10253b3a8eb9SGleb Smirnoff } 10263b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NOSYNC) { 10273b3a8eb9SGleb Smirnoff if (!opts) 10283b3a8eb9SGleb Smirnoff printf(", "); 10293b3a8eb9SGleb Smirnoff printf("no-sync"); 10303b3a8eb9SGleb Smirnoff opts = 0; 10313b3a8eb9SGleb Smirnoff } 10323b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SRCTRACK) { 10333b3a8eb9SGleb Smirnoff if (!opts) 10343b3a8eb9SGleb Smirnoff printf(", "); 10353b3a8eb9SGleb Smirnoff printf("source-track"); 10363b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RULESRCTRACK) 10373b3a8eb9SGleb Smirnoff printf(" rule"); 10383b3a8eb9SGleb Smirnoff else 10393b3a8eb9SGleb Smirnoff printf(" global"); 10403b3a8eb9SGleb Smirnoff opts = 0; 10413b3a8eb9SGleb Smirnoff } 10423b3a8eb9SGleb Smirnoff if (r->max_src_states) { 10433b3a8eb9SGleb Smirnoff if (!opts) 10443b3a8eb9SGleb Smirnoff printf(", "); 10453b3a8eb9SGleb Smirnoff printf("max-src-states %u", r->max_src_states); 10463b3a8eb9SGleb Smirnoff opts = 0; 10473b3a8eb9SGleb Smirnoff } 10483b3a8eb9SGleb Smirnoff if (r->max_src_conn) { 10493b3a8eb9SGleb Smirnoff if (!opts) 10503b3a8eb9SGleb Smirnoff printf(", "); 10513b3a8eb9SGleb Smirnoff printf("max-src-conn %u", r->max_src_conn); 10523b3a8eb9SGleb Smirnoff opts = 0; 10533b3a8eb9SGleb Smirnoff } 10543b3a8eb9SGleb Smirnoff if (r->max_src_conn_rate.limit) { 10553b3a8eb9SGleb Smirnoff if (!opts) 10563b3a8eb9SGleb Smirnoff printf(", "); 10573b3a8eb9SGleb Smirnoff printf("max-src-conn-rate %u/%u", 10583b3a8eb9SGleb Smirnoff r->max_src_conn_rate.limit, 10593b3a8eb9SGleb Smirnoff r->max_src_conn_rate.seconds); 10603b3a8eb9SGleb Smirnoff opts = 0; 10613b3a8eb9SGleb Smirnoff } 10623b3a8eb9SGleb Smirnoff if (r->max_src_nodes) { 10633b3a8eb9SGleb Smirnoff if (!opts) 10643b3a8eb9SGleb Smirnoff printf(", "); 10653b3a8eb9SGleb Smirnoff printf("max-src-nodes %u", r->max_src_nodes); 10663b3a8eb9SGleb Smirnoff opts = 0; 10673b3a8eb9SGleb Smirnoff } 10683b3a8eb9SGleb Smirnoff if (r->overload_tblname[0]) { 10693b3a8eb9SGleb Smirnoff if (!opts) 10703b3a8eb9SGleb Smirnoff printf(", "); 10713b3a8eb9SGleb Smirnoff printf("overload <%s>", r->overload_tblname); 10723b3a8eb9SGleb Smirnoff if (r->flush) 10733b3a8eb9SGleb Smirnoff printf(" flush"); 10743b3a8eb9SGleb Smirnoff if (r->flush & PF_FLUSH_GLOBAL) 10753b3a8eb9SGleb Smirnoff printf(" global"); 10763b3a8eb9SGleb Smirnoff } 10773b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_IFBOUND) { 10783b3a8eb9SGleb Smirnoff if (!opts) 10793b3a8eb9SGleb Smirnoff printf(", "); 10803b3a8eb9SGleb Smirnoff printf("if-bound"); 10813b3a8eb9SGleb Smirnoff opts = 0; 10823b3a8eb9SGleb Smirnoff } 10833b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY) { 10843b3a8eb9SGleb Smirnoff if (!opts) 10853b3a8eb9SGleb Smirnoff printf(", "); 10863b3a8eb9SGleb Smirnoff printf("sloppy"); 10873b3a8eb9SGleb Smirnoff opts = 0; 10883b3a8eb9SGleb Smirnoff } 10893b3a8eb9SGleb Smirnoff for (i = 0; i < PFTM_MAX; ++i) 10903b3a8eb9SGleb Smirnoff if (r->timeout[i]) { 10913b3a8eb9SGleb Smirnoff int j; 10923b3a8eb9SGleb Smirnoff 10933b3a8eb9SGleb Smirnoff if (!opts) 10943b3a8eb9SGleb Smirnoff printf(", "); 10953b3a8eb9SGleb Smirnoff opts = 0; 10963b3a8eb9SGleb Smirnoff for (j = 0; pf_timeouts[j].name != NULL; 10973b3a8eb9SGleb Smirnoff ++j) 10983b3a8eb9SGleb Smirnoff if (pf_timeouts[j].timeout == i) 10993b3a8eb9SGleb Smirnoff break; 11003b3a8eb9SGleb Smirnoff printf("%s %u", pf_timeouts[j].name == NULL ? 11013b3a8eb9SGleb Smirnoff "inv.timeout" : pf_timeouts[j].name, 11023b3a8eb9SGleb Smirnoff r->timeout[i]); 11033b3a8eb9SGleb Smirnoff } 11043b3a8eb9SGleb Smirnoff printf(")"); 11053b3a8eb9SGleb Smirnoff } 11063b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_FRAGMENT) 11073b3a8eb9SGleb Smirnoff printf(" fragment"); 11083b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NODF) 11093b3a8eb9SGleb Smirnoff printf(" no-df"); 11103b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RANDOMID) 11113b3a8eb9SGleb Smirnoff printf(" random-id"); 11123b3a8eb9SGleb Smirnoff if (r->min_ttl) 11133b3a8eb9SGleb Smirnoff printf(" min-ttl %d", r->min_ttl); 11143b3a8eb9SGleb Smirnoff if (r->max_mss) 11153b3a8eb9SGleb Smirnoff printf(" max-mss %d", r->max_mss); 11163b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SET_TOS) 11173b3a8eb9SGleb Smirnoff printf(" set-tos 0x%2.2x", r->set_tos); 11183b3a8eb9SGleb Smirnoff if (r->allow_opts) 11193b3a8eb9SGleb Smirnoff printf(" allow-opts"); 11203b3a8eb9SGleb Smirnoff if (r->action == PF_SCRUB) { 11213b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_REASSEMBLE_TCP) 11223b3a8eb9SGleb Smirnoff printf(" reassemble tcp"); 11233b3a8eb9SGleb Smirnoff 11243b3a8eb9SGleb Smirnoff printf(" fragment reassemble"); 11253b3a8eb9SGleb Smirnoff } 11266fcc8e04SKristof Provost i = 0; 11276fcc8e04SKristof Provost while (r->label[i][0]) 11286fcc8e04SKristof Provost printf(" label \"%s\"", r->label[i++]); 112976c5eeccSKristof Provost if (r->ridentifier) 113076c5eeccSKristof Provost printf(" ridentifier %u", r->ridentifier); 113163b3c1c7SKristof Provost /* Only dnrpipe as we might do (0, 42) to only queue return traffic. */ 113263b3c1c7SKristof Provost if (r->dnrpipe) 113363b3c1c7SKristof Provost printf(" %s(%d, %d)", 113463b3c1c7SKristof Provost r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", 113563b3c1c7SKristof Provost r->dnpipe, r->dnrpipe); 113663b3c1c7SKristof Provost else if (r->dnpipe) 113763b3c1c7SKristof Provost printf(" %s %d", 113863b3c1c7SKristof Provost r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", 113963b3c1c7SKristof Provost r->dnpipe); 11403b3a8eb9SGleb Smirnoff if (r->qname[0] && r->pqname[0]) 11413b3a8eb9SGleb Smirnoff printf(" queue(%s, %s)", r->qname, r->pqname); 11423b3a8eb9SGleb Smirnoff else if (r->qname[0]) 11433b3a8eb9SGleb Smirnoff printf(" queue %s", r->qname); 11443b3a8eb9SGleb Smirnoff if (r->tagname[0]) 11453b3a8eb9SGleb Smirnoff printf(" tag %s", r->tagname); 11463b3a8eb9SGleb Smirnoff if (r->match_tagname[0]) { 11473b3a8eb9SGleb Smirnoff if (r->match_tag_not) 11483b3a8eb9SGleb Smirnoff printf(" !"); 11493b3a8eb9SGleb Smirnoff printf(" tagged %s", r->match_tagname); 11503b3a8eb9SGleb Smirnoff } 11513b3a8eb9SGleb Smirnoff if (r->rtableid != -1) 11523b3a8eb9SGleb Smirnoff printf(" rtable %u", r->rtableid); 11533b3a8eb9SGleb Smirnoff if (r->divert.port) { 11543b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 11553b3a8eb9SGleb Smirnoff printf(" divert-to %u", ntohs(r->divert.port)); 11563b3a8eb9SGleb Smirnoff #else 11573b3a8eb9SGleb Smirnoff if (PF_AZERO(&r->divert.addr, r->af)) { 11583b3a8eb9SGleb Smirnoff printf(" divert-reply"); 11593b3a8eb9SGleb Smirnoff } else { 11603b3a8eb9SGleb Smirnoff /* XXX cut&paste from print_addr */ 11613b3a8eb9SGleb Smirnoff char buf[48]; 11623b3a8eb9SGleb Smirnoff 11633b3a8eb9SGleb Smirnoff printf(" divert-to "); 11643b3a8eb9SGleb Smirnoff if (inet_ntop(r->af, &r->divert.addr, buf, 11653b3a8eb9SGleb Smirnoff sizeof(buf)) == NULL) 11663b3a8eb9SGleb Smirnoff printf("?"); 11673b3a8eb9SGleb Smirnoff else 11683b3a8eb9SGleb Smirnoff printf("%s", buf); 11693b3a8eb9SGleb Smirnoff printf(" port %u", ntohs(r->divert.port)); 11703b3a8eb9SGleb Smirnoff } 11713b3a8eb9SGleb Smirnoff #endif 11723b3a8eb9SGleb Smirnoff } 11733b3a8eb9SGleb Smirnoff if (!anchor_call[0] && (r->action == PF_NAT || 11743b3a8eb9SGleb Smirnoff r->action == PF_BINAT || r->action == PF_RDR)) { 11753b3a8eb9SGleb Smirnoff printf(" -> "); 11763b3a8eb9SGleb Smirnoff print_pool(&r->rpool, r->rpool.proxy_port[0], 11773b3a8eb9SGleb Smirnoff r->rpool.proxy_port[1], r->af, r->action); 11783b3a8eb9SGleb Smirnoff } 11793b3a8eb9SGleb Smirnoff } 11803b3a8eb9SGleb Smirnoff 11813b3a8eb9SGleb Smirnoff void 11823b3a8eb9SGleb Smirnoff print_tabledef(const char *name, int flags, int addrs, 11833b3a8eb9SGleb Smirnoff struct node_tinithead *nodes) 11843b3a8eb9SGleb Smirnoff { 11853b3a8eb9SGleb Smirnoff struct node_tinit *ti, *nti; 11863b3a8eb9SGleb Smirnoff struct node_host *h; 11873b3a8eb9SGleb Smirnoff 11883b3a8eb9SGleb Smirnoff printf("table <%s>", name); 11893b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_CONST) 11903b3a8eb9SGleb Smirnoff printf(" const"); 11913b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_PERSIST) 11923b3a8eb9SGleb Smirnoff printf(" persist"); 11933b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_COUNTERS) 11943b3a8eb9SGleb Smirnoff printf(" counters"); 11953b3a8eb9SGleb Smirnoff SIMPLEQ_FOREACH(ti, nodes, entries) { 11963b3a8eb9SGleb Smirnoff if (ti->file) { 11973b3a8eb9SGleb Smirnoff printf(" file \"%s\"", ti->file); 11983b3a8eb9SGleb Smirnoff continue; 11993b3a8eb9SGleb Smirnoff } 12003b3a8eb9SGleb Smirnoff printf(" {"); 12013b3a8eb9SGleb Smirnoff for (;;) { 12023b3a8eb9SGleb Smirnoff for (h = ti->host; h != NULL; h = h->next) { 12033b3a8eb9SGleb Smirnoff printf(h->not ? " !" : " "); 12043b3a8eb9SGleb Smirnoff print_addr(&h->addr, h->af, 0); 12053b3a8eb9SGleb Smirnoff } 12063b3a8eb9SGleb Smirnoff nti = SIMPLEQ_NEXT(ti, entries); 12073b3a8eb9SGleb Smirnoff if (nti != NULL && nti->file == NULL) 12083b3a8eb9SGleb Smirnoff ti = nti; /* merge lists */ 12093b3a8eb9SGleb Smirnoff else 12103b3a8eb9SGleb Smirnoff break; 12113b3a8eb9SGleb Smirnoff } 12123b3a8eb9SGleb Smirnoff printf(" }"); 12133b3a8eb9SGleb Smirnoff } 12143b3a8eb9SGleb Smirnoff if (addrs && SIMPLEQ_EMPTY(nodes)) 12153b3a8eb9SGleb Smirnoff printf(" { }"); 12163b3a8eb9SGleb Smirnoff printf("\n"); 12173b3a8eb9SGleb Smirnoff } 12183b3a8eb9SGleb Smirnoff 12193b3a8eb9SGleb Smirnoff int 12203b3a8eb9SGleb Smirnoff parse_flags(char *s) 12213b3a8eb9SGleb Smirnoff { 12223b3a8eb9SGleb Smirnoff char *p, *q; 12233b3a8eb9SGleb Smirnoff u_int8_t f = 0; 12243b3a8eb9SGleb Smirnoff 12253b3a8eb9SGleb Smirnoff for (p = s; *p; p++) { 12263b3a8eb9SGleb Smirnoff if ((q = strchr(tcpflags, *p)) == NULL) 12273b3a8eb9SGleb Smirnoff return -1; 12283b3a8eb9SGleb Smirnoff else 12293b3a8eb9SGleb Smirnoff f |= 1 << (q - tcpflags); 12303b3a8eb9SGleb Smirnoff } 12313b3a8eb9SGleb Smirnoff return (f ? f : PF_TH_ALL); 12323b3a8eb9SGleb Smirnoff } 12333b3a8eb9SGleb Smirnoff 12343b3a8eb9SGleb Smirnoff void 12353b3a8eb9SGleb Smirnoff set_ipmask(struct node_host *h, u_int8_t b) 12363b3a8eb9SGleb Smirnoff { 12373b3a8eb9SGleb Smirnoff struct pf_addr *m, *n; 12383b3a8eb9SGleb Smirnoff int i, j = 0; 12393b3a8eb9SGleb Smirnoff 12403b3a8eb9SGleb Smirnoff m = &h->addr.v.a.mask; 12413b3a8eb9SGleb Smirnoff memset(m, 0, sizeof(*m)); 12423b3a8eb9SGleb Smirnoff 12433b3a8eb9SGleb Smirnoff while (b >= 32) { 12443b3a8eb9SGleb Smirnoff m->addr32[j++] = 0xffffffff; 12453b3a8eb9SGleb Smirnoff b -= 32; 12463b3a8eb9SGleb Smirnoff } 12473b3a8eb9SGleb Smirnoff for (i = 31; i > 31-b; --i) 12483b3a8eb9SGleb Smirnoff m->addr32[j] |= (1 << i); 12493b3a8eb9SGleb Smirnoff if (b) 12503b3a8eb9SGleb Smirnoff m->addr32[j] = htonl(m->addr32[j]); 12513b3a8eb9SGleb Smirnoff 12523b3a8eb9SGleb Smirnoff /* Mask off bits of the address that will never be used. */ 12533b3a8eb9SGleb Smirnoff n = &h->addr.v.a.addr; 12543b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_ADDRMASK) 12553b3a8eb9SGleb Smirnoff for (i = 0; i < 4; i++) 12563b3a8eb9SGleb Smirnoff n->addr32[i] = n->addr32[i] & m->addr32[i]; 12573b3a8eb9SGleb Smirnoff } 12583b3a8eb9SGleb Smirnoff 12593b3a8eb9SGleb Smirnoff int 12603b3a8eb9SGleb Smirnoff check_netmask(struct node_host *h, sa_family_t af) 12613b3a8eb9SGleb Smirnoff { 12623b3a8eb9SGleb Smirnoff struct node_host *n = NULL; 12633b3a8eb9SGleb Smirnoff struct pf_addr *m; 12643b3a8eb9SGleb Smirnoff 12653b3a8eb9SGleb Smirnoff for (n = h; n != NULL; n = n->next) { 12663b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_TABLE) 12673b3a8eb9SGleb Smirnoff continue; 12683b3a8eb9SGleb Smirnoff m = &h->addr.v.a.mask; 12693b3a8eb9SGleb Smirnoff /* fix up netmask for dynaddr */ 12703b3a8eb9SGleb Smirnoff if (af == AF_INET && h->addr.type == PF_ADDR_DYNIFTL && 12713b3a8eb9SGleb Smirnoff unmask(m, AF_INET6) > 32) 12723b3a8eb9SGleb Smirnoff set_ipmask(n, 32); 12733b3a8eb9SGleb Smirnoff /* netmasks > 32 bit are invalid on v4 */ 12743b3a8eb9SGleb Smirnoff if (af == AF_INET && 12753b3a8eb9SGleb Smirnoff (m->addr32[1] || m->addr32[2] || m->addr32[3])) { 12763b3a8eb9SGleb Smirnoff fprintf(stderr, "netmask %u invalid for IPv4 address\n", 12773b3a8eb9SGleb Smirnoff unmask(m, AF_INET6)); 12783b3a8eb9SGleb Smirnoff return (1); 12793b3a8eb9SGleb Smirnoff } 12803b3a8eb9SGleb Smirnoff } 12813b3a8eb9SGleb Smirnoff return (0); 12823b3a8eb9SGleb Smirnoff } 12833b3a8eb9SGleb Smirnoff 12843b3a8eb9SGleb Smirnoff /* interface lookup routines */ 12853b3a8eb9SGleb Smirnoff 128613cfafabSKristof Provost static struct node_host *iftab; 12873b3a8eb9SGleb Smirnoff 12881d34c9daSPatrick Kelsey /* 12891d34c9daSPatrick Kelsey * Retrieve the list of groups this interface is a member of and make sure 12901d34c9daSPatrick Kelsey * each group is in the group map. 12911d34c9daSPatrick Kelsey */ 12921d34c9daSPatrick Kelsey static void 12931d34c9daSPatrick Kelsey ifa_add_groups_to_map(char *ifa_name) 12941d34c9daSPatrick Kelsey { 12951d34c9daSPatrick Kelsey int s, len; 12961d34c9daSPatrick Kelsey struct ifgroupreq ifgr; 12971d34c9daSPatrick Kelsey struct ifg_req *ifg; 12981d34c9daSPatrick Kelsey 12991d34c9daSPatrick Kelsey s = get_query_socket(); 13001d34c9daSPatrick Kelsey 13011d34c9daSPatrick Kelsey /* Get size of group list for this interface */ 13021d34c9daSPatrick Kelsey memset(&ifgr, 0, sizeof(ifgr)); 13031d34c9daSPatrick Kelsey strlcpy(ifgr.ifgr_name, ifa_name, IFNAMSIZ); 13041d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 13051d34c9daSPatrick Kelsey err(1, "SIOCGIFGROUP"); 13061d34c9daSPatrick Kelsey 13071d34c9daSPatrick Kelsey /* Retrieve group list for this interface */ 13081d34c9daSPatrick Kelsey len = ifgr.ifgr_len; 13091d34c9daSPatrick Kelsey ifgr.ifgr_groups = 13101d34c9daSPatrick Kelsey (struct ifg_req *)calloc(len / sizeof(struct ifg_req), 13111d34c9daSPatrick Kelsey sizeof(struct ifg_req)); 13121d34c9daSPatrick Kelsey if (ifgr.ifgr_groups == NULL) 13131d34c9daSPatrick Kelsey err(1, "calloc"); 13141d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 13151d34c9daSPatrick Kelsey err(1, "SIOCGIFGROUP"); 13161d34c9daSPatrick Kelsey 13171d34c9daSPatrick Kelsey ifg = ifgr.ifgr_groups; 13181d34c9daSPatrick Kelsey for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 13191d34c9daSPatrick Kelsey len -= sizeof(struct ifg_req); 13201d34c9daSPatrick Kelsey if (strcmp(ifg->ifgrq_group, "all")) { 13211d34c9daSPatrick Kelsey ENTRY item; 13221d34c9daSPatrick Kelsey ENTRY *ret_item; 13231d34c9daSPatrick Kelsey int *answer; 13241d34c9daSPatrick Kelsey 13251d34c9daSPatrick Kelsey item.key = ifg->ifgrq_group; 13261d34c9daSPatrick Kelsey if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) { 13271d34c9daSPatrick Kelsey struct ifgroupreq ifgr2; 13281d34c9daSPatrick Kelsey 13291d34c9daSPatrick Kelsey /* Don't know the answer yet */ 13301d34c9daSPatrick Kelsey if ((answer = malloc(sizeof(int))) == NULL) 13311d34c9daSPatrick Kelsey err(1, "malloc"); 13321d34c9daSPatrick Kelsey 13331d34c9daSPatrick Kelsey bzero(&ifgr2, sizeof(ifgr2)); 13341d34c9daSPatrick Kelsey strlcpy(ifgr2.ifgr_name, ifg->ifgrq_group, 13351d34c9daSPatrick Kelsey sizeof(ifgr2.ifgr_name)); 13361d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr2) == 0) 13371d34c9daSPatrick Kelsey *answer = ifgr2.ifgr_len; 13381d34c9daSPatrick Kelsey else 13391d34c9daSPatrick Kelsey *answer = 0; 13401d34c9daSPatrick Kelsey 13411d34c9daSPatrick Kelsey item.key = strdup(ifg->ifgrq_group); 13421d34c9daSPatrick Kelsey item.data = answer; 13431d34c9daSPatrick Kelsey if (hsearch_r(item, ENTER, &ret_item, 13441d34c9daSPatrick Kelsey &isgroup_map) == 0) 13451d34c9daSPatrick Kelsey err(1, "interface group query response" 13461d34c9daSPatrick Kelsey " map insert"); 13471d34c9daSPatrick Kelsey } 13481d34c9daSPatrick Kelsey } 13491d34c9daSPatrick Kelsey } 13501d34c9daSPatrick Kelsey free(ifgr.ifgr_groups); 13511d34c9daSPatrick Kelsey } 13521d34c9daSPatrick Kelsey 13533b3a8eb9SGleb Smirnoff void 13543b3a8eb9SGleb Smirnoff ifa_load(void) 13553b3a8eb9SGleb Smirnoff { 13563b3a8eb9SGleb Smirnoff struct ifaddrs *ifap, *ifa; 13573b3a8eb9SGleb Smirnoff struct node_host *n = NULL, *h = NULL; 13583b3a8eb9SGleb Smirnoff 13593b3a8eb9SGleb Smirnoff if (getifaddrs(&ifap) < 0) 13603b3a8eb9SGleb Smirnoff err(1, "getifaddrs"); 13613b3a8eb9SGleb Smirnoff 13623b3a8eb9SGleb Smirnoff for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 13633b3a8eb9SGleb Smirnoff if (!(ifa->ifa_addr->sa_family == AF_INET || 13643b3a8eb9SGleb Smirnoff ifa->ifa_addr->sa_family == AF_INET6 || 13653b3a8eb9SGleb Smirnoff ifa->ifa_addr->sa_family == AF_LINK)) 13663b3a8eb9SGleb Smirnoff continue; 13673b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 13683b3a8eb9SGleb Smirnoff if (n == NULL) 13693b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 13703b3a8eb9SGleb Smirnoff n->af = ifa->ifa_addr->sa_family; 13713b3a8eb9SGleb Smirnoff n->ifa_flags = ifa->ifa_flags; 13723b3a8eb9SGleb Smirnoff #ifdef __KAME__ 13733b3a8eb9SGleb Smirnoff if (n->af == AF_INET6 && 13743b3a8eb9SGleb Smirnoff IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) 13753b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_addr) && 13763b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 13773b3a8eb9SGleb Smirnoff 0) { 13783b3a8eb9SGleb Smirnoff struct sockaddr_in6 *sin6; 13793b3a8eb9SGleb Smirnoff 13803b3a8eb9SGleb Smirnoff sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 13813b3a8eb9SGleb Smirnoff sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | 13823b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[3]; 13833b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[2] = 0; 13843b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[3] = 0; 13853b3a8eb9SGleb Smirnoff } 13863b3a8eb9SGleb Smirnoff #endif 13873b3a8eb9SGleb Smirnoff n->ifindex = 0; 13883b3a8eb9SGleb Smirnoff if (n->af == AF_INET) { 13893b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) 13903b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin_addr.s_addr, 13913b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 13923b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) 13933b3a8eb9SGleb Smirnoff ifa->ifa_netmask)->sin_addr.s_addr, 13943b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 13953b3a8eb9SGleb Smirnoff if (ifa->ifa_broadaddr != NULL) 13963b3a8eb9SGleb Smirnoff memcpy(&n->bcast, &((struct sockaddr_in *) 13973b3a8eb9SGleb Smirnoff ifa->ifa_broadaddr)->sin_addr.s_addr, 13983b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 13993b3a8eb9SGleb Smirnoff if (ifa->ifa_dstaddr != NULL) 14003b3a8eb9SGleb Smirnoff memcpy(&n->peer, &((struct sockaddr_in *) 14013b3a8eb9SGleb Smirnoff ifa->ifa_dstaddr)->sin_addr.s_addr, 14023b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 14033b3a8eb9SGleb Smirnoff } else if (n->af == AF_INET6) { 14043b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) 14053b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_addr.s6_addr, 14063b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 14073b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) 14083b3a8eb9SGleb Smirnoff ifa->ifa_netmask)->sin6_addr.s6_addr, 14093b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 14103b3a8eb9SGleb Smirnoff if (ifa->ifa_broadaddr != NULL) 14113b3a8eb9SGleb Smirnoff memcpy(&n->bcast, &((struct sockaddr_in6 *) 14123b3a8eb9SGleb Smirnoff ifa->ifa_broadaddr)->sin6_addr.s6_addr, 14133b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 14143b3a8eb9SGleb Smirnoff if (ifa->ifa_dstaddr != NULL) 14153b3a8eb9SGleb Smirnoff memcpy(&n->peer, &((struct sockaddr_in6 *) 14163b3a8eb9SGleb Smirnoff ifa->ifa_dstaddr)->sin6_addr.s6_addr, 14173b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 14183b3a8eb9SGleb Smirnoff n->ifindex = ((struct sockaddr_in6 *) 14193b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_scope_id; 14201d34c9daSPatrick Kelsey } else if (n->af == AF_LINK) { 14211d34c9daSPatrick Kelsey ifa_add_groups_to_map(ifa->ifa_name); 14223b3a8eb9SGleb Smirnoff } 14233b3a8eb9SGleb Smirnoff if ((n->ifname = strdup(ifa->ifa_name)) == NULL) 14243b3a8eb9SGleb Smirnoff err(1, "ifa_load: strdup"); 14253b3a8eb9SGleb Smirnoff n->next = NULL; 14263b3a8eb9SGleb Smirnoff n->tail = n; 14273b3a8eb9SGleb Smirnoff if (h == NULL) 14283b3a8eb9SGleb Smirnoff h = n; 14293b3a8eb9SGleb Smirnoff else { 14303b3a8eb9SGleb Smirnoff h->tail->next = n; 14313b3a8eb9SGleb Smirnoff h->tail = n; 14323b3a8eb9SGleb Smirnoff } 14333b3a8eb9SGleb Smirnoff } 14343b3a8eb9SGleb Smirnoff 14353b3a8eb9SGleb Smirnoff iftab = h; 14363b3a8eb9SGleb Smirnoff freeifaddrs(ifap); 14373b3a8eb9SGleb Smirnoff } 14383b3a8eb9SGleb Smirnoff 14391d34c9daSPatrick Kelsey static int 1440f870cb7fSBjoern A. Zeeb get_socket_domain(void) 1441f870cb7fSBjoern A. Zeeb { 1442f870cb7fSBjoern A. Zeeb int sdom; 1443f870cb7fSBjoern A. Zeeb 1444f870cb7fSBjoern A. Zeeb sdom = AF_UNSPEC; 1445f870cb7fSBjoern A. Zeeb #ifdef WITH_INET6 1446f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC && feature_present("inet6")) 1447f870cb7fSBjoern A. Zeeb sdom = AF_INET6; 1448f870cb7fSBjoern A. Zeeb #endif 1449f870cb7fSBjoern A. Zeeb #ifdef WITH_INET 1450f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC && feature_present("inet")) 1451f870cb7fSBjoern A. Zeeb sdom = AF_INET; 1452f870cb7fSBjoern A. Zeeb #endif 1453f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC) 1454f870cb7fSBjoern A. Zeeb sdom = AF_LINK; 1455f870cb7fSBjoern A. Zeeb 1456f870cb7fSBjoern A. Zeeb return (sdom); 1457f870cb7fSBjoern A. Zeeb } 1458f870cb7fSBjoern A. Zeeb 14591d34c9daSPatrick Kelsey int 14601d34c9daSPatrick Kelsey get_query_socket(void) 14611d34c9daSPatrick Kelsey { 14621d34c9daSPatrick Kelsey static int s = -1; 14631d34c9daSPatrick Kelsey 14641d34c9daSPatrick Kelsey if (s == -1) { 14651d34c9daSPatrick Kelsey if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) 14661d34c9daSPatrick Kelsey err(1, "socket"); 14671d34c9daSPatrick Kelsey } 14681d34c9daSPatrick Kelsey 14691d34c9daSPatrick Kelsey return (s); 14701d34c9daSPatrick Kelsey } 14711d34c9daSPatrick Kelsey 14721d34c9daSPatrick Kelsey /* 14731d34c9daSPatrick Kelsey * Returns the response len if the name is a group, otherwise returns 0. 14741d34c9daSPatrick Kelsey */ 14751d34c9daSPatrick Kelsey static int 14761d34c9daSPatrick Kelsey is_a_group(char *name) 14771d34c9daSPatrick Kelsey { 14781d34c9daSPatrick Kelsey ENTRY item; 14791d34c9daSPatrick Kelsey ENTRY *ret_item; 14801d34c9daSPatrick Kelsey 14811d34c9daSPatrick Kelsey item.key = name; 14821d34c9daSPatrick Kelsey if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) 14831d34c9daSPatrick Kelsey return (0); 14841d34c9daSPatrick Kelsey 14851d34c9daSPatrick Kelsey return (*(int *)ret_item->data); 14861d34c9daSPatrick Kelsey } 14871d34c9daSPatrick Kelsey 14883b3a8eb9SGleb Smirnoff struct node_host * 14891d34c9daSPatrick Kelsey ifa_exists(char *ifa_name) 14903b3a8eb9SGleb Smirnoff { 14913b3a8eb9SGleb Smirnoff struct node_host *n; 14923b3a8eb9SGleb Smirnoff 14933b3a8eb9SGleb Smirnoff if (iftab == NULL) 14943b3a8eb9SGleb Smirnoff ifa_load(); 14953b3a8eb9SGleb Smirnoff 14961d34c9daSPatrick Kelsey /* check whether this is a group */ 14971d34c9daSPatrick Kelsey if (is_a_group(ifa_name)) { 14983b3a8eb9SGleb Smirnoff /* fake a node_host */ 14993b3a8eb9SGleb Smirnoff if ((n = calloc(1, sizeof(*n))) == NULL) 15003b3a8eb9SGleb Smirnoff err(1, "calloc"); 15013b3a8eb9SGleb Smirnoff if ((n->ifname = strdup(ifa_name)) == NULL) 15023b3a8eb9SGleb Smirnoff err(1, "strdup"); 15033b3a8eb9SGleb Smirnoff return (n); 15043b3a8eb9SGleb Smirnoff } 15053b3a8eb9SGleb Smirnoff 15063b3a8eb9SGleb Smirnoff for (n = iftab; n; n = n->next) { 15073b3a8eb9SGleb Smirnoff if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) 15083b3a8eb9SGleb Smirnoff return (n); 15093b3a8eb9SGleb Smirnoff } 15103b3a8eb9SGleb Smirnoff 15113b3a8eb9SGleb Smirnoff return (NULL); 15123b3a8eb9SGleb Smirnoff } 15133b3a8eb9SGleb Smirnoff 15143b3a8eb9SGleb Smirnoff struct node_host * 15151d34c9daSPatrick Kelsey ifa_grouplookup(char *ifa_name, int flags) 15163b3a8eb9SGleb Smirnoff { 15173b3a8eb9SGleb Smirnoff struct ifg_req *ifg; 15183b3a8eb9SGleb Smirnoff struct ifgroupreq ifgr; 15193b3a8eb9SGleb Smirnoff int s, len; 15203b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 15213b3a8eb9SGleb Smirnoff 15221d34c9daSPatrick Kelsey s = get_query_socket(); 15231d34c9daSPatrick Kelsey len = is_a_group(ifa_name); 15241d34c9daSPatrick Kelsey if (len == 0) 15251d34c9daSPatrick Kelsey return (NULL); 15263b3a8eb9SGleb Smirnoff bzero(&ifgr, sizeof(ifgr)); 15273b3a8eb9SGleb Smirnoff strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); 15284c8fb952SKristof Provost ifgr.ifgr_len = len; 15293b3a8eb9SGleb Smirnoff if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 15303b3a8eb9SGleb Smirnoff err(1, "calloc"); 15313b3a8eb9SGleb Smirnoff if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 15323b3a8eb9SGleb Smirnoff err(1, "SIOCGIFGMEMB"); 15333b3a8eb9SGleb Smirnoff 15343b3a8eb9SGleb Smirnoff for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req); 15353b3a8eb9SGleb Smirnoff ifg++) { 15363b3a8eb9SGleb Smirnoff len -= sizeof(struct ifg_req); 1537d5b08e13SKristof Provost if ((n = ifa_lookup(ifg->ifgrq_member, flags)) == NULL) 15383b3a8eb9SGleb Smirnoff continue; 15393b3a8eb9SGleb Smirnoff if (h == NULL) 15403b3a8eb9SGleb Smirnoff h = n; 15413b3a8eb9SGleb Smirnoff else { 15423b3a8eb9SGleb Smirnoff h->tail->next = n; 15433b3a8eb9SGleb Smirnoff h->tail = n->tail; 15443b3a8eb9SGleb Smirnoff } 15453b3a8eb9SGleb Smirnoff } 15463b3a8eb9SGleb Smirnoff free(ifgr.ifgr_groups); 15473b3a8eb9SGleb Smirnoff 15483b3a8eb9SGleb Smirnoff return (h); 15493b3a8eb9SGleb Smirnoff } 15503b3a8eb9SGleb Smirnoff 15513b3a8eb9SGleb Smirnoff struct node_host * 15521d34c9daSPatrick Kelsey ifa_lookup(char *ifa_name, int flags) 15533b3a8eb9SGleb Smirnoff { 15543b3a8eb9SGleb Smirnoff struct node_host *p = NULL, *h = NULL, *n = NULL; 15553b3a8eb9SGleb Smirnoff int got4 = 0, got6 = 0; 15563b3a8eb9SGleb Smirnoff const char *last_if = NULL; 15573b3a8eb9SGleb Smirnoff 15588fd675d8SKristof Provost /* first load iftab and isgroup_map */ 15598fd675d8SKristof Provost if (iftab == NULL) 15608fd675d8SKristof Provost ifa_load(); 15618fd675d8SKristof Provost 15623b3a8eb9SGleb Smirnoff if ((h = ifa_grouplookup(ifa_name, flags)) != NULL) 15633b3a8eb9SGleb Smirnoff return (h); 15643b3a8eb9SGleb Smirnoff 15653b3a8eb9SGleb Smirnoff if (!strncmp(ifa_name, "self", IFNAMSIZ)) 15663b3a8eb9SGleb Smirnoff ifa_name = NULL; 15673b3a8eb9SGleb Smirnoff 15683b3a8eb9SGleb Smirnoff for (p = iftab; p; p = p->next) { 15693b3a8eb9SGleb Smirnoff if (ifa_skip_if(ifa_name, p)) 15703b3a8eb9SGleb Smirnoff continue; 15713b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET) 15723b3a8eb9SGleb Smirnoff continue; 15733b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_BROADCAST) && 15743b3a8eb9SGleb Smirnoff !(p->ifa_flags & IFF_BROADCAST)) 15753b3a8eb9SGleb Smirnoff continue; 15763b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_PEER) && 15773b3a8eb9SGleb Smirnoff !(p->ifa_flags & IFF_POINTOPOINT)) 15783b3a8eb9SGleb Smirnoff continue; 15793b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NETWORK) && p->ifindex > 0) 15803b3a8eb9SGleb Smirnoff continue; 15813b3a8eb9SGleb Smirnoff if (last_if == NULL || strcmp(last_if, p->ifname)) 15823b3a8eb9SGleb Smirnoff got4 = got6 = 0; 15833b3a8eb9SGleb Smirnoff last_if = p->ifname; 15843b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET && got4) 15853b3a8eb9SGleb Smirnoff continue; 158699eb0055SKristof Provost if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && 158799eb0055SKristof Provost IN6_IS_ADDR_LINKLOCAL(&p->addr.v.a.addr.v6)) 158899eb0055SKristof Provost continue; 15893b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && got6) 15903b3a8eb9SGleb Smirnoff continue; 15913b3a8eb9SGleb Smirnoff if (p->af == AF_INET) 15923b3a8eb9SGleb Smirnoff got4 = 1; 15933b3a8eb9SGleb Smirnoff else 15943b3a8eb9SGleb Smirnoff got6 = 1; 15953b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 15963b3a8eb9SGleb Smirnoff if (n == NULL) 15973b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 15983b3a8eb9SGleb Smirnoff n->af = p->af; 15993b3a8eb9SGleb Smirnoff if (flags & PFI_AFLAG_BROADCAST) 16003b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->bcast, 16013b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 16023b3a8eb9SGleb Smirnoff else if (flags & PFI_AFLAG_PEER) 16033b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->peer, 16043b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 16053b3a8eb9SGleb Smirnoff else 16063b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, 16073b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 16083b3a8eb9SGleb Smirnoff if (flags & PFI_AFLAG_NETWORK) 16093b3a8eb9SGleb Smirnoff set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); 16103b3a8eb9SGleb Smirnoff else { 16113b3a8eb9SGleb Smirnoff if (n->af == AF_INET) { 16123b3a8eb9SGleb Smirnoff if (p->ifa_flags & IFF_LOOPBACK && 16133b3a8eb9SGleb Smirnoff p->ifa_flags & IFF_LINK1) 16143b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, 16153b3a8eb9SGleb Smirnoff &p->addr.v.a.mask, 16163b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 16173b3a8eb9SGleb Smirnoff else 16183b3a8eb9SGleb Smirnoff set_ipmask(n, 32); 16193b3a8eb9SGleb Smirnoff } else 16203b3a8eb9SGleb Smirnoff set_ipmask(n, 128); 16213b3a8eb9SGleb Smirnoff } 16223b3a8eb9SGleb Smirnoff n->ifindex = p->ifindex; 16230f9e47a9SKristof Provost n->ifname = strdup(p->ifname); 16243b3a8eb9SGleb Smirnoff 16253b3a8eb9SGleb Smirnoff n->next = NULL; 16263b3a8eb9SGleb Smirnoff n->tail = n; 16273b3a8eb9SGleb Smirnoff if (h == NULL) 16283b3a8eb9SGleb Smirnoff h = n; 16293b3a8eb9SGleb Smirnoff else { 16303b3a8eb9SGleb Smirnoff h->tail->next = n; 16313b3a8eb9SGleb Smirnoff h->tail = n; 16323b3a8eb9SGleb Smirnoff } 16333b3a8eb9SGleb Smirnoff } 16343b3a8eb9SGleb Smirnoff return (h); 16353b3a8eb9SGleb Smirnoff } 16363b3a8eb9SGleb Smirnoff 16373b3a8eb9SGleb Smirnoff int 16383b3a8eb9SGleb Smirnoff ifa_skip_if(const char *filter, struct node_host *p) 16393b3a8eb9SGleb Smirnoff { 16403b3a8eb9SGleb Smirnoff int n; 16413b3a8eb9SGleb Smirnoff 16423b3a8eb9SGleb Smirnoff if (p->af != AF_INET && p->af != AF_INET6) 16433b3a8eb9SGleb Smirnoff return (1); 16443b3a8eb9SGleb Smirnoff if (filter == NULL || !*filter) 16453b3a8eb9SGleb Smirnoff return (0); 16463b3a8eb9SGleb Smirnoff if (!strcmp(p->ifname, filter)) 16473b3a8eb9SGleb Smirnoff return (0); /* exact match */ 16483b3a8eb9SGleb Smirnoff n = strlen(filter); 16493b3a8eb9SGleb Smirnoff if (n < 1 || n >= IFNAMSIZ) 16503b3a8eb9SGleb Smirnoff return (1); /* sanity check */ 16513b3a8eb9SGleb Smirnoff if (filter[n-1] >= '0' && filter[n-1] <= '9') 16523b3a8eb9SGleb Smirnoff return (1); /* only do exact match in that case */ 16533b3a8eb9SGleb Smirnoff if (strncmp(p->ifname, filter, n)) 16543b3a8eb9SGleb Smirnoff return (1); /* prefix doesn't match */ 16553b3a8eb9SGleb Smirnoff return (p->ifname[n] < '0' || p->ifname[n] > '9'); 16563b3a8eb9SGleb Smirnoff } 16573b3a8eb9SGleb Smirnoff 16583b3a8eb9SGleb Smirnoff 16593b3a8eb9SGleb Smirnoff struct node_host * 16603b3a8eb9SGleb Smirnoff host(const char *s) 16613b3a8eb9SGleb Smirnoff { 16623b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 16633b3a8eb9SGleb Smirnoff int mask, v4mask, v6mask, cont = 1; 16643b3a8eb9SGleb Smirnoff char *p, *q, *ps; 16653b3a8eb9SGleb Smirnoff 16663b3a8eb9SGleb Smirnoff if ((p = strrchr(s, '/')) != NULL) { 16673b3a8eb9SGleb Smirnoff mask = strtol(p+1, &q, 0); 16683b3a8eb9SGleb Smirnoff if (!q || *q || mask > 128 || q == (p+1)) { 16693b3a8eb9SGleb Smirnoff fprintf(stderr, "invalid netmask '%s'\n", p); 16703b3a8eb9SGleb Smirnoff return (NULL); 16713b3a8eb9SGleb Smirnoff } 16723b3a8eb9SGleb Smirnoff if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 16733b3a8eb9SGleb Smirnoff err(1, "host: malloc"); 16743b3a8eb9SGleb Smirnoff strlcpy(ps, s, strlen(s) - strlen(p) + 1); 16753b3a8eb9SGleb Smirnoff v4mask = v6mask = mask; 16763b3a8eb9SGleb Smirnoff } else { 16773b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 16783b3a8eb9SGleb Smirnoff err(1, "host: strdup"); 16793b3a8eb9SGleb Smirnoff v4mask = 32; 16803b3a8eb9SGleb Smirnoff v6mask = 128; 16813b3a8eb9SGleb Smirnoff mask = -1; 16823b3a8eb9SGleb Smirnoff } 16833b3a8eb9SGleb Smirnoff 16843b3a8eb9SGleb Smirnoff /* IPv4 address? */ 16853b3a8eb9SGleb Smirnoff if (cont && (h = host_v4(s, mask)) != NULL) 16863b3a8eb9SGleb Smirnoff cont = 0; 16873b3a8eb9SGleb Smirnoff 16883b3a8eb9SGleb Smirnoff /* IPv6 address? */ 16893b3a8eb9SGleb Smirnoff if (cont && (h = host_v6(ps, v6mask)) != NULL) 16903b3a8eb9SGleb Smirnoff cont = 0; 16913b3a8eb9SGleb Smirnoff 1692d2568b02SKristof Provost /* interface with this name exists? */ 1693d2568b02SKristof Provost /* expensive with thousands of interfaces - prioritze IPv4/6 check */ 1694d2568b02SKristof Provost if (cont && (h = host_if(ps, mask)) != NULL) 1695d2568b02SKristof Provost cont = 0; 1696d2568b02SKristof Provost 16973b3a8eb9SGleb Smirnoff /* dns lookup */ 16983b3a8eb9SGleb Smirnoff if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL) 16993b3a8eb9SGleb Smirnoff cont = 0; 17003b3a8eb9SGleb Smirnoff free(ps); 17013b3a8eb9SGleb Smirnoff 17023b3a8eb9SGleb Smirnoff if (h == NULL || cont == 1) { 17033b3a8eb9SGleb Smirnoff fprintf(stderr, "no IP address found for %s\n", s); 17043b3a8eb9SGleb Smirnoff return (NULL); 17053b3a8eb9SGleb Smirnoff } 17063b3a8eb9SGleb Smirnoff return (h); 17073b3a8eb9SGleb Smirnoff } 17083b3a8eb9SGleb Smirnoff 17093b3a8eb9SGleb Smirnoff struct node_host * 17103b3a8eb9SGleb Smirnoff host_if(const char *s, int mask) 17113b3a8eb9SGleb Smirnoff { 17123b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 17133b3a8eb9SGleb Smirnoff char *p, *ps; 17143b3a8eb9SGleb Smirnoff int flags = 0; 17153b3a8eb9SGleb Smirnoff 17163b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 17173b3a8eb9SGleb Smirnoff err(1, "host_if: strdup"); 17183b3a8eb9SGleb Smirnoff while ((p = strrchr(ps, ':')) != NULL) { 17193b3a8eb9SGleb Smirnoff if (!strcmp(p+1, "network")) 17203b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NETWORK; 17213b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "broadcast")) 17223b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_BROADCAST; 17233b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "peer")) 17243b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_PEER; 17253b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "0")) 17263b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NOALIAS; 17273b3a8eb9SGleb Smirnoff else { 17283b3a8eb9SGleb Smirnoff free(ps); 17293b3a8eb9SGleb Smirnoff return (NULL); 17303b3a8eb9SGleb Smirnoff } 17313b3a8eb9SGleb Smirnoff *p = '\0'; 17323b3a8eb9SGleb Smirnoff } 17333b3a8eb9SGleb Smirnoff if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */ 17343b3a8eb9SGleb Smirnoff fprintf(stderr, "illegal combination of interface modifiers\n"); 17353b3a8eb9SGleb Smirnoff free(ps); 17363b3a8eb9SGleb Smirnoff return (NULL); 17373b3a8eb9SGleb Smirnoff } 17383b3a8eb9SGleb Smirnoff if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) { 17393b3a8eb9SGleb Smirnoff fprintf(stderr, "network or broadcast lookup, but " 17403b3a8eb9SGleb Smirnoff "extra netmask given\n"); 17413b3a8eb9SGleb Smirnoff free(ps); 17423b3a8eb9SGleb Smirnoff return (NULL); 17433b3a8eb9SGleb Smirnoff } 17443b3a8eb9SGleb Smirnoff if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) { 17453b3a8eb9SGleb Smirnoff /* interface with this name exists */ 17463b3a8eb9SGleb Smirnoff h = ifa_lookup(ps, flags); 17473b3a8eb9SGleb Smirnoff for (n = h; n != NULL && mask > -1; n = n->next) 17483b3a8eb9SGleb Smirnoff set_ipmask(n, mask); 17493b3a8eb9SGleb Smirnoff } 17503b3a8eb9SGleb Smirnoff 17513b3a8eb9SGleb Smirnoff free(ps); 17523b3a8eb9SGleb Smirnoff return (h); 17533b3a8eb9SGleb Smirnoff } 17543b3a8eb9SGleb Smirnoff 17553b3a8eb9SGleb Smirnoff struct node_host * 17563b3a8eb9SGleb Smirnoff host_v4(const char *s, int mask) 17573b3a8eb9SGleb Smirnoff { 17583b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 17593b3a8eb9SGleb Smirnoff struct in_addr ina; 17603b3a8eb9SGleb Smirnoff int bits = 32; 17613b3a8eb9SGleb Smirnoff 17623b3a8eb9SGleb Smirnoff memset(&ina, 0, sizeof(struct in_addr)); 17633b3a8eb9SGleb Smirnoff if (strrchr(s, '/') != NULL) { 17643b3a8eb9SGleb Smirnoff if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 17653b3a8eb9SGleb Smirnoff return (NULL); 17663b3a8eb9SGleb Smirnoff } else { 17673b3a8eb9SGleb Smirnoff if (inet_pton(AF_INET, s, &ina) != 1) 17683b3a8eb9SGleb Smirnoff return (NULL); 17693b3a8eb9SGleb Smirnoff } 17703b3a8eb9SGleb Smirnoff 17713b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(struct node_host)); 17723b3a8eb9SGleb Smirnoff if (h == NULL) 17733b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 17743b3a8eb9SGleb Smirnoff h->ifname = NULL; 17753b3a8eb9SGleb Smirnoff h->af = AF_INET; 17763b3a8eb9SGleb Smirnoff h->addr.v.a.addr.addr32[0] = ina.s_addr; 17773b3a8eb9SGleb Smirnoff set_ipmask(h, bits); 17783b3a8eb9SGleb Smirnoff h->next = NULL; 17793b3a8eb9SGleb Smirnoff h->tail = h; 17803b3a8eb9SGleb Smirnoff 17813b3a8eb9SGleb Smirnoff return (h); 17823b3a8eb9SGleb Smirnoff } 17833b3a8eb9SGleb Smirnoff 17843b3a8eb9SGleb Smirnoff struct node_host * 17853b3a8eb9SGleb Smirnoff host_v6(const char *s, int mask) 17863b3a8eb9SGleb Smirnoff { 17873b3a8eb9SGleb Smirnoff struct addrinfo hints, *res; 17883b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 17893b3a8eb9SGleb Smirnoff 17903b3a8eb9SGleb Smirnoff memset(&hints, 0, sizeof(hints)); 17913b3a8eb9SGleb Smirnoff hints.ai_family = AF_INET6; 17923b3a8eb9SGleb Smirnoff hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 17933b3a8eb9SGleb Smirnoff hints.ai_flags = AI_NUMERICHOST; 17943b3a8eb9SGleb Smirnoff if (getaddrinfo(s, "0", &hints, &res) == 0) { 17953b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(struct node_host)); 17963b3a8eb9SGleb Smirnoff if (h == NULL) 17973b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 17983b3a8eb9SGleb Smirnoff h->ifname = NULL; 17993b3a8eb9SGleb Smirnoff h->af = AF_INET6; 18003b3a8eb9SGleb Smirnoff memcpy(&h->addr.v.a.addr, 18013b3a8eb9SGleb Smirnoff &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 18023b3a8eb9SGleb Smirnoff sizeof(h->addr.v.a.addr)); 18033b3a8eb9SGleb Smirnoff h->ifindex = 18043b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 18053b3a8eb9SGleb Smirnoff set_ipmask(h, mask); 18063b3a8eb9SGleb Smirnoff freeaddrinfo(res); 18073b3a8eb9SGleb Smirnoff h->next = NULL; 18083b3a8eb9SGleb Smirnoff h->tail = h; 18093b3a8eb9SGleb Smirnoff } 18103b3a8eb9SGleb Smirnoff 18113b3a8eb9SGleb Smirnoff return (h); 18123b3a8eb9SGleb Smirnoff } 18133b3a8eb9SGleb Smirnoff 18143b3a8eb9SGleb Smirnoff struct node_host * 18153b3a8eb9SGleb Smirnoff host_dns(const char *s, int v4mask, int v6mask) 18163b3a8eb9SGleb Smirnoff { 18173b3a8eb9SGleb Smirnoff struct addrinfo hints, *res0, *res; 18183b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 18193b3a8eb9SGleb Smirnoff int error, noalias = 0; 18203b3a8eb9SGleb Smirnoff int got4 = 0, got6 = 0; 18213b3a8eb9SGleb Smirnoff char *p, *ps; 18223b3a8eb9SGleb Smirnoff 18233b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 18243b3a8eb9SGleb Smirnoff err(1, "host_dns: strdup"); 18253b3a8eb9SGleb Smirnoff if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) { 18263b3a8eb9SGleb Smirnoff noalias = 1; 18273b3a8eb9SGleb Smirnoff *p = '\0'; 18283b3a8eb9SGleb Smirnoff } 18293b3a8eb9SGleb Smirnoff memset(&hints, 0, sizeof(hints)); 18303b3a8eb9SGleb Smirnoff hints.ai_family = PF_UNSPEC; 18313b3a8eb9SGleb Smirnoff hints.ai_socktype = SOCK_STREAM; /* DUMMY */ 18323b3a8eb9SGleb Smirnoff error = getaddrinfo(ps, NULL, &hints, &res0); 18333b3a8eb9SGleb Smirnoff if (error) { 18343b3a8eb9SGleb Smirnoff free(ps); 18353b3a8eb9SGleb Smirnoff return (h); 18363b3a8eb9SGleb Smirnoff } 18373b3a8eb9SGleb Smirnoff 18383b3a8eb9SGleb Smirnoff for (res = res0; res; res = res->ai_next) { 18393b3a8eb9SGleb Smirnoff if (res->ai_family != AF_INET && 18403b3a8eb9SGleb Smirnoff res->ai_family != AF_INET6) 18413b3a8eb9SGleb Smirnoff continue; 18423b3a8eb9SGleb Smirnoff if (noalias) { 18433b3a8eb9SGleb Smirnoff if (res->ai_family == AF_INET) { 18443b3a8eb9SGleb Smirnoff if (got4) 18453b3a8eb9SGleb Smirnoff continue; 18463b3a8eb9SGleb Smirnoff got4 = 1; 18473b3a8eb9SGleb Smirnoff } else { 18483b3a8eb9SGleb Smirnoff if (got6) 18493b3a8eb9SGleb Smirnoff continue; 18503b3a8eb9SGleb Smirnoff got6 = 1; 18513b3a8eb9SGleb Smirnoff } 18523b3a8eb9SGleb Smirnoff } 18533b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 18543b3a8eb9SGleb Smirnoff if (n == NULL) 18553b3a8eb9SGleb Smirnoff err(1, "host_dns: calloc"); 18563b3a8eb9SGleb Smirnoff n->ifname = NULL; 18573b3a8eb9SGleb Smirnoff n->af = res->ai_family; 18583b3a8eb9SGleb Smirnoff if (res->ai_family == AF_INET) { 18593b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, 18603b3a8eb9SGleb Smirnoff &((struct sockaddr_in *) 18613b3a8eb9SGleb Smirnoff res->ai_addr)->sin_addr.s_addr, 18623b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 18633b3a8eb9SGleb Smirnoff set_ipmask(n, v4mask); 18643b3a8eb9SGleb Smirnoff } else { 18653b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, 18663b3a8eb9SGleb Smirnoff &((struct sockaddr_in6 *) 18673b3a8eb9SGleb Smirnoff res->ai_addr)->sin6_addr.s6_addr, 18683b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 18693b3a8eb9SGleb Smirnoff n->ifindex = 18703b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *) 18713b3a8eb9SGleb Smirnoff res->ai_addr)->sin6_scope_id; 18723b3a8eb9SGleb Smirnoff set_ipmask(n, v6mask); 18733b3a8eb9SGleb Smirnoff } 18743b3a8eb9SGleb Smirnoff n->next = NULL; 18753b3a8eb9SGleb Smirnoff n->tail = n; 18763b3a8eb9SGleb Smirnoff if (h == NULL) 18773b3a8eb9SGleb Smirnoff h = n; 18783b3a8eb9SGleb Smirnoff else { 18793b3a8eb9SGleb Smirnoff h->tail->next = n; 18803b3a8eb9SGleb Smirnoff h->tail = n; 18813b3a8eb9SGleb Smirnoff } 18823b3a8eb9SGleb Smirnoff } 18833b3a8eb9SGleb Smirnoff freeaddrinfo(res0); 18843b3a8eb9SGleb Smirnoff free(ps); 18853b3a8eb9SGleb Smirnoff 18863b3a8eb9SGleb Smirnoff return (h); 18873b3a8eb9SGleb Smirnoff } 18883b3a8eb9SGleb Smirnoff 18893b3a8eb9SGleb Smirnoff /* 18903b3a8eb9SGleb Smirnoff * convert a hostname to a list of addresses and put them in the given buffer. 18913b3a8eb9SGleb Smirnoff * test: 18923b3a8eb9SGleb Smirnoff * if set to 1, only simple addresses are accepted (no netblock, no "!"). 18933b3a8eb9SGleb Smirnoff */ 18943b3a8eb9SGleb Smirnoff int 18953b3a8eb9SGleb Smirnoff append_addr(struct pfr_buffer *b, char *s, int test) 18963b3a8eb9SGleb Smirnoff { 18973b3a8eb9SGleb Smirnoff char *r; 18983b3a8eb9SGleb Smirnoff struct node_host *h, *n; 18993b3a8eb9SGleb Smirnoff int rv, not = 0; 19003b3a8eb9SGleb Smirnoff 19013b3a8eb9SGleb Smirnoff for (r = s; *r == '!'; r++) 19023b3a8eb9SGleb Smirnoff not = !not; 19033b3a8eb9SGleb Smirnoff if ((n = host(r)) == NULL) { 19043b3a8eb9SGleb Smirnoff errno = 0; 19053b3a8eb9SGleb Smirnoff return (-1); 19063b3a8eb9SGleb Smirnoff } 19073b3a8eb9SGleb Smirnoff rv = append_addr_host(b, n, test, not); 19083b3a8eb9SGleb Smirnoff do { 19093b3a8eb9SGleb Smirnoff h = n; 19103b3a8eb9SGleb Smirnoff n = n->next; 19113b3a8eb9SGleb Smirnoff free(h); 19123b3a8eb9SGleb Smirnoff } while (n != NULL); 19133b3a8eb9SGleb Smirnoff return (rv); 19143b3a8eb9SGleb Smirnoff } 19153b3a8eb9SGleb Smirnoff 19163b3a8eb9SGleb Smirnoff /* 19173b3a8eb9SGleb Smirnoff * same as previous function, but with a pre-parsed input and the ability 19183b3a8eb9SGleb Smirnoff * to "negate" the result. Does not free the node_host list. 19193b3a8eb9SGleb Smirnoff * not: 19203b3a8eb9SGleb Smirnoff * setting it to 1 is equivalent to adding "!" in front of parameter s. 19213b3a8eb9SGleb Smirnoff */ 19223b3a8eb9SGleb Smirnoff int 19233b3a8eb9SGleb Smirnoff append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not) 19243b3a8eb9SGleb Smirnoff { 19253b3a8eb9SGleb Smirnoff int bits; 19263b3a8eb9SGleb Smirnoff struct pfr_addr addr; 19273b3a8eb9SGleb Smirnoff 19283b3a8eb9SGleb Smirnoff do { 19293b3a8eb9SGleb Smirnoff bzero(&addr, sizeof(addr)); 19303b3a8eb9SGleb Smirnoff addr.pfra_not = n->not ^ not; 19313b3a8eb9SGleb Smirnoff addr.pfra_af = n->af; 19323b3a8eb9SGleb Smirnoff addr.pfra_net = unmask(&n->addr.v.a.mask, n->af); 19333b3a8eb9SGleb Smirnoff switch (n->af) { 19343b3a8eb9SGleb Smirnoff case AF_INET: 19353b3a8eb9SGleb Smirnoff addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0]; 19363b3a8eb9SGleb Smirnoff bits = 32; 19373b3a8eb9SGleb Smirnoff break; 19383b3a8eb9SGleb Smirnoff case AF_INET6: 19393b3a8eb9SGleb Smirnoff memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6, 19403b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 19413b3a8eb9SGleb Smirnoff bits = 128; 19423b3a8eb9SGleb Smirnoff break; 19433b3a8eb9SGleb Smirnoff default: 19443b3a8eb9SGleb Smirnoff errno = EINVAL; 19453b3a8eb9SGleb Smirnoff return (-1); 19463b3a8eb9SGleb Smirnoff } 19473b3a8eb9SGleb Smirnoff if ((test && (not || addr.pfra_net != bits)) || 19483b3a8eb9SGleb Smirnoff addr.pfra_net > bits) { 19493b3a8eb9SGleb Smirnoff errno = EINVAL; 19503b3a8eb9SGleb Smirnoff return (-1); 19513b3a8eb9SGleb Smirnoff } 19523b3a8eb9SGleb Smirnoff if (pfr_buf_add(b, &addr)) 19533b3a8eb9SGleb Smirnoff return (-1); 19543b3a8eb9SGleb Smirnoff } while ((n = n->next) != NULL); 19553b3a8eb9SGleb Smirnoff 19563b3a8eb9SGleb Smirnoff return (0); 19573b3a8eb9SGleb Smirnoff } 19583b3a8eb9SGleb Smirnoff 19593b3a8eb9SGleb Smirnoff int 19603b3a8eb9SGleb Smirnoff pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor) 19613b3a8eb9SGleb Smirnoff { 19623b3a8eb9SGleb Smirnoff struct pfioc_trans_e trans; 19633b3a8eb9SGleb Smirnoff 19643b3a8eb9SGleb Smirnoff bzero(&trans, sizeof(trans)); 19653b3a8eb9SGleb Smirnoff trans.rs_num = rs_num; 19663b3a8eb9SGleb Smirnoff if (strlcpy(trans.anchor, anchor, 19673b3a8eb9SGleb Smirnoff sizeof(trans.anchor)) >= sizeof(trans.anchor)) 19683b3a8eb9SGleb Smirnoff errx(1, "pfctl_add_trans: strlcpy"); 19693b3a8eb9SGleb Smirnoff 19703b3a8eb9SGleb Smirnoff return pfr_buf_add(buf, &trans); 19713b3a8eb9SGleb Smirnoff } 19723b3a8eb9SGleb Smirnoff 19733b3a8eb9SGleb Smirnoff u_int32_t 19743b3a8eb9SGleb Smirnoff pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor) 19753b3a8eb9SGleb Smirnoff { 19763b3a8eb9SGleb Smirnoff struct pfioc_trans_e *p; 19773b3a8eb9SGleb Smirnoff 19783b3a8eb9SGleb Smirnoff PFRB_FOREACH(p, buf) 19793b3a8eb9SGleb Smirnoff if (rs_num == p->rs_num && !strcmp(anchor, p->anchor)) 19803b3a8eb9SGleb Smirnoff return (p->ticket); 19813b3a8eb9SGleb Smirnoff errx(1, "pfctl_get_ticket: assertion failed"); 19823b3a8eb9SGleb Smirnoff } 19833b3a8eb9SGleb Smirnoff 19843b3a8eb9SGleb Smirnoff int 19853b3a8eb9SGleb Smirnoff pfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from) 19863b3a8eb9SGleb Smirnoff { 19873b3a8eb9SGleb Smirnoff struct pfioc_trans trans; 19883b3a8eb9SGleb Smirnoff 19893b3a8eb9SGleb Smirnoff bzero(&trans, sizeof(trans)); 19903b3a8eb9SGleb Smirnoff trans.size = buf->pfrb_size - from; 19913b3a8eb9SGleb Smirnoff trans.esize = sizeof(struct pfioc_trans_e); 19923b3a8eb9SGleb Smirnoff trans.array = ((struct pfioc_trans_e *)buf->pfrb_caddr) + from; 19933b3a8eb9SGleb Smirnoff return ioctl(dev, cmd, &trans); 19943b3a8eb9SGleb Smirnoff } 1995