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 531d34c9daSPatrick Kelsey #include <search.h> 543b3a8eb9SGleb Smirnoff #include <stdio.h> 553b3a8eb9SGleb Smirnoff #include <stdlib.h> 563b3a8eb9SGleb Smirnoff #include <string.h> 573b3a8eb9SGleb Smirnoff #include <ctype.h> 583b3a8eb9SGleb Smirnoff #include <netdb.h> 593b3a8eb9SGleb Smirnoff #include <stdarg.h> 603b3a8eb9SGleb Smirnoff #include <errno.h> 613b3a8eb9SGleb Smirnoff #include <err.h> 623b3a8eb9SGleb Smirnoff #include <ifaddrs.h> 633b3a8eb9SGleb Smirnoff #include <unistd.h> 643b3a8eb9SGleb Smirnoff 653b3a8eb9SGleb Smirnoff #include "pfctl_parser.h" 663b3a8eb9SGleb Smirnoff #include "pfctl.h" 673b3a8eb9SGleb Smirnoff 683b3a8eb9SGleb Smirnoff void print_op (u_int8_t, const char *, const char *); 693b3a8eb9SGleb Smirnoff void print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int); 703b3a8eb9SGleb Smirnoff void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned); 713b3a8eb9SGleb Smirnoff void print_flags (u_int8_t); 723b3a8eb9SGleb Smirnoff void print_fromto(struct pf_rule_addr *, pf_osfp_t, 733b3a8eb9SGleb Smirnoff struct pf_rule_addr *, u_int8_t, u_int8_t, int, int); 743b3a8eb9SGleb Smirnoff int ifa_skip_if(const char *filter, struct node_host *p); 753b3a8eb9SGleb Smirnoff 763b3a8eb9SGleb Smirnoff struct node_host *host_if(const char *, int); 773b3a8eb9SGleb Smirnoff struct node_host *host_v4(const char *, int); 783b3a8eb9SGleb Smirnoff struct node_host *host_v6(const char *, int); 793b3a8eb9SGleb Smirnoff struct node_host *host_dns(const char *, int, int); 803b3a8eb9SGleb Smirnoff 8172a3cf0fSKristof Provost const char * const tcpflags = "FSRPAUEW"; 823b3a8eb9SGleb Smirnoff 833b3a8eb9SGleb Smirnoff static const struct icmptypeent icmp_type[] = { 843b3a8eb9SGleb Smirnoff { "echoreq", ICMP_ECHO }, 853b3a8eb9SGleb Smirnoff { "echorep", ICMP_ECHOREPLY }, 863b3a8eb9SGleb Smirnoff { "unreach", ICMP_UNREACH }, 873b3a8eb9SGleb Smirnoff { "squench", ICMP_SOURCEQUENCH }, 883b3a8eb9SGleb Smirnoff { "redir", ICMP_REDIRECT }, 893b3a8eb9SGleb Smirnoff { "althost", ICMP_ALTHOSTADDR }, 903b3a8eb9SGleb Smirnoff { "routeradv", ICMP_ROUTERADVERT }, 913b3a8eb9SGleb Smirnoff { "routersol", ICMP_ROUTERSOLICIT }, 923b3a8eb9SGleb Smirnoff { "timex", ICMP_TIMXCEED }, 933b3a8eb9SGleb Smirnoff { "paramprob", ICMP_PARAMPROB }, 943b3a8eb9SGleb Smirnoff { "timereq", ICMP_TSTAMP }, 953b3a8eb9SGleb Smirnoff { "timerep", ICMP_TSTAMPREPLY }, 963b3a8eb9SGleb Smirnoff { "inforeq", ICMP_IREQ }, 973b3a8eb9SGleb Smirnoff { "inforep", ICMP_IREQREPLY }, 983b3a8eb9SGleb Smirnoff { "maskreq", ICMP_MASKREQ }, 993b3a8eb9SGleb Smirnoff { "maskrep", ICMP_MASKREPLY }, 1003b3a8eb9SGleb Smirnoff { "trace", ICMP_TRACEROUTE }, 1013b3a8eb9SGleb Smirnoff { "dataconv", ICMP_DATACONVERR }, 1023b3a8eb9SGleb Smirnoff { "mobredir", ICMP_MOBILE_REDIRECT }, 1033b3a8eb9SGleb Smirnoff { "ipv6-where", ICMP_IPV6_WHEREAREYOU }, 1043b3a8eb9SGleb Smirnoff { "ipv6-here", ICMP_IPV6_IAMHERE }, 1053b3a8eb9SGleb Smirnoff { "mobregreq", ICMP_MOBILE_REGREQUEST }, 1063b3a8eb9SGleb Smirnoff { "mobregrep", ICMP_MOBILE_REGREPLY }, 1073b3a8eb9SGleb Smirnoff { "skip", ICMP_SKIP }, 1083b3a8eb9SGleb Smirnoff { "photuris", ICMP_PHOTURIS } 1093b3a8eb9SGleb Smirnoff }; 1103b3a8eb9SGleb Smirnoff 1113b3a8eb9SGleb Smirnoff static const struct icmptypeent icmp6_type[] = { 1123b3a8eb9SGleb Smirnoff { "unreach", ICMP6_DST_UNREACH }, 1133b3a8eb9SGleb Smirnoff { "toobig", ICMP6_PACKET_TOO_BIG }, 1143b3a8eb9SGleb Smirnoff { "timex", ICMP6_TIME_EXCEEDED }, 1153b3a8eb9SGleb Smirnoff { "paramprob", ICMP6_PARAM_PROB }, 1163b3a8eb9SGleb Smirnoff { "echoreq", ICMP6_ECHO_REQUEST }, 1173b3a8eb9SGleb Smirnoff { "echorep", ICMP6_ECHO_REPLY }, 1183b3a8eb9SGleb Smirnoff { "groupqry", ICMP6_MEMBERSHIP_QUERY }, 1193b3a8eb9SGleb Smirnoff { "listqry", MLD_LISTENER_QUERY }, 1203b3a8eb9SGleb Smirnoff { "grouprep", ICMP6_MEMBERSHIP_REPORT }, 1213b3a8eb9SGleb Smirnoff { "listenrep", MLD_LISTENER_REPORT }, 1223b3a8eb9SGleb Smirnoff { "groupterm", ICMP6_MEMBERSHIP_REDUCTION }, 1233b3a8eb9SGleb Smirnoff { "listendone", MLD_LISTENER_DONE }, 1243b3a8eb9SGleb Smirnoff { "routersol", ND_ROUTER_SOLICIT }, 1253b3a8eb9SGleb Smirnoff { "routeradv", ND_ROUTER_ADVERT }, 1263b3a8eb9SGleb Smirnoff { "neighbrsol", ND_NEIGHBOR_SOLICIT }, 1273b3a8eb9SGleb Smirnoff { "neighbradv", ND_NEIGHBOR_ADVERT }, 1283b3a8eb9SGleb Smirnoff { "redir", ND_REDIRECT }, 1293b3a8eb9SGleb Smirnoff { "routrrenum", ICMP6_ROUTER_RENUMBERING }, 1303b3a8eb9SGleb Smirnoff { "wrureq", ICMP6_WRUREQUEST }, 1313b3a8eb9SGleb Smirnoff { "wrurep", ICMP6_WRUREPLY }, 1323b3a8eb9SGleb Smirnoff { "fqdnreq", ICMP6_FQDN_QUERY }, 1333b3a8eb9SGleb Smirnoff { "fqdnrep", ICMP6_FQDN_REPLY }, 1343b3a8eb9SGleb Smirnoff { "niqry", ICMP6_NI_QUERY }, 1353b3a8eb9SGleb Smirnoff { "nirep", ICMP6_NI_REPLY }, 1363b3a8eb9SGleb Smirnoff { "mtraceresp", MLD_MTRACE_RESP }, 1373b3a8eb9SGleb Smirnoff { "mtrace", MLD_MTRACE } 1383b3a8eb9SGleb Smirnoff }; 1393b3a8eb9SGleb Smirnoff 1403b3a8eb9SGleb Smirnoff static const struct icmpcodeent icmp_code[] = { 1413b3a8eb9SGleb Smirnoff { "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET }, 1423b3a8eb9SGleb Smirnoff { "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST }, 1433b3a8eb9SGleb Smirnoff { "proto-unr", ICMP_UNREACH, ICMP_UNREACH_PROTOCOL }, 1443b3a8eb9SGleb Smirnoff { "port-unr", ICMP_UNREACH, ICMP_UNREACH_PORT }, 1453b3a8eb9SGleb Smirnoff { "needfrag", ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG }, 1463b3a8eb9SGleb Smirnoff { "srcfail", ICMP_UNREACH, ICMP_UNREACH_SRCFAIL }, 1473b3a8eb9SGleb Smirnoff { "net-unk", ICMP_UNREACH, ICMP_UNREACH_NET_UNKNOWN }, 1483b3a8eb9SGleb Smirnoff { "host-unk", ICMP_UNREACH, ICMP_UNREACH_HOST_UNKNOWN }, 1493b3a8eb9SGleb Smirnoff { "isolate", ICMP_UNREACH, ICMP_UNREACH_ISOLATED }, 1503b3a8eb9SGleb Smirnoff { "net-prohib", ICMP_UNREACH, ICMP_UNREACH_NET_PROHIB }, 1513b3a8eb9SGleb Smirnoff { "host-prohib", ICMP_UNREACH, ICMP_UNREACH_HOST_PROHIB }, 1523b3a8eb9SGleb Smirnoff { "net-tos", ICMP_UNREACH, ICMP_UNREACH_TOSNET }, 1533b3a8eb9SGleb Smirnoff { "host-tos", ICMP_UNREACH, ICMP_UNREACH_TOSHOST }, 1543b3a8eb9SGleb Smirnoff { "filter-prohib", ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB }, 1553b3a8eb9SGleb Smirnoff { "host-preced", ICMP_UNREACH, ICMP_UNREACH_HOST_PRECEDENCE }, 1563b3a8eb9SGleb Smirnoff { "cutoff-preced", ICMP_UNREACH, ICMP_UNREACH_PRECEDENCE_CUTOFF }, 1573b3a8eb9SGleb Smirnoff { "redir-net", ICMP_REDIRECT, ICMP_REDIRECT_NET }, 1583b3a8eb9SGleb Smirnoff { "redir-host", ICMP_REDIRECT, ICMP_REDIRECT_HOST }, 1593b3a8eb9SGleb Smirnoff { "redir-tos-net", ICMP_REDIRECT, ICMP_REDIRECT_TOSNET }, 1603b3a8eb9SGleb Smirnoff { "redir-tos-host", ICMP_REDIRECT, ICMP_REDIRECT_TOSHOST }, 1613b3a8eb9SGleb Smirnoff { "normal-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL }, 1623b3a8eb9SGleb Smirnoff { "common-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON }, 1633b3a8eb9SGleb Smirnoff { "transit", ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS }, 1643b3a8eb9SGleb Smirnoff { "reassemb", ICMP_TIMXCEED, ICMP_TIMXCEED_REASS }, 1653b3a8eb9SGleb Smirnoff { "badhead", ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR }, 1663b3a8eb9SGleb Smirnoff { "optmiss", ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT }, 1673b3a8eb9SGleb Smirnoff { "badlen", ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH }, 1683b3a8eb9SGleb Smirnoff { "unknown-ind", ICMP_PHOTURIS, ICMP_PHOTURIS_UNKNOWN_INDEX }, 1693b3a8eb9SGleb Smirnoff { "auth-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_AUTH_FAILED }, 1703b3a8eb9SGleb Smirnoff { "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED } 1713b3a8eb9SGleb Smirnoff }; 1723b3a8eb9SGleb Smirnoff 1733b3a8eb9SGleb Smirnoff static const struct icmpcodeent icmp6_code[] = { 1743b3a8eb9SGleb Smirnoff { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN }, 1753b3a8eb9SGleb Smirnoff { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE }, 1763b3a8eb9SGleb Smirnoff { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR }, 1773b3a8eb9SGleb Smirnoff { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE }, 1783b3a8eb9SGleb Smirnoff { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR }, 1793b3a8eb9SGleb Smirnoff { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT }, 1803b3a8eb9SGleb Smirnoff { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT }, 1813b3a8eb9SGleb Smirnoff { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY }, 1823b3a8eb9SGleb Smirnoff { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER }, 1833b3a8eb9SGleb Smirnoff { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER }, 1843b3a8eb9SGleb Smirnoff { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK }, 1853b3a8eb9SGleb Smirnoff { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER } 1863b3a8eb9SGleb Smirnoff }; 1873b3a8eb9SGleb Smirnoff 1883b3a8eb9SGleb Smirnoff const struct pf_timeout pf_timeouts[] = { 1893b3a8eb9SGleb Smirnoff { "tcp.first", PFTM_TCP_FIRST_PACKET }, 1903b3a8eb9SGleb Smirnoff { "tcp.opening", PFTM_TCP_OPENING }, 1913b3a8eb9SGleb Smirnoff { "tcp.established", PFTM_TCP_ESTABLISHED }, 1923b3a8eb9SGleb Smirnoff { "tcp.closing", PFTM_TCP_CLOSING }, 1933b3a8eb9SGleb Smirnoff { "tcp.finwait", PFTM_TCP_FIN_WAIT }, 1943b3a8eb9SGleb Smirnoff { "tcp.closed", PFTM_TCP_CLOSED }, 1953b3a8eb9SGleb Smirnoff { "tcp.tsdiff", PFTM_TS_DIFF }, 1963b3a8eb9SGleb Smirnoff { "udp.first", PFTM_UDP_FIRST_PACKET }, 1973b3a8eb9SGleb Smirnoff { "udp.single", PFTM_UDP_SINGLE }, 1983b3a8eb9SGleb Smirnoff { "udp.multiple", PFTM_UDP_MULTIPLE }, 1993b3a8eb9SGleb Smirnoff { "icmp.first", PFTM_ICMP_FIRST_PACKET }, 2003b3a8eb9SGleb Smirnoff { "icmp.error", PFTM_ICMP_ERROR_REPLY }, 2013b3a8eb9SGleb Smirnoff { "other.first", PFTM_OTHER_FIRST_PACKET }, 2023b3a8eb9SGleb Smirnoff { "other.single", PFTM_OTHER_SINGLE }, 2033b3a8eb9SGleb Smirnoff { "other.multiple", PFTM_OTHER_MULTIPLE }, 2043b3a8eb9SGleb Smirnoff { "frag", PFTM_FRAG }, 2053b3a8eb9SGleb Smirnoff { "interval", PFTM_INTERVAL }, 2063b3a8eb9SGleb Smirnoff { "adaptive.start", PFTM_ADAPTIVE_START }, 2073b3a8eb9SGleb Smirnoff { "adaptive.end", PFTM_ADAPTIVE_END }, 2083b3a8eb9SGleb Smirnoff { "src.track", PFTM_SRC_NODE }, 2093b3a8eb9SGleb Smirnoff { NULL, 0 } 2103b3a8eb9SGleb Smirnoff }; 2113b3a8eb9SGleb Smirnoff 2121d34c9daSPatrick Kelsey static struct hsearch_data isgroup_map; 2131d34c9daSPatrick Kelsey 2141d34c9daSPatrick Kelsey static __attribute__((constructor)) void 2151d34c9daSPatrick Kelsey pfctl_parser_init(void) 2161d34c9daSPatrick Kelsey { 2171d34c9daSPatrick Kelsey /* 2181d34c9daSPatrick Kelsey * As hdestroy() will never be called on these tables, it will be 2191d34c9daSPatrick Kelsey * safe to use references into the stored data as keys. 2201d34c9daSPatrick Kelsey */ 2211d34c9daSPatrick Kelsey if (hcreate_r(0, &isgroup_map) == 0) 2221d34c9daSPatrick Kelsey err(1, "Failed to create interface group query response map"); 2231d34c9daSPatrick Kelsey } 2241d34c9daSPatrick Kelsey 2253b3a8eb9SGleb Smirnoff const struct icmptypeent * 2263b3a8eb9SGleb Smirnoff geticmptypebynumber(u_int8_t type, sa_family_t af) 2273b3a8eb9SGleb Smirnoff { 2283b3a8eb9SGleb Smirnoff unsigned int i; 2293b3a8eb9SGleb Smirnoff 2303b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 231c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_type); i++) { 2323b3a8eb9SGleb Smirnoff if (type == icmp_type[i].type) 2333b3a8eb9SGleb Smirnoff return (&icmp_type[i]); 2343b3a8eb9SGleb Smirnoff } 2353b3a8eb9SGleb Smirnoff } else { 236c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_type); i++) { 2373b3a8eb9SGleb Smirnoff if (type == icmp6_type[i].type) 2383b3a8eb9SGleb Smirnoff return (&icmp6_type[i]); 2393b3a8eb9SGleb Smirnoff } 2403b3a8eb9SGleb Smirnoff } 2413b3a8eb9SGleb Smirnoff return (NULL); 2423b3a8eb9SGleb Smirnoff } 2433b3a8eb9SGleb Smirnoff 2443b3a8eb9SGleb Smirnoff const struct icmptypeent * 2453b3a8eb9SGleb Smirnoff geticmptypebyname(char *w, sa_family_t af) 2463b3a8eb9SGleb Smirnoff { 2473b3a8eb9SGleb Smirnoff unsigned int i; 2483b3a8eb9SGleb Smirnoff 2493b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 250c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_type); i++) { 2513b3a8eb9SGleb Smirnoff if (!strcmp(w, icmp_type[i].name)) 2523b3a8eb9SGleb Smirnoff return (&icmp_type[i]); 2533b3a8eb9SGleb Smirnoff } 2543b3a8eb9SGleb Smirnoff } else { 255c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_type); i++) { 2563b3a8eb9SGleb Smirnoff if (!strcmp(w, icmp6_type[i].name)) 2573b3a8eb9SGleb Smirnoff return (&icmp6_type[i]); 2583b3a8eb9SGleb Smirnoff } 2593b3a8eb9SGleb Smirnoff } 2603b3a8eb9SGleb Smirnoff return (NULL); 2613b3a8eb9SGleb Smirnoff } 2623b3a8eb9SGleb Smirnoff 2633b3a8eb9SGleb Smirnoff const struct icmpcodeent * 2643b3a8eb9SGleb Smirnoff geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af) 2653b3a8eb9SGleb Smirnoff { 2663b3a8eb9SGleb Smirnoff unsigned int i; 2673b3a8eb9SGleb Smirnoff 2683b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 269c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_code); i++) { 2703b3a8eb9SGleb Smirnoff if (type == icmp_code[i].type && 2713b3a8eb9SGleb Smirnoff code == icmp_code[i].code) 2723b3a8eb9SGleb Smirnoff return (&icmp_code[i]); 2733b3a8eb9SGleb Smirnoff } 2743b3a8eb9SGleb Smirnoff } else { 275c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_code); i++) { 2763b3a8eb9SGleb Smirnoff if (type == icmp6_code[i].type && 2773b3a8eb9SGleb Smirnoff code == icmp6_code[i].code) 2783b3a8eb9SGleb Smirnoff return (&icmp6_code[i]); 2793b3a8eb9SGleb Smirnoff } 2803b3a8eb9SGleb Smirnoff } 2813b3a8eb9SGleb Smirnoff return (NULL); 2823b3a8eb9SGleb Smirnoff } 2833b3a8eb9SGleb Smirnoff 2843b3a8eb9SGleb Smirnoff const struct icmpcodeent * 2853b3a8eb9SGleb Smirnoff geticmpcodebyname(u_long type, char *w, sa_family_t af) 2863b3a8eb9SGleb Smirnoff { 2873b3a8eb9SGleb Smirnoff unsigned int i; 2883b3a8eb9SGleb Smirnoff 2893b3a8eb9SGleb Smirnoff if (af != AF_INET6) { 290c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp_code); i++) { 2913b3a8eb9SGleb Smirnoff if (type == icmp_code[i].type && 2923b3a8eb9SGleb Smirnoff !strcmp(w, icmp_code[i].name)) 2933b3a8eb9SGleb Smirnoff return (&icmp_code[i]); 2943b3a8eb9SGleb Smirnoff } 2953b3a8eb9SGleb Smirnoff } else { 296c52ee6c2SMarcelo Araujo for (i=0; i < nitems(icmp6_code); i++) { 2973b3a8eb9SGleb Smirnoff if (type == icmp6_code[i].type && 2983b3a8eb9SGleb Smirnoff !strcmp(w, icmp6_code[i].name)) 2993b3a8eb9SGleb Smirnoff return (&icmp6_code[i]); 3003b3a8eb9SGleb Smirnoff } 3013b3a8eb9SGleb Smirnoff } 3023b3a8eb9SGleb Smirnoff return (NULL); 3033b3a8eb9SGleb Smirnoff } 3043b3a8eb9SGleb Smirnoff 3053b3a8eb9SGleb Smirnoff void 3063b3a8eb9SGleb Smirnoff print_op(u_int8_t op, const char *a1, const char *a2) 3073b3a8eb9SGleb Smirnoff { 3083b3a8eb9SGleb Smirnoff if (op == PF_OP_IRG) 3093b3a8eb9SGleb Smirnoff printf(" %s >< %s", a1, a2); 3103b3a8eb9SGleb Smirnoff else if (op == PF_OP_XRG) 3113b3a8eb9SGleb Smirnoff printf(" %s <> %s", a1, a2); 3123b3a8eb9SGleb Smirnoff else if (op == PF_OP_EQ) 3133b3a8eb9SGleb Smirnoff printf(" = %s", a1); 3143b3a8eb9SGleb Smirnoff else if (op == PF_OP_NE) 3153b3a8eb9SGleb Smirnoff printf(" != %s", a1); 3163b3a8eb9SGleb Smirnoff else if (op == PF_OP_LT) 3173b3a8eb9SGleb Smirnoff printf(" < %s", a1); 3183b3a8eb9SGleb Smirnoff else if (op == PF_OP_LE) 3193b3a8eb9SGleb Smirnoff printf(" <= %s", a1); 3203b3a8eb9SGleb Smirnoff else if (op == PF_OP_GT) 3213b3a8eb9SGleb Smirnoff printf(" > %s", a1); 3223b3a8eb9SGleb Smirnoff else if (op == PF_OP_GE) 3233b3a8eb9SGleb Smirnoff printf(" >= %s", a1); 3243b3a8eb9SGleb Smirnoff else if (op == PF_OP_RRG) 3253b3a8eb9SGleb Smirnoff printf(" %s:%s", a1, a2); 3263b3a8eb9SGleb Smirnoff } 3273b3a8eb9SGleb Smirnoff 3283b3a8eb9SGleb Smirnoff void 3293b3a8eb9SGleb Smirnoff print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int numeric) 3303b3a8eb9SGleb Smirnoff { 3313b3a8eb9SGleb Smirnoff char a1[6], a2[6]; 3323b3a8eb9SGleb Smirnoff struct servent *s; 3333b3a8eb9SGleb Smirnoff 3343b3a8eb9SGleb Smirnoff if (!numeric) 3353b3a8eb9SGleb Smirnoff s = getservbyport(p1, proto); 3363b3a8eb9SGleb Smirnoff else 3373b3a8eb9SGleb Smirnoff s = NULL; 3383b3a8eb9SGleb Smirnoff p1 = ntohs(p1); 3393b3a8eb9SGleb Smirnoff p2 = ntohs(p2); 3403b3a8eb9SGleb Smirnoff snprintf(a1, sizeof(a1), "%u", p1); 3413b3a8eb9SGleb Smirnoff snprintf(a2, sizeof(a2), "%u", p2); 3423b3a8eb9SGleb Smirnoff printf(" port"); 3433b3a8eb9SGleb Smirnoff if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE)) 3443b3a8eb9SGleb Smirnoff print_op(op, s->s_name, a2); 3453b3a8eb9SGleb Smirnoff else 3463b3a8eb9SGleb Smirnoff print_op(op, a1, a2); 3473b3a8eb9SGleb Smirnoff } 3483b3a8eb9SGleb Smirnoff 3493b3a8eb9SGleb Smirnoff void 3503b3a8eb9SGleb Smirnoff print_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax) 3513b3a8eb9SGleb Smirnoff { 3523b3a8eb9SGleb Smirnoff char a1[11], a2[11]; 3533b3a8eb9SGleb Smirnoff 3543b3a8eb9SGleb Smirnoff snprintf(a1, sizeof(a1), "%u", u1); 3553b3a8eb9SGleb Smirnoff snprintf(a2, sizeof(a2), "%u", u2); 3563b3a8eb9SGleb Smirnoff printf(" %s", t); 3573b3a8eb9SGleb Smirnoff if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE)) 3583b3a8eb9SGleb Smirnoff print_op(op, "unknown", a2); 3593b3a8eb9SGleb Smirnoff else 3603b3a8eb9SGleb Smirnoff print_op(op, a1, a2); 3613b3a8eb9SGleb Smirnoff } 3623b3a8eb9SGleb Smirnoff 3633b3a8eb9SGleb Smirnoff void 3643b3a8eb9SGleb Smirnoff print_flags(u_int8_t f) 3653b3a8eb9SGleb Smirnoff { 3663b3a8eb9SGleb Smirnoff int i; 3673b3a8eb9SGleb Smirnoff 3683b3a8eb9SGleb Smirnoff for (i = 0; tcpflags[i]; ++i) 3693b3a8eb9SGleb Smirnoff if (f & (1 << i)) 3703b3a8eb9SGleb Smirnoff printf("%c", tcpflags[i]); 3713b3a8eb9SGleb Smirnoff } 3723b3a8eb9SGleb Smirnoff 3733b3a8eb9SGleb Smirnoff void 3743b3a8eb9SGleb Smirnoff print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, 3753b3a8eb9SGleb Smirnoff sa_family_t af, u_int8_t proto, int verbose, int numeric) 3763b3a8eb9SGleb Smirnoff { 3773b3a8eb9SGleb Smirnoff char buf[PF_OSFP_LEN*3]; 3783b3a8eb9SGleb Smirnoff if (src->addr.type == PF_ADDR_ADDRMASK && 3793b3a8eb9SGleb Smirnoff dst->addr.type == PF_ADDR_ADDRMASK && 3803b3a8eb9SGleb Smirnoff PF_AZERO(&src->addr.v.a.addr, AF_INET6) && 3813b3a8eb9SGleb Smirnoff PF_AZERO(&src->addr.v.a.mask, AF_INET6) && 3823b3a8eb9SGleb Smirnoff PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && 3833b3a8eb9SGleb Smirnoff PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && 3843b3a8eb9SGleb Smirnoff !src->neg && !dst->neg && 3853b3a8eb9SGleb Smirnoff !src->port_op && !dst->port_op && 3863b3a8eb9SGleb Smirnoff osfp == PF_OSFP_ANY) 3873b3a8eb9SGleb Smirnoff printf(" all"); 3883b3a8eb9SGleb Smirnoff else { 3893b3a8eb9SGleb Smirnoff printf(" from "); 3903b3a8eb9SGleb Smirnoff if (src->neg) 3913b3a8eb9SGleb Smirnoff printf("! "); 3923b3a8eb9SGleb Smirnoff print_addr(&src->addr, af, verbose); 3933b3a8eb9SGleb Smirnoff if (src->port_op) 3943b3a8eb9SGleb Smirnoff print_port(src->port_op, src->port[0], 3953b3a8eb9SGleb Smirnoff src->port[1], 3963b3a8eb9SGleb Smirnoff proto == IPPROTO_TCP ? "tcp" : "udp", 3973b3a8eb9SGleb Smirnoff numeric); 3983b3a8eb9SGleb Smirnoff if (osfp != PF_OSFP_ANY) 3993b3a8eb9SGleb Smirnoff printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf, 4003b3a8eb9SGleb Smirnoff sizeof(buf))); 4013b3a8eb9SGleb Smirnoff 4023b3a8eb9SGleb Smirnoff printf(" to "); 4033b3a8eb9SGleb Smirnoff if (dst->neg) 4043b3a8eb9SGleb Smirnoff printf("! "); 4053b3a8eb9SGleb Smirnoff print_addr(&dst->addr, af, verbose); 4063b3a8eb9SGleb Smirnoff if (dst->port_op) 4073b3a8eb9SGleb Smirnoff print_port(dst->port_op, dst->port[0], 4083b3a8eb9SGleb Smirnoff dst->port[1], 4093b3a8eb9SGleb Smirnoff proto == IPPROTO_TCP ? "tcp" : "udp", 4103b3a8eb9SGleb Smirnoff numeric); 4113b3a8eb9SGleb Smirnoff } 4123b3a8eb9SGleb Smirnoff } 4133b3a8eb9SGleb Smirnoff 4143b3a8eb9SGleb Smirnoff void 4153b3a8eb9SGleb Smirnoff print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2, 4163b3a8eb9SGleb Smirnoff sa_family_t af, int id) 4173b3a8eb9SGleb Smirnoff { 4183b3a8eb9SGleb Smirnoff struct pf_pooladdr *pooladdr; 4193b3a8eb9SGleb Smirnoff 4203b3a8eb9SGleb Smirnoff if ((TAILQ_FIRST(&pool->list) != NULL) && 4213b3a8eb9SGleb Smirnoff TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4223b3a8eb9SGleb Smirnoff printf("{ "); 4233b3a8eb9SGleb Smirnoff TAILQ_FOREACH(pooladdr, &pool->list, entries){ 4243b3a8eb9SGleb Smirnoff switch (id) { 4253b3a8eb9SGleb Smirnoff case PF_NAT: 4263b3a8eb9SGleb Smirnoff case PF_RDR: 4273b3a8eb9SGleb Smirnoff case PF_BINAT: 4283b3a8eb9SGleb Smirnoff print_addr(&pooladdr->addr, af, 0); 4293b3a8eb9SGleb Smirnoff break; 4303b3a8eb9SGleb Smirnoff case PF_PASS: 4313b3a8eb9SGleb Smirnoff if (PF_AZERO(&pooladdr->addr.v.a.addr, af)) 4323b3a8eb9SGleb Smirnoff printf("%s", pooladdr->ifname); 4333b3a8eb9SGleb Smirnoff else { 4343b3a8eb9SGleb Smirnoff printf("(%s ", pooladdr->ifname); 4353b3a8eb9SGleb Smirnoff print_addr(&pooladdr->addr, af, 0); 4363b3a8eb9SGleb Smirnoff printf(")"); 4373b3a8eb9SGleb Smirnoff } 4383b3a8eb9SGleb Smirnoff break; 4393b3a8eb9SGleb Smirnoff default: 4403b3a8eb9SGleb Smirnoff break; 4413b3a8eb9SGleb Smirnoff } 4423b3a8eb9SGleb Smirnoff if (TAILQ_NEXT(pooladdr, entries) != NULL) 4433b3a8eb9SGleb Smirnoff printf(", "); 4443b3a8eb9SGleb Smirnoff else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4453b3a8eb9SGleb Smirnoff printf(" }"); 4463b3a8eb9SGleb Smirnoff } 4473b3a8eb9SGleb Smirnoff switch (id) { 4483b3a8eb9SGleb Smirnoff case PF_NAT: 4493b3a8eb9SGleb Smirnoff if ((p1 != PF_NAT_PROXY_PORT_LOW || 4503b3a8eb9SGleb Smirnoff p2 != PF_NAT_PROXY_PORT_HIGH) && (p1 != 0 || p2 != 0)) { 4513b3a8eb9SGleb Smirnoff if (p1 == p2) 4523b3a8eb9SGleb Smirnoff printf(" port %u", p1); 4533b3a8eb9SGleb Smirnoff else 4543b3a8eb9SGleb Smirnoff printf(" port %u:%u", p1, p2); 4553b3a8eb9SGleb Smirnoff } 4563b3a8eb9SGleb Smirnoff break; 4573b3a8eb9SGleb Smirnoff case PF_RDR: 4583b3a8eb9SGleb Smirnoff if (p1) { 4593b3a8eb9SGleb Smirnoff printf(" port %u", p1); 4603b3a8eb9SGleb Smirnoff if (p2 && (p2 != p1)) 4613b3a8eb9SGleb Smirnoff printf(":%u", p2); 4623b3a8eb9SGleb Smirnoff } 4633b3a8eb9SGleb Smirnoff break; 4643b3a8eb9SGleb Smirnoff default: 4653b3a8eb9SGleb Smirnoff break; 4663b3a8eb9SGleb Smirnoff } 4673b3a8eb9SGleb Smirnoff switch (pool->opts & PF_POOL_TYPEMASK) { 4683b3a8eb9SGleb Smirnoff case PF_POOL_NONE: 4693b3a8eb9SGleb Smirnoff break; 4703b3a8eb9SGleb Smirnoff case PF_POOL_BITMASK: 4713b3a8eb9SGleb Smirnoff printf(" bitmask"); 4723b3a8eb9SGleb Smirnoff break; 4733b3a8eb9SGleb Smirnoff case PF_POOL_RANDOM: 4743b3a8eb9SGleb Smirnoff printf(" random"); 4753b3a8eb9SGleb Smirnoff break; 4763b3a8eb9SGleb Smirnoff case PF_POOL_SRCHASH: 4773b3a8eb9SGleb Smirnoff printf(" source-hash 0x%08x%08x%08x%08x", 4783b3a8eb9SGleb Smirnoff pool->key.key32[0], pool->key.key32[1], 4793b3a8eb9SGleb Smirnoff pool->key.key32[2], pool->key.key32[3]); 4803b3a8eb9SGleb Smirnoff break; 4813b3a8eb9SGleb Smirnoff case PF_POOL_ROUNDROBIN: 4823b3a8eb9SGleb Smirnoff printf(" round-robin"); 4833b3a8eb9SGleb Smirnoff break; 4843b3a8eb9SGleb Smirnoff } 4853b3a8eb9SGleb Smirnoff if (pool->opts & PF_POOL_STICKYADDR) 4863b3a8eb9SGleb Smirnoff printf(" sticky-address"); 4873b3a8eb9SGleb Smirnoff if (id == PF_NAT && p1 == 0 && p2 == 0) 4883b3a8eb9SGleb Smirnoff printf(" static-port"); 4893b3a8eb9SGleb Smirnoff } 4903b3a8eb9SGleb Smirnoff 49172a3cf0fSKristof Provost const char * const pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 49272a3cf0fSKristof Provost const char * const pf_lcounters[LCNT_MAX+1] = LCNT_NAMES; 49372a3cf0fSKristof Provost const char * const pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 49472a3cf0fSKristof Provost const char * const pf_scounters[FCNT_MAX+1] = FCNT_NAMES; 4953b3a8eb9SGleb Smirnoff 4963b3a8eb9SGleb Smirnoff void 4973b3a8eb9SGleb Smirnoff print_status(struct pf_status *s, int opts) 4983b3a8eb9SGleb Smirnoff { 4993b3a8eb9SGleb Smirnoff char statline[80], *running; 5003b3a8eb9SGleb Smirnoff time_t runtime; 5013b3a8eb9SGleb Smirnoff int i; 5023b3a8eb9SGleb Smirnoff char buf[PF_MD5_DIGEST_LENGTH * 2 + 1]; 5033b3a8eb9SGleb Smirnoff static const char hex[] = "0123456789abcdef"; 5043b3a8eb9SGleb Smirnoff 5053b3a8eb9SGleb Smirnoff runtime = time(NULL) - s->since; 5063b3a8eb9SGleb Smirnoff running = s->running ? "Enabled" : "Disabled"; 5073b3a8eb9SGleb Smirnoff 5083b3a8eb9SGleb Smirnoff if (s->since) { 5093b3a8eb9SGleb Smirnoff unsigned int sec, min, hrs, day = runtime; 5103b3a8eb9SGleb Smirnoff 5113b3a8eb9SGleb Smirnoff sec = day % 60; 5123b3a8eb9SGleb Smirnoff day /= 60; 5133b3a8eb9SGleb Smirnoff min = day % 60; 5143b3a8eb9SGleb Smirnoff day /= 60; 5153b3a8eb9SGleb Smirnoff hrs = day % 24; 5163b3a8eb9SGleb Smirnoff day /= 24; 5173b3a8eb9SGleb Smirnoff snprintf(statline, sizeof(statline), 5183b3a8eb9SGleb Smirnoff "Status: %s for %u days %.2u:%.2u:%.2u", 5193b3a8eb9SGleb Smirnoff running, day, hrs, min, sec); 5203b3a8eb9SGleb Smirnoff } else 5213b3a8eb9SGleb Smirnoff snprintf(statline, sizeof(statline), "Status: %s", running); 5223b3a8eb9SGleb Smirnoff printf("%-44s", statline); 5233b3a8eb9SGleb Smirnoff switch (s->debug) { 5243b3a8eb9SGleb Smirnoff case PF_DEBUG_NONE: 5253b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: None"); 5263b3a8eb9SGleb Smirnoff break; 5273b3a8eb9SGleb Smirnoff case PF_DEBUG_URGENT: 5283b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Urgent"); 5293b3a8eb9SGleb Smirnoff break; 5303b3a8eb9SGleb Smirnoff case PF_DEBUG_MISC: 5313b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Misc"); 5323b3a8eb9SGleb Smirnoff break; 5333b3a8eb9SGleb Smirnoff case PF_DEBUG_NOISY: 5343b3a8eb9SGleb Smirnoff printf("%15s\n\n", "Debug: Loud"); 5353b3a8eb9SGleb Smirnoff break; 5363b3a8eb9SGleb Smirnoff } 5373b3a8eb9SGleb Smirnoff 5383b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 5393b3a8eb9SGleb Smirnoff printf("Hostid: 0x%08x\n", ntohl(s->hostid)); 5403b3a8eb9SGleb Smirnoff 5413b3a8eb9SGleb Smirnoff for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) { 5423b3a8eb9SGleb Smirnoff buf[i + i] = hex[s->pf_chksum[i] >> 4]; 5433b3a8eb9SGleb Smirnoff buf[i + i + 1] = hex[s->pf_chksum[i] & 0x0f]; 5443b3a8eb9SGleb Smirnoff } 5453b3a8eb9SGleb Smirnoff buf[i + i] = '\0'; 5463b3a8eb9SGleb Smirnoff printf("Checksum: 0x%s\n\n", buf); 5473b3a8eb9SGleb Smirnoff } 5483b3a8eb9SGleb Smirnoff 5493b3a8eb9SGleb Smirnoff if (s->ifname[0] != 0) { 5503b3a8eb9SGleb Smirnoff printf("Interface Stats for %-16s %5s %16s\n", 5513b3a8eb9SGleb Smirnoff s->ifname, "IPv4", "IPv6"); 5523b3a8eb9SGleb Smirnoff printf(" %-25s %14llu %16llu\n", "Bytes In", 5533b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[0][0], 5543b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[1][0]); 5553b3a8eb9SGleb Smirnoff printf(" %-25s %14llu %16llu\n", "Bytes Out", 5563b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[0][1], 5573b3a8eb9SGleb Smirnoff (unsigned long long)s->bcounters[1][1]); 5583b3a8eb9SGleb Smirnoff printf(" Packets In\n"); 5593b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Passed", 5603b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][0][PF_PASS], 5613b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][0][PF_PASS]); 5623b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Blocked", 5633b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][0][PF_DROP], 5643b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][0][PF_DROP]); 5653b3a8eb9SGleb Smirnoff printf(" Packets Out\n"); 5663b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n", "Passed", 5673b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][1][PF_PASS], 5683b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][1][PF_PASS]); 5693b3a8eb9SGleb Smirnoff printf(" %-23s %14llu %16llu\n\n", "Blocked", 5703b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[0][1][PF_DROP], 5713b3a8eb9SGleb Smirnoff (unsigned long long)s->pcounters[1][1][PF_DROP]); 5723b3a8eb9SGleb Smirnoff } 5733b3a8eb9SGleb Smirnoff printf("%-27s %14s %16s\n", "State Table", "Total", "Rate"); 5743b3a8eb9SGleb Smirnoff printf(" %-25s %14u %14s\n", "current entries", s->states, ""); 5753b3a8eb9SGleb Smirnoff for (i = 0; i < FCNT_MAX; i++) { 5763b3a8eb9SGleb Smirnoff printf(" %-25s %14llu ", pf_fcounters[i], 5773b3a8eb9SGleb Smirnoff (unsigned long long)s->fcounters[i]); 5783b3a8eb9SGleb Smirnoff if (runtime > 0) 5793b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 5803b3a8eb9SGleb Smirnoff (double)s->fcounters[i] / (double)runtime); 5813b3a8eb9SGleb Smirnoff else 5823b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 5833b3a8eb9SGleb Smirnoff } 5843b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 5853b3a8eb9SGleb Smirnoff printf("Source Tracking Table\n"); 5863b3a8eb9SGleb Smirnoff printf(" %-25s %14u %14s\n", "current entries", 5873b3a8eb9SGleb Smirnoff s->src_nodes, ""); 5883b3a8eb9SGleb Smirnoff for (i = 0; i < SCNT_MAX; i++) { 5893b3a8eb9SGleb Smirnoff printf(" %-25s %14lld ", pf_scounters[i], 5903b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 5913b3a8eb9SGleb Smirnoff (long long)s->scounters[i]); 5923b3a8eb9SGleb Smirnoff #else 5933b3a8eb9SGleb Smirnoff s->scounters[i]); 5943b3a8eb9SGleb Smirnoff #endif 5953b3a8eb9SGleb Smirnoff if (runtime > 0) 5963b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 5973b3a8eb9SGleb Smirnoff (double)s->scounters[i] / (double)runtime); 5983b3a8eb9SGleb Smirnoff else 5993b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6003b3a8eb9SGleb Smirnoff } 6013b3a8eb9SGleb Smirnoff } 6023b3a8eb9SGleb Smirnoff printf("Counters\n"); 6033b3a8eb9SGleb Smirnoff for (i = 0; i < PFRES_MAX; i++) { 6043b3a8eb9SGleb Smirnoff printf(" %-25s %14llu ", pf_reasons[i], 6053b3a8eb9SGleb Smirnoff (unsigned long long)s->counters[i]); 6063b3a8eb9SGleb Smirnoff if (runtime > 0) 6073b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 6083b3a8eb9SGleb Smirnoff (double)s->counters[i] / (double)runtime); 6093b3a8eb9SGleb Smirnoff else 6103b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6113b3a8eb9SGleb Smirnoff } 6123b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 6133b3a8eb9SGleb Smirnoff printf("Limit Counters\n"); 6143b3a8eb9SGleb Smirnoff for (i = 0; i < LCNT_MAX; i++) { 6153b3a8eb9SGleb Smirnoff printf(" %-25s %14lld ", pf_lcounters[i], 6163b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 6173b3a8eb9SGleb Smirnoff (unsigned long long)s->lcounters[i]); 6183b3a8eb9SGleb Smirnoff #else 6193b3a8eb9SGleb Smirnoff s->lcounters[i]); 6203b3a8eb9SGleb Smirnoff #endif 6213b3a8eb9SGleb Smirnoff if (runtime > 0) 6223b3a8eb9SGleb Smirnoff printf("%14.1f/s\n", 6233b3a8eb9SGleb Smirnoff (double)s->lcounters[i] / (double)runtime); 6243b3a8eb9SGleb Smirnoff else 6253b3a8eb9SGleb Smirnoff printf("%14s\n", ""); 6263b3a8eb9SGleb Smirnoff } 6273b3a8eb9SGleb Smirnoff } 6283b3a8eb9SGleb Smirnoff } 6293b3a8eb9SGleb Smirnoff 6303b3a8eb9SGleb Smirnoff void 631fa1d4439SKristof Provost print_running(struct pf_status *status) 632fa1d4439SKristof Provost { 633fa1d4439SKristof Provost printf("%s\n", status->running ? "Enabled" : "Disabled"); 634fa1d4439SKristof Provost } 635fa1d4439SKristof Provost 636fa1d4439SKristof Provost void 6373b3a8eb9SGleb Smirnoff print_src_node(struct pf_src_node *sn, int opts) 6383b3a8eb9SGleb Smirnoff { 6393b3a8eb9SGleb Smirnoff struct pf_addr_wrap aw; 6403b3a8eb9SGleb Smirnoff int min, sec; 6413b3a8eb9SGleb Smirnoff 6423b3a8eb9SGleb Smirnoff memset(&aw, 0, sizeof(aw)); 6433b3a8eb9SGleb Smirnoff if (sn->af == AF_INET) 6443b3a8eb9SGleb Smirnoff aw.v.a.mask.addr32[0] = 0xffffffff; 6453b3a8eb9SGleb Smirnoff else 6463b3a8eb9SGleb Smirnoff memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask)); 6473b3a8eb9SGleb Smirnoff 6483b3a8eb9SGleb Smirnoff aw.v.a.addr = sn->addr; 6493b3a8eb9SGleb Smirnoff print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); 6503b3a8eb9SGleb Smirnoff printf(" -> "); 6513b3a8eb9SGleb Smirnoff aw.v.a.addr = sn->raddr; 6523b3a8eb9SGleb Smirnoff print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); 6533b3a8eb9SGleb Smirnoff printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states, 6543b3a8eb9SGleb Smirnoff sn->conn, sn->conn_rate.count / 1000, 6553b3a8eb9SGleb Smirnoff (sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds); 6563b3a8eb9SGleb Smirnoff if (opts & PF_OPT_VERBOSE) { 6573b3a8eb9SGleb Smirnoff sec = sn->creation % 60; 6583b3a8eb9SGleb Smirnoff sn->creation /= 60; 6593b3a8eb9SGleb Smirnoff min = sn->creation % 60; 6603b3a8eb9SGleb Smirnoff sn->creation /= 60; 6613b3a8eb9SGleb Smirnoff printf(" age %.2u:%.2u:%.2u", sn->creation, min, sec); 6623b3a8eb9SGleb Smirnoff if (sn->states == 0) { 6633b3a8eb9SGleb Smirnoff sec = sn->expire % 60; 6643b3a8eb9SGleb Smirnoff sn->expire /= 60; 6653b3a8eb9SGleb Smirnoff min = sn->expire % 60; 6663b3a8eb9SGleb Smirnoff sn->expire /= 60; 6673b3a8eb9SGleb Smirnoff printf(", expires in %.2u:%.2u:%.2u", 6683b3a8eb9SGleb Smirnoff sn->expire, min, sec); 6693b3a8eb9SGleb Smirnoff } 6703b3a8eb9SGleb Smirnoff printf(", %llu pkts, %llu bytes", 6713b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 6723b3a8eb9SGleb Smirnoff (unsigned long long)(sn->packets[0] + sn->packets[1]), 6733b3a8eb9SGleb Smirnoff (unsigned long long)(sn->bytes[0] + sn->bytes[1])); 6743b3a8eb9SGleb Smirnoff #else 6753b3a8eb9SGleb Smirnoff sn->packets[0] + sn->packets[1], 6763b3a8eb9SGleb Smirnoff sn->bytes[0] + sn->bytes[1]); 6773b3a8eb9SGleb Smirnoff #endif 6783b3a8eb9SGleb Smirnoff switch (sn->ruletype) { 6793b3a8eb9SGleb Smirnoff case PF_NAT: 6803b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 6813b3a8eb9SGleb Smirnoff printf(", nat rule %u", sn->rule.nr); 6823b3a8eb9SGleb Smirnoff break; 6833b3a8eb9SGleb Smirnoff case PF_RDR: 6843b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 6853b3a8eb9SGleb Smirnoff printf(", rdr rule %u", sn->rule.nr); 6863b3a8eb9SGleb Smirnoff break; 6873b3a8eb9SGleb Smirnoff case PF_PASS: 6883b3a8eb9SGleb Smirnoff if (sn->rule.nr != -1) 6893b3a8eb9SGleb Smirnoff printf(", filter rule %u", sn->rule.nr); 6903b3a8eb9SGleb Smirnoff break; 6913b3a8eb9SGleb Smirnoff } 6923b3a8eb9SGleb Smirnoff printf("\n"); 6933b3a8eb9SGleb Smirnoff } 6943b3a8eb9SGleb Smirnoff } 6953b3a8eb9SGleb Smirnoff 6963b3a8eb9SGleb Smirnoff void 697*e9eb0941SKristof Provost print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numeric) 6983b3a8eb9SGleb Smirnoff { 6993b3a8eb9SGleb Smirnoff static const char *actiontypes[] = { "pass", "block", "scrub", 7003b3a8eb9SGleb Smirnoff "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" }; 7013b3a8eb9SGleb Smirnoff static const char *anchortypes[] = { "anchor", "anchor", "anchor", 7023b3a8eb9SGleb Smirnoff "anchor", "nat-anchor", "nat-anchor", "binat-anchor", 7033b3a8eb9SGleb Smirnoff "binat-anchor", "rdr-anchor", "rdr-anchor" }; 7043b3a8eb9SGleb Smirnoff int i, opts; 7053b3a8eb9SGleb Smirnoff 7063b3a8eb9SGleb Smirnoff if (verbose) 7073b3a8eb9SGleb Smirnoff printf("@%d ", r->nr); 7083b3a8eb9SGleb Smirnoff if (r->action > PF_NORDR) 7093b3a8eb9SGleb Smirnoff printf("action(%d)", r->action); 7103b3a8eb9SGleb Smirnoff else if (anchor_call[0]) { 7113b3a8eb9SGleb Smirnoff if (anchor_call[0] == '_') { 7123b3a8eb9SGleb Smirnoff printf("%s", anchortypes[r->action]); 7133b3a8eb9SGleb Smirnoff } else 7143b3a8eb9SGleb Smirnoff printf("%s \"%s\"", anchortypes[r->action], 7153b3a8eb9SGleb Smirnoff anchor_call); 7163b3a8eb9SGleb Smirnoff } else { 7173b3a8eb9SGleb Smirnoff printf("%s", actiontypes[r->action]); 7183b3a8eb9SGleb Smirnoff if (r->natpass) 7193b3a8eb9SGleb Smirnoff printf(" pass"); 7203b3a8eb9SGleb Smirnoff } 7213b3a8eb9SGleb Smirnoff if (r->action == PF_DROP) { 7223b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RETURN) 7233b3a8eb9SGleb Smirnoff printf(" return"); 7243b3a8eb9SGleb Smirnoff else if (r->rule_flag & PFRULE_RETURNRST) { 7253b3a8eb9SGleb Smirnoff if (!r->return_ttl) 7263b3a8eb9SGleb Smirnoff printf(" return-rst"); 7273b3a8eb9SGleb Smirnoff else 7283b3a8eb9SGleb Smirnoff printf(" return-rst(ttl %d)", r->return_ttl); 7293b3a8eb9SGleb Smirnoff } else if (r->rule_flag & PFRULE_RETURNICMP) { 7303b3a8eb9SGleb Smirnoff const struct icmpcodeent *ic, *ic6; 7313b3a8eb9SGleb Smirnoff 7323b3a8eb9SGleb Smirnoff ic = geticmpcodebynumber(r->return_icmp >> 8, 7333b3a8eb9SGleb Smirnoff r->return_icmp & 255, AF_INET); 7343b3a8eb9SGleb Smirnoff ic6 = geticmpcodebynumber(r->return_icmp6 >> 8, 7353b3a8eb9SGleb Smirnoff r->return_icmp6 & 255, AF_INET6); 7363b3a8eb9SGleb Smirnoff 7373b3a8eb9SGleb Smirnoff switch (r->af) { 7383b3a8eb9SGleb Smirnoff case AF_INET: 7393b3a8eb9SGleb Smirnoff printf(" return-icmp"); 7403b3a8eb9SGleb Smirnoff if (ic == NULL) 7413b3a8eb9SGleb Smirnoff printf("(%u)", r->return_icmp & 255); 7423b3a8eb9SGleb Smirnoff else 7433b3a8eb9SGleb Smirnoff printf("(%s)", ic->name); 7443b3a8eb9SGleb Smirnoff break; 7453b3a8eb9SGleb Smirnoff case AF_INET6: 7463b3a8eb9SGleb Smirnoff printf(" return-icmp6"); 7473b3a8eb9SGleb Smirnoff if (ic6 == NULL) 7483b3a8eb9SGleb Smirnoff printf("(%u)", r->return_icmp6 & 255); 7493b3a8eb9SGleb Smirnoff else 7503b3a8eb9SGleb Smirnoff printf("(%s)", ic6->name); 7513b3a8eb9SGleb Smirnoff break; 7523b3a8eb9SGleb Smirnoff default: 7533b3a8eb9SGleb Smirnoff printf(" return-icmp"); 7543b3a8eb9SGleb Smirnoff if (ic == NULL) 7553b3a8eb9SGleb Smirnoff printf("(%u, ", r->return_icmp & 255); 7563b3a8eb9SGleb Smirnoff else 7573b3a8eb9SGleb Smirnoff printf("(%s, ", ic->name); 7583b3a8eb9SGleb Smirnoff if (ic6 == NULL) 7593b3a8eb9SGleb Smirnoff printf("%u)", r->return_icmp6 & 255); 7603b3a8eb9SGleb Smirnoff else 7613b3a8eb9SGleb Smirnoff printf("%s)", ic6->name); 7623b3a8eb9SGleb Smirnoff break; 7633b3a8eb9SGleb Smirnoff } 7643b3a8eb9SGleb Smirnoff } else 7653b3a8eb9SGleb Smirnoff printf(" drop"); 7663b3a8eb9SGleb Smirnoff } 7673b3a8eb9SGleb Smirnoff if (r->direction == PF_IN) 7683b3a8eb9SGleb Smirnoff printf(" in"); 7693b3a8eb9SGleb Smirnoff else if (r->direction == PF_OUT) 7703b3a8eb9SGleb Smirnoff printf(" out"); 7713b3a8eb9SGleb Smirnoff if (r->log) { 7723b3a8eb9SGleb Smirnoff printf(" log"); 7733b3a8eb9SGleb Smirnoff if (r->log & ~PF_LOG || r->logif) { 7743b3a8eb9SGleb Smirnoff int count = 0; 7753b3a8eb9SGleb Smirnoff 7763b3a8eb9SGleb Smirnoff printf(" ("); 7773b3a8eb9SGleb Smirnoff if (r->log & PF_LOG_ALL) 7783b3a8eb9SGleb Smirnoff printf("%sall", count++ ? ", " : ""); 7793b3a8eb9SGleb Smirnoff if (r->log & PF_LOG_SOCKET_LOOKUP) 7803b3a8eb9SGleb Smirnoff printf("%suser", count++ ? ", " : ""); 7813b3a8eb9SGleb Smirnoff if (r->logif) 7823b3a8eb9SGleb Smirnoff printf("%sto pflog%u", count++ ? ", " : "", 7833b3a8eb9SGleb Smirnoff r->logif); 7843b3a8eb9SGleb Smirnoff printf(")"); 7853b3a8eb9SGleb Smirnoff } 7863b3a8eb9SGleb Smirnoff } 7873b3a8eb9SGleb Smirnoff if (r->quick) 7883b3a8eb9SGleb Smirnoff printf(" quick"); 7893b3a8eb9SGleb Smirnoff if (r->ifname[0]) { 7903b3a8eb9SGleb Smirnoff if (r->ifnot) 7913b3a8eb9SGleb Smirnoff printf(" on ! %s", r->ifname); 7923b3a8eb9SGleb Smirnoff else 7933b3a8eb9SGleb Smirnoff printf(" on %s", r->ifname); 7943b3a8eb9SGleb Smirnoff } 7953b3a8eb9SGleb Smirnoff if (r->rt) { 7963b3a8eb9SGleb Smirnoff if (r->rt == PF_ROUTETO) 7973b3a8eb9SGleb Smirnoff printf(" route-to"); 7983b3a8eb9SGleb Smirnoff else if (r->rt == PF_REPLYTO) 7993b3a8eb9SGleb Smirnoff printf(" reply-to"); 8003b3a8eb9SGleb Smirnoff else if (r->rt == PF_DUPTO) 8013b3a8eb9SGleb Smirnoff printf(" dup-to"); 8023b3a8eb9SGleb Smirnoff printf(" "); 8033b3a8eb9SGleb Smirnoff print_pool(&r->rpool, 0, 0, r->af, PF_PASS); 8043b3a8eb9SGleb Smirnoff } 8053b3a8eb9SGleb Smirnoff if (r->af) { 8063b3a8eb9SGleb Smirnoff if (r->af == AF_INET) 8073b3a8eb9SGleb Smirnoff printf(" inet"); 8083b3a8eb9SGleb Smirnoff else 8093b3a8eb9SGleb Smirnoff printf(" inet6"); 8103b3a8eb9SGleb Smirnoff } 8113b3a8eb9SGleb Smirnoff if (r->proto) { 8123b3a8eb9SGleb Smirnoff struct protoent *p; 8133b3a8eb9SGleb Smirnoff 8143b3a8eb9SGleb Smirnoff if ((p = getprotobynumber(r->proto)) != NULL) 8153b3a8eb9SGleb Smirnoff printf(" proto %s", p->p_name); 8163b3a8eb9SGleb Smirnoff else 8173b3a8eb9SGleb Smirnoff printf(" proto %u", r->proto); 8183b3a8eb9SGleb Smirnoff } 8193b3a8eb9SGleb Smirnoff print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto, 8203b3a8eb9SGleb Smirnoff verbose, numeric); 8213b3a8eb9SGleb Smirnoff if (r->uid.op) 8223b3a8eb9SGleb Smirnoff print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user", 8233b3a8eb9SGleb Smirnoff UID_MAX); 8243b3a8eb9SGleb Smirnoff if (r->gid.op) 8253b3a8eb9SGleb Smirnoff print_ugid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group", 8263b3a8eb9SGleb Smirnoff GID_MAX); 8273b3a8eb9SGleb Smirnoff if (r->flags || r->flagset) { 8283b3a8eb9SGleb Smirnoff printf(" flags "); 8293b3a8eb9SGleb Smirnoff print_flags(r->flags); 8303b3a8eb9SGleb Smirnoff printf("/"); 8313b3a8eb9SGleb Smirnoff print_flags(r->flagset); 8323b3a8eb9SGleb Smirnoff } else if (r->action == PF_PASS && 8333b3a8eb9SGleb Smirnoff (!r->proto || r->proto == IPPROTO_TCP) && 8343b3a8eb9SGleb Smirnoff !(r->rule_flag & PFRULE_FRAGMENT) && 8353b3a8eb9SGleb Smirnoff !anchor_call[0] && r->keep_state) 8363b3a8eb9SGleb Smirnoff printf(" flags any"); 8373b3a8eb9SGleb Smirnoff if (r->type) { 8383b3a8eb9SGleb Smirnoff const struct icmptypeent *it; 8393b3a8eb9SGleb Smirnoff 8403b3a8eb9SGleb Smirnoff it = geticmptypebynumber(r->type-1, r->af); 8413b3a8eb9SGleb Smirnoff if (r->af != AF_INET6) 8423b3a8eb9SGleb Smirnoff printf(" icmp-type"); 8433b3a8eb9SGleb Smirnoff else 8443b3a8eb9SGleb Smirnoff printf(" icmp6-type"); 8453b3a8eb9SGleb Smirnoff if (it != NULL) 8463b3a8eb9SGleb Smirnoff printf(" %s", it->name); 8473b3a8eb9SGleb Smirnoff else 8483b3a8eb9SGleb Smirnoff printf(" %u", r->type-1); 8493b3a8eb9SGleb Smirnoff if (r->code) { 8503b3a8eb9SGleb Smirnoff const struct icmpcodeent *ic; 8513b3a8eb9SGleb Smirnoff 8523b3a8eb9SGleb Smirnoff ic = geticmpcodebynumber(r->type-1, r->code-1, r->af); 8533b3a8eb9SGleb Smirnoff if (ic != NULL) 8543b3a8eb9SGleb Smirnoff printf(" code %s", ic->name); 8553b3a8eb9SGleb Smirnoff else 8563b3a8eb9SGleb Smirnoff printf(" code %u", r->code-1); 8573b3a8eb9SGleb Smirnoff } 8583b3a8eb9SGleb Smirnoff } 8593b3a8eb9SGleb Smirnoff if (r->tos) 8603b3a8eb9SGleb Smirnoff printf(" tos 0x%2.2x", r->tos); 8613e248e0fSKristof Provost if (r->prio) 8623e248e0fSKristof Provost printf(" prio %u", r->prio == PF_PRIO_ZERO ? 0 : r->prio); 8633e248e0fSKristof Provost if (r->scrub_flags & PFSTATE_SETMASK) { 8643e248e0fSKristof Provost char *comma = ""; 8653e248e0fSKristof Provost printf(" set ("); 8663e248e0fSKristof Provost if (r->scrub_flags & PFSTATE_SETPRIO) { 8673e248e0fSKristof Provost if (r->set_prio[0] == r->set_prio[1]) 8683e248e0fSKristof Provost printf("%s prio %u", comma, r->set_prio[0]); 8693e248e0fSKristof Provost else 8703e248e0fSKristof Provost printf("%s prio(%u, %u)", comma, r->set_prio[0], 8713e248e0fSKristof Provost r->set_prio[1]); 8723e248e0fSKristof Provost comma = ","; 8733e248e0fSKristof Provost } 8743e248e0fSKristof Provost printf(" )"); 8753e248e0fSKristof Provost } 8763b3a8eb9SGleb Smirnoff if (!r->keep_state && r->action == PF_PASS && !anchor_call[0]) 8773b3a8eb9SGleb Smirnoff printf(" no state"); 8783b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_NORMAL) 8793b3a8eb9SGleb Smirnoff printf(" keep state"); 8803b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_MODULATE) 8813b3a8eb9SGleb Smirnoff printf(" modulate state"); 8823b3a8eb9SGleb Smirnoff else if (r->keep_state == PF_STATE_SYNPROXY) 8833b3a8eb9SGleb Smirnoff printf(" synproxy state"); 8843b3a8eb9SGleb Smirnoff if (r->prob) { 8853b3a8eb9SGleb Smirnoff char buf[20]; 8863b3a8eb9SGleb Smirnoff 8873b3a8eb9SGleb Smirnoff snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0)); 8883b3a8eb9SGleb Smirnoff for (i = strlen(buf)-1; i > 0; i--) { 8893b3a8eb9SGleb Smirnoff if (buf[i] == '0') 8903b3a8eb9SGleb Smirnoff buf[i] = '\0'; 8913b3a8eb9SGleb Smirnoff else { 8923b3a8eb9SGleb Smirnoff if (buf[i] == '.') 8933b3a8eb9SGleb Smirnoff buf[i] = '\0'; 8943b3a8eb9SGleb Smirnoff break; 8953b3a8eb9SGleb Smirnoff } 8963b3a8eb9SGleb Smirnoff } 8973b3a8eb9SGleb Smirnoff printf(" probability %s%%", buf); 8983b3a8eb9SGleb Smirnoff } 8993b3a8eb9SGleb Smirnoff opts = 0; 9003b3a8eb9SGleb Smirnoff if (r->max_states || r->max_src_nodes || r->max_src_states) 9013b3a8eb9SGleb Smirnoff opts = 1; 9023b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NOSYNC) 9033b3a8eb9SGleb Smirnoff opts = 1; 9043b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SRCTRACK) 9053b3a8eb9SGleb Smirnoff opts = 1; 9063b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_IFBOUND) 9073b3a8eb9SGleb Smirnoff opts = 1; 9083b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY) 9093b3a8eb9SGleb Smirnoff opts = 1; 9103b3a8eb9SGleb Smirnoff for (i = 0; !opts && i < PFTM_MAX; ++i) 9113b3a8eb9SGleb Smirnoff if (r->timeout[i]) 9123b3a8eb9SGleb Smirnoff opts = 1; 9133b3a8eb9SGleb Smirnoff if (opts) { 9143b3a8eb9SGleb Smirnoff printf(" ("); 9153b3a8eb9SGleb Smirnoff if (r->max_states) { 9163b3a8eb9SGleb Smirnoff printf("max %u", r->max_states); 9173b3a8eb9SGleb Smirnoff opts = 0; 9183b3a8eb9SGleb Smirnoff } 9193b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NOSYNC) { 9203b3a8eb9SGleb Smirnoff if (!opts) 9213b3a8eb9SGleb Smirnoff printf(", "); 9223b3a8eb9SGleb Smirnoff printf("no-sync"); 9233b3a8eb9SGleb Smirnoff opts = 0; 9243b3a8eb9SGleb Smirnoff } 9253b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SRCTRACK) { 9263b3a8eb9SGleb Smirnoff if (!opts) 9273b3a8eb9SGleb Smirnoff printf(", "); 9283b3a8eb9SGleb Smirnoff printf("source-track"); 9293b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RULESRCTRACK) 9303b3a8eb9SGleb Smirnoff printf(" rule"); 9313b3a8eb9SGleb Smirnoff else 9323b3a8eb9SGleb Smirnoff printf(" global"); 9333b3a8eb9SGleb Smirnoff opts = 0; 9343b3a8eb9SGleb Smirnoff } 9353b3a8eb9SGleb Smirnoff if (r->max_src_states) { 9363b3a8eb9SGleb Smirnoff if (!opts) 9373b3a8eb9SGleb Smirnoff printf(", "); 9383b3a8eb9SGleb Smirnoff printf("max-src-states %u", r->max_src_states); 9393b3a8eb9SGleb Smirnoff opts = 0; 9403b3a8eb9SGleb Smirnoff } 9413b3a8eb9SGleb Smirnoff if (r->max_src_conn) { 9423b3a8eb9SGleb Smirnoff if (!opts) 9433b3a8eb9SGleb Smirnoff printf(", "); 9443b3a8eb9SGleb Smirnoff printf("max-src-conn %u", r->max_src_conn); 9453b3a8eb9SGleb Smirnoff opts = 0; 9463b3a8eb9SGleb Smirnoff } 9473b3a8eb9SGleb Smirnoff if (r->max_src_conn_rate.limit) { 9483b3a8eb9SGleb Smirnoff if (!opts) 9493b3a8eb9SGleb Smirnoff printf(", "); 9503b3a8eb9SGleb Smirnoff printf("max-src-conn-rate %u/%u", 9513b3a8eb9SGleb Smirnoff r->max_src_conn_rate.limit, 9523b3a8eb9SGleb Smirnoff r->max_src_conn_rate.seconds); 9533b3a8eb9SGleb Smirnoff opts = 0; 9543b3a8eb9SGleb Smirnoff } 9553b3a8eb9SGleb Smirnoff if (r->max_src_nodes) { 9563b3a8eb9SGleb Smirnoff if (!opts) 9573b3a8eb9SGleb Smirnoff printf(", "); 9583b3a8eb9SGleb Smirnoff printf("max-src-nodes %u", r->max_src_nodes); 9593b3a8eb9SGleb Smirnoff opts = 0; 9603b3a8eb9SGleb Smirnoff } 9613b3a8eb9SGleb Smirnoff if (r->overload_tblname[0]) { 9623b3a8eb9SGleb Smirnoff if (!opts) 9633b3a8eb9SGleb Smirnoff printf(", "); 9643b3a8eb9SGleb Smirnoff printf("overload <%s>", r->overload_tblname); 9653b3a8eb9SGleb Smirnoff if (r->flush) 9663b3a8eb9SGleb Smirnoff printf(" flush"); 9673b3a8eb9SGleb Smirnoff if (r->flush & PF_FLUSH_GLOBAL) 9683b3a8eb9SGleb Smirnoff printf(" global"); 9693b3a8eb9SGleb Smirnoff } 9703b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_IFBOUND) { 9713b3a8eb9SGleb Smirnoff if (!opts) 9723b3a8eb9SGleb Smirnoff printf(", "); 9733b3a8eb9SGleb Smirnoff printf("if-bound"); 9743b3a8eb9SGleb Smirnoff opts = 0; 9753b3a8eb9SGleb Smirnoff } 9763b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY) { 9773b3a8eb9SGleb Smirnoff if (!opts) 9783b3a8eb9SGleb Smirnoff printf(", "); 9793b3a8eb9SGleb Smirnoff printf("sloppy"); 9803b3a8eb9SGleb Smirnoff opts = 0; 9813b3a8eb9SGleb Smirnoff } 9823b3a8eb9SGleb Smirnoff for (i = 0; i < PFTM_MAX; ++i) 9833b3a8eb9SGleb Smirnoff if (r->timeout[i]) { 9843b3a8eb9SGleb Smirnoff int j; 9853b3a8eb9SGleb Smirnoff 9863b3a8eb9SGleb Smirnoff if (!opts) 9873b3a8eb9SGleb Smirnoff printf(", "); 9883b3a8eb9SGleb Smirnoff opts = 0; 9893b3a8eb9SGleb Smirnoff for (j = 0; pf_timeouts[j].name != NULL; 9903b3a8eb9SGleb Smirnoff ++j) 9913b3a8eb9SGleb Smirnoff if (pf_timeouts[j].timeout == i) 9923b3a8eb9SGleb Smirnoff break; 9933b3a8eb9SGleb Smirnoff printf("%s %u", pf_timeouts[j].name == NULL ? 9943b3a8eb9SGleb Smirnoff "inv.timeout" : pf_timeouts[j].name, 9953b3a8eb9SGleb Smirnoff r->timeout[i]); 9963b3a8eb9SGleb Smirnoff } 9973b3a8eb9SGleb Smirnoff printf(")"); 9983b3a8eb9SGleb Smirnoff } 9993b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_FRAGMENT) 10003b3a8eb9SGleb Smirnoff printf(" fragment"); 10013b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_NODF) 10023b3a8eb9SGleb Smirnoff printf(" no-df"); 10033b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RANDOMID) 10043b3a8eb9SGleb Smirnoff printf(" random-id"); 10053b3a8eb9SGleb Smirnoff if (r->min_ttl) 10063b3a8eb9SGleb Smirnoff printf(" min-ttl %d", r->min_ttl); 10073b3a8eb9SGleb Smirnoff if (r->max_mss) 10083b3a8eb9SGleb Smirnoff printf(" max-mss %d", r->max_mss); 10093b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_SET_TOS) 10103b3a8eb9SGleb Smirnoff printf(" set-tos 0x%2.2x", r->set_tos); 10113b3a8eb9SGleb Smirnoff if (r->allow_opts) 10123b3a8eb9SGleb Smirnoff printf(" allow-opts"); 10133b3a8eb9SGleb Smirnoff if (r->action == PF_SCRUB) { 10143b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_REASSEMBLE_TCP) 10153b3a8eb9SGleb Smirnoff printf(" reassemble tcp"); 10163b3a8eb9SGleb Smirnoff 10173b3a8eb9SGleb Smirnoff printf(" fragment reassemble"); 10183b3a8eb9SGleb Smirnoff } 10193b3a8eb9SGleb Smirnoff if (r->label[0]) 10203b3a8eb9SGleb Smirnoff printf(" label \"%s\"", r->label); 10213b3a8eb9SGleb Smirnoff if (r->qname[0] && r->pqname[0]) 10223b3a8eb9SGleb Smirnoff printf(" queue(%s, %s)", r->qname, r->pqname); 10233b3a8eb9SGleb Smirnoff else if (r->qname[0]) 10243b3a8eb9SGleb Smirnoff printf(" queue %s", r->qname); 10253b3a8eb9SGleb Smirnoff if (r->tagname[0]) 10263b3a8eb9SGleb Smirnoff printf(" tag %s", r->tagname); 10273b3a8eb9SGleb Smirnoff if (r->match_tagname[0]) { 10283b3a8eb9SGleb Smirnoff if (r->match_tag_not) 10293b3a8eb9SGleb Smirnoff printf(" !"); 10303b3a8eb9SGleb Smirnoff printf(" tagged %s", r->match_tagname); 10313b3a8eb9SGleb Smirnoff } 10323b3a8eb9SGleb Smirnoff if (r->rtableid != -1) 10333b3a8eb9SGleb Smirnoff printf(" rtable %u", r->rtableid); 10343b3a8eb9SGleb Smirnoff if (r->divert.port) { 10353b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 10363b3a8eb9SGleb Smirnoff printf(" divert-to %u", ntohs(r->divert.port)); 10373b3a8eb9SGleb Smirnoff #else 10383b3a8eb9SGleb Smirnoff if (PF_AZERO(&r->divert.addr, r->af)) { 10393b3a8eb9SGleb Smirnoff printf(" divert-reply"); 10403b3a8eb9SGleb Smirnoff } else { 10413b3a8eb9SGleb Smirnoff /* XXX cut&paste from print_addr */ 10423b3a8eb9SGleb Smirnoff char buf[48]; 10433b3a8eb9SGleb Smirnoff 10443b3a8eb9SGleb Smirnoff printf(" divert-to "); 10453b3a8eb9SGleb Smirnoff if (inet_ntop(r->af, &r->divert.addr, buf, 10463b3a8eb9SGleb Smirnoff sizeof(buf)) == NULL) 10473b3a8eb9SGleb Smirnoff printf("?"); 10483b3a8eb9SGleb Smirnoff else 10493b3a8eb9SGleb Smirnoff printf("%s", buf); 10503b3a8eb9SGleb Smirnoff printf(" port %u", ntohs(r->divert.port)); 10513b3a8eb9SGleb Smirnoff } 10523b3a8eb9SGleb Smirnoff #endif 10533b3a8eb9SGleb Smirnoff } 10543b3a8eb9SGleb Smirnoff if (!anchor_call[0] && (r->action == PF_NAT || 10553b3a8eb9SGleb Smirnoff r->action == PF_BINAT || r->action == PF_RDR)) { 10563b3a8eb9SGleb Smirnoff printf(" -> "); 10573b3a8eb9SGleb Smirnoff print_pool(&r->rpool, r->rpool.proxy_port[0], 10583b3a8eb9SGleb Smirnoff r->rpool.proxy_port[1], r->af, r->action); 10593b3a8eb9SGleb Smirnoff } 10603b3a8eb9SGleb Smirnoff } 10613b3a8eb9SGleb Smirnoff 10623b3a8eb9SGleb Smirnoff void 10633b3a8eb9SGleb Smirnoff print_tabledef(const char *name, int flags, int addrs, 10643b3a8eb9SGleb Smirnoff struct node_tinithead *nodes) 10653b3a8eb9SGleb Smirnoff { 10663b3a8eb9SGleb Smirnoff struct node_tinit *ti, *nti; 10673b3a8eb9SGleb Smirnoff struct node_host *h; 10683b3a8eb9SGleb Smirnoff 10693b3a8eb9SGleb Smirnoff printf("table <%s>", name); 10703b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_CONST) 10713b3a8eb9SGleb Smirnoff printf(" const"); 10723b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_PERSIST) 10733b3a8eb9SGleb Smirnoff printf(" persist"); 10743b3a8eb9SGleb Smirnoff if (flags & PFR_TFLAG_COUNTERS) 10753b3a8eb9SGleb Smirnoff printf(" counters"); 10763b3a8eb9SGleb Smirnoff SIMPLEQ_FOREACH(ti, nodes, entries) { 10773b3a8eb9SGleb Smirnoff if (ti->file) { 10783b3a8eb9SGleb Smirnoff printf(" file \"%s\"", ti->file); 10793b3a8eb9SGleb Smirnoff continue; 10803b3a8eb9SGleb Smirnoff } 10813b3a8eb9SGleb Smirnoff printf(" {"); 10823b3a8eb9SGleb Smirnoff for (;;) { 10833b3a8eb9SGleb Smirnoff for (h = ti->host; h != NULL; h = h->next) { 10843b3a8eb9SGleb Smirnoff printf(h->not ? " !" : " "); 10853b3a8eb9SGleb Smirnoff print_addr(&h->addr, h->af, 0); 10863b3a8eb9SGleb Smirnoff } 10873b3a8eb9SGleb Smirnoff nti = SIMPLEQ_NEXT(ti, entries); 10883b3a8eb9SGleb Smirnoff if (nti != NULL && nti->file == NULL) 10893b3a8eb9SGleb Smirnoff ti = nti; /* merge lists */ 10903b3a8eb9SGleb Smirnoff else 10913b3a8eb9SGleb Smirnoff break; 10923b3a8eb9SGleb Smirnoff } 10933b3a8eb9SGleb Smirnoff printf(" }"); 10943b3a8eb9SGleb Smirnoff } 10953b3a8eb9SGleb Smirnoff if (addrs && SIMPLEQ_EMPTY(nodes)) 10963b3a8eb9SGleb Smirnoff printf(" { }"); 10973b3a8eb9SGleb Smirnoff printf("\n"); 10983b3a8eb9SGleb Smirnoff } 10993b3a8eb9SGleb Smirnoff 11003b3a8eb9SGleb Smirnoff int 11013b3a8eb9SGleb Smirnoff parse_flags(char *s) 11023b3a8eb9SGleb Smirnoff { 11033b3a8eb9SGleb Smirnoff char *p, *q; 11043b3a8eb9SGleb Smirnoff u_int8_t f = 0; 11053b3a8eb9SGleb Smirnoff 11063b3a8eb9SGleb Smirnoff for (p = s; *p; p++) { 11073b3a8eb9SGleb Smirnoff if ((q = strchr(tcpflags, *p)) == NULL) 11083b3a8eb9SGleb Smirnoff return -1; 11093b3a8eb9SGleb Smirnoff else 11103b3a8eb9SGleb Smirnoff f |= 1 << (q - tcpflags); 11113b3a8eb9SGleb Smirnoff } 11123b3a8eb9SGleb Smirnoff return (f ? f : PF_TH_ALL); 11133b3a8eb9SGleb Smirnoff } 11143b3a8eb9SGleb Smirnoff 11153b3a8eb9SGleb Smirnoff void 11163b3a8eb9SGleb Smirnoff set_ipmask(struct node_host *h, u_int8_t b) 11173b3a8eb9SGleb Smirnoff { 11183b3a8eb9SGleb Smirnoff struct pf_addr *m, *n; 11193b3a8eb9SGleb Smirnoff int i, j = 0; 11203b3a8eb9SGleb Smirnoff 11213b3a8eb9SGleb Smirnoff m = &h->addr.v.a.mask; 11223b3a8eb9SGleb Smirnoff memset(m, 0, sizeof(*m)); 11233b3a8eb9SGleb Smirnoff 11243b3a8eb9SGleb Smirnoff while (b >= 32) { 11253b3a8eb9SGleb Smirnoff m->addr32[j++] = 0xffffffff; 11263b3a8eb9SGleb Smirnoff b -= 32; 11273b3a8eb9SGleb Smirnoff } 11283b3a8eb9SGleb Smirnoff for (i = 31; i > 31-b; --i) 11293b3a8eb9SGleb Smirnoff m->addr32[j] |= (1 << i); 11303b3a8eb9SGleb Smirnoff if (b) 11313b3a8eb9SGleb Smirnoff m->addr32[j] = htonl(m->addr32[j]); 11323b3a8eb9SGleb Smirnoff 11333b3a8eb9SGleb Smirnoff /* Mask off bits of the address that will never be used. */ 11343b3a8eb9SGleb Smirnoff n = &h->addr.v.a.addr; 11353b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_ADDRMASK) 11363b3a8eb9SGleb Smirnoff for (i = 0; i < 4; i++) 11373b3a8eb9SGleb Smirnoff n->addr32[i] = n->addr32[i] & m->addr32[i]; 11383b3a8eb9SGleb Smirnoff } 11393b3a8eb9SGleb Smirnoff 11403b3a8eb9SGleb Smirnoff int 11413b3a8eb9SGleb Smirnoff check_netmask(struct node_host *h, sa_family_t af) 11423b3a8eb9SGleb Smirnoff { 11433b3a8eb9SGleb Smirnoff struct node_host *n = NULL; 11443b3a8eb9SGleb Smirnoff struct pf_addr *m; 11453b3a8eb9SGleb Smirnoff 11463b3a8eb9SGleb Smirnoff for (n = h; n != NULL; n = n->next) { 11473b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_TABLE) 11483b3a8eb9SGleb Smirnoff continue; 11493b3a8eb9SGleb Smirnoff m = &h->addr.v.a.mask; 11503b3a8eb9SGleb Smirnoff /* fix up netmask for dynaddr */ 11513b3a8eb9SGleb Smirnoff if (af == AF_INET && h->addr.type == PF_ADDR_DYNIFTL && 11523b3a8eb9SGleb Smirnoff unmask(m, AF_INET6) > 32) 11533b3a8eb9SGleb Smirnoff set_ipmask(n, 32); 11543b3a8eb9SGleb Smirnoff /* netmasks > 32 bit are invalid on v4 */ 11553b3a8eb9SGleb Smirnoff if (af == AF_INET && 11563b3a8eb9SGleb Smirnoff (m->addr32[1] || m->addr32[2] || m->addr32[3])) { 11573b3a8eb9SGleb Smirnoff fprintf(stderr, "netmask %u invalid for IPv4 address\n", 11583b3a8eb9SGleb Smirnoff unmask(m, AF_INET6)); 11593b3a8eb9SGleb Smirnoff return (1); 11603b3a8eb9SGleb Smirnoff } 11613b3a8eb9SGleb Smirnoff } 11623b3a8eb9SGleb Smirnoff return (0); 11633b3a8eb9SGleb Smirnoff } 11643b3a8eb9SGleb Smirnoff 11653b3a8eb9SGleb Smirnoff /* interface lookup routines */ 11663b3a8eb9SGleb Smirnoff 116713cfafabSKristof Provost static struct node_host *iftab; 11683b3a8eb9SGleb Smirnoff 11691d34c9daSPatrick Kelsey /* 11701d34c9daSPatrick Kelsey * Retrieve the list of groups this interface is a member of and make sure 11711d34c9daSPatrick Kelsey * each group is in the group map. 11721d34c9daSPatrick Kelsey */ 11731d34c9daSPatrick Kelsey static void 11741d34c9daSPatrick Kelsey ifa_add_groups_to_map(char *ifa_name) 11751d34c9daSPatrick Kelsey { 11761d34c9daSPatrick Kelsey int s, len; 11771d34c9daSPatrick Kelsey struct ifgroupreq ifgr; 11781d34c9daSPatrick Kelsey struct ifg_req *ifg; 11791d34c9daSPatrick Kelsey 11801d34c9daSPatrick Kelsey s = get_query_socket(); 11811d34c9daSPatrick Kelsey 11821d34c9daSPatrick Kelsey /* Get size of group list for this interface */ 11831d34c9daSPatrick Kelsey memset(&ifgr, 0, sizeof(ifgr)); 11841d34c9daSPatrick Kelsey strlcpy(ifgr.ifgr_name, ifa_name, IFNAMSIZ); 11851d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 11861d34c9daSPatrick Kelsey err(1, "SIOCGIFGROUP"); 11871d34c9daSPatrick Kelsey 11881d34c9daSPatrick Kelsey /* Retrieve group list for this interface */ 11891d34c9daSPatrick Kelsey len = ifgr.ifgr_len; 11901d34c9daSPatrick Kelsey ifgr.ifgr_groups = 11911d34c9daSPatrick Kelsey (struct ifg_req *)calloc(len / sizeof(struct ifg_req), 11921d34c9daSPatrick Kelsey sizeof(struct ifg_req)); 11931d34c9daSPatrick Kelsey if (ifgr.ifgr_groups == NULL) 11941d34c9daSPatrick Kelsey err(1, "calloc"); 11951d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 11961d34c9daSPatrick Kelsey err(1, "SIOCGIFGROUP"); 11971d34c9daSPatrick Kelsey 11981d34c9daSPatrick Kelsey ifg = ifgr.ifgr_groups; 11991d34c9daSPatrick Kelsey for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 12001d34c9daSPatrick Kelsey len -= sizeof(struct ifg_req); 12011d34c9daSPatrick Kelsey if (strcmp(ifg->ifgrq_group, "all")) { 12021d34c9daSPatrick Kelsey ENTRY item; 12031d34c9daSPatrick Kelsey ENTRY *ret_item; 12041d34c9daSPatrick Kelsey int *answer; 12051d34c9daSPatrick Kelsey 12061d34c9daSPatrick Kelsey item.key = ifg->ifgrq_group; 12071d34c9daSPatrick Kelsey if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) { 12081d34c9daSPatrick Kelsey struct ifgroupreq ifgr2; 12091d34c9daSPatrick Kelsey 12101d34c9daSPatrick Kelsey /* Don't know the answer yet */ 12111d34c9daSPatrick Kelsey if ((answer = malloc(sizeof(int))) == NULL) 12121d34c9daSPatrick Kelsey err(1, "malloc"); 12131d34c9daSPatrick Kelsey 12141d34c9daSPatrick Kelsey bzero(&ifgr2, sizeof(ifgr2)); 12151d34c9daSPatrick Kelsey strlcpy(ifgr2.ifgr_name, ifg->ifgrq_group, 12161d34c9daSPatrick Kelsey sizeof(ifgr2.ifgr_name)); 12171d34c9daSPatrick Kelsey if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr2) == 0) 12181d34c9daSPatrick Kelsey *answer = ifgr2.ifgr_len; 12191d34c9daSPatrick Kelsey else 12201d34c9daSPatrick Kelsey *answer = 0; 12211d34c9daSPatrick Kelsey 12221d34c9daSPatrick Kelsey item.key = strdup(ifg->ifgrq_group); 12231d34c9daSPatrick Kelsey item.data = answer; 12241d34c9daSPatrick Kelsey if (hsearch_r(item, ENTER, &ret_item, 12251d34c9daSPatrick Kelsey &isgroup_map) == 0) 12261d34c9daSPatrick Kelsey err(1, "interface group query response" 12271d34c9daSPatrick Kelsey " map insert"); 12281d34c9daSPatrick Kelsey } 12291d34c9daSPatrick Kelsey } 12301d34c9daSPatrick Kelsey } 12311d34c9daSPatrick Kelsey free(ifgr.ifgr_groups); 12321d34c9daSPatrick Kelsey } 12331d34c9daSPatrick Kelsey 12343b3a8eb9SGleb Smirnoff void 12353b3a8eb9SGleb Smirnoff ifa_load(void) 12363b3a8eb9SGleb Smirnoff { 12373b3a8eb9SGleb Smirnoff struct ifaddrs *ifap, *ifa; 12383b3a8eb9SGleb Smirnoff struct node_host *n = NULL, *h = NULL; 12393b3a8eb9SGleb Smirnoff 12403b3a8eb9SGleb Smirnoff if (getifaddrs(&ifap) < 0) 12413b3a8eb9SGleb Smirnoff err(1, "getifaddrs"); 12423b3a8eb9SGleb Smirnoff 12433b3a8eb9SGleb Smirnoff for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 12443b3a8eb9SGleb Smirnoff if (!(ifa->ifa_addr->sa_family == AF_INET || 12453b3a8eb9SGleb Smirnoff ifa->ifa_addr->sa_family == AF_INET6 || 12463b3a8eb9SGleb Smirnoff ifa->ifa_addr->sa_family == AF_LINK)) 12473b3a8eb9SGleb Smirnoff continue; 12483b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 12493b3a8eb9SGleb Smirnoff if (n == NULL) 12503b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 12513b3a8eb9SGleb Smirnoff n->af = ifa->ifa_addr->sa_family; 12523b3a8eb9SGleb Smirnoff n->ifa_flags = ifa->ifa_flags; 12533b3a8eb9SGleb Smirnoff #ifdef __KAME__ 12543b3a8eb9SGleb Smirnoff if (n->af == AF_INET6 && 12553b3a8eb9SGleb Smirnoff IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) 12563b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_addr) && 12573b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 12583b3a8eb9SGleb Smirnoff 0) { 12593b3a8eb9SGleb Smirnoff struct sockaddr_in6 *sin6; 12603b3a8eb9SGleb Smirnoff 12613b3a8eb9SGleb Smirnoff sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 12623b3a8eb9SGleb Smirnoff sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | 12633b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[3]; 12643b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[2] = 0; 12653b3a8eb9SGleb Smirnoff sin6->sin6_addr.s6_addr[3] = 0; 12663b3a8eb9SGleb Smirnoff } 12673b3a8eb9SGleb Smirnoff #endif 12683b3a8eb9SGleb Smirnoff n->ifindex = 0; 12693b3a8eb9SGleb Smirnoff if (n->af == AF_INET) { 12703b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) 12713b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin_addr.s_addr, 12723b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 12733b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) 12743b3a8eb9SGleb Smirnoff ifa->ifa_netmask)->sin_addr.s_addr, 12753b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 12763b3a8eb9SGleb Smirnoff if (ifa->ifa_broadaddr != NULL) 12773b3a8eb9SGleb Smirnoff memcpy(&n->bcast, &((struct sockaddr_in *) 12783b3a8eb9SGleb Smirnoff ifa->ifa_broadaddr)->sin_addr.s_addr, 12793b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 12803b3a8eb9SGleb Smirnoff if (ifa->ifa_dstaddr != NULL) 12813b3a8eb9SGleb Smirnoff memcpy(&n->peer, &((struct sockaddr_in *) 12823b3a8eb9SGleb Smirnoff ifa->ifa_dstaddr)->sin_addr.s_addr, 12833b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 12843b3a8eb9SGleb Smirnoff } else if (n->af == AF_INET6) { 12853b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) 12863b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_addr.s6_addr, 12873b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 12883b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) 12893b3a8eb9SGleb Smirnoff ifa->ifa_netmask)->sin6_addr.s6_addr, 12903b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 12913b3a8eb9SGleb Smirnoff if (ifa->ifa_broadaddr != NULL) 12923b3a8eb9SGleb Smirnoff memcpy(&n->bcast, &((struct sockaddr_in6 *) 12933b3a8eb9SGleb Smirnoff ifa->ifa_broadaddr)->sin6_addr.s6_addr, 12943b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 12953b3a8eb9SGleb Smirnoff if (ifa->ifa_dstaddr != NULL) 12963b3a8eb9SGleb Smirnoff memcpy(&n->peer, &((struct sockaddr_in6 *) 12973b3a8eb9SGleb Smirnoff ifa->ifa_dstaddr)->sin6_addr.s6_addr, 12983b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 12993b3a8eb9SGleb Smirnoff n->ifindex = ((struct sockaddr_in6 *) 13003b3a8eb9SGleb Smirnoff ifa->ifa_addr)->sin6_scope_id; 13011d34c9daSPatrick Kelsey } else if (n->af == AF_LINK) { 13021d34c9daSPatrick Kelsey ifa_add_groups_to_map(ifa->ifa_name); 13033b3a8eb9SGleb Smirnoff } 13043b3a8eb9SGleb Smirnoff if ((n->ifname = strdup(ifa->ifa_name)) == NULL) 13053b3a8eb9SGleb Smirnoff err(1, "ifa_load: strdup"); 13063b3a8eb9SGleb Smirnoff n->next = NULL; 13073b3a8eb9SGleb Smirnoff n->tail = n; 13083b3a8eb9SGleb Smirnoff if (h == NULL) 13093b3a8eb9SGleb Smirnoff h = n; 13103b3a8eb9SGleb Smirnoff else { 13113b3a8eb9SGleb Smirnoff h->tail->next = n; 13123b3a8eb9SGleb Smirnoff h->tail = n; 13133b3a8eb9SGleb Smirnoff } 13143b3a8eb9SGleb Smirnoff } 13153b3a8eb9SGleb Smirnoff 13163b3a8eb9SGleb Smirnoff iftab = h; 13173b3a8eb9SGleb Smirnoff freeifaddrs(ifap); 13183b3a8eb9SGleb Smirnoff } 13193b3a8eb9SGleb Smirnoff 13201d34c9daSPatrick Kelsey static int 1321f870cb7fSBjoern A. Zeeb get_socket_domain(void) 1322f870cb7fSBjoern A. Zeeb { 1323f870cb7fSBjoern A. Zeeb int sdom; 1324f870cb7fSBjoern A. Zeeb 1325f870cb7fSBjoern A. Zeeb sdom = AF_UNSPEC; 1326f870cb7fSBjoern A. Zeeb #ifdef WITH_INET6 1327f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC && feature_present("inet6")) 1328f870cb7fSBjoern A. Zeeb sdom = AF_INET6; 1329f870cb7fSBjoern A. Zeeb #endif 1330f870cb7fSBjoern A. Zeeb #ifdef WITH_INET 1331f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC && feature_present("inet")) 1332f870cb7fSBjoern A. Zeeb sdom = AF_INET; 1333f870cb7fSBjoern A. Zeeb #endif 1334f870cb7fSBjoern A. Zeeb if (sdom == AF_UNSPEC) 1335f870cb7fSBjoern A. Zeeb sdom = AF_LINK; 1336f870cb7fSBjoern A. Zeeb 1337f870cb7fSBjoern A. Zeeb return (sdom); 1338f870cb7fSBjoern A. Zeeb } 1339f870cb7fSBjoern A. Zeeb 13401d34c9daSPatrick Kelsey int 13411d34c9daSPatrick Kelsey get_query_socket(void) 13421d34c9daSPatrick Kelsey { 13431d34c9daSPatrick Kelsey static int s = -1; 13441d34c9daSPatrick Kelsey 13451d34c9daSPatrick Kelsey if (s == -1) { 13461d34c9daSPatrick Kelsey if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) 13471d34c9daSPatrick Kelsey err(1, "socket"); 13481d34c9daSPatrick Kelsey } 13491d34c9daSPatrick Kelsey 13501d34c9daSPatrick Kelsey return (s); 13511d34c9daSPatrick Kelsey } 13521d34c9daSPatrick Kelsey 13531d34c9daSPatrick Kelsey /* 13541d34c9daSPatrick Kelsey * Returns the response len if the name is a group, otherwise returns 0. 13551d34c9daSPatrick Kelsey */ 13561d34c9daSPatrick Kelsey static int 13571d34c9daSPatrick Kelsey is_a_group(char *name) 13581d34c9daSPatrick Kelsey { 13591d34c9daSPatrick Kelsey ENTRY item; 13601d34c9daSPatrick Kelsey ENTRY *ret_item; 13611d34c9daSPatrick Kelsey 13621d34c9daSPatrick Kelsey item.key = name; 13631d34c9daSPatrick Kelsey if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) 13641d34c9daSPatrick Kelsey return (0); 13651d34c9daSPatrick Kelsey 13661d34c9daSPatrick Kelsey return (*(int *)ret_item->data); 13671d34c9daSPatrick Kelsey } 13681d34c9daSPatrick Kelsey 13693b3a8eb9SGleb Smirnoff struct node_host * 13701d34c9daSPatrick Kelsey ifa_exists(char *ifa_name) 13713b3a8eb9SGleb Smirnoff { 13723b3a8eb9SGleb Smirnoff struct node_host *n; 13733b3a8eb9SGleb Smirnoff 13743b3a8eb9SGleb Smirnoff if (iftab == NULL) 13753b3a8eb9SGleb Smirnoff ifa_load(); 13763b3a8eb9SGleb Smirnoff 13771d34c9daSPatrick Kelsey /* check whether this is a group */ 13781d34c9daSPatrick Kelsey if (is_a_group(ifa_name)) { 13793b3a8eb9SGleb Smirnoff /* fake a node_host */ 13803b3a8eb9SGleb Smirnoff if ((n = calloc(1, sizeof(*n))) == NULL) 13813b3a8eb9SGleb Smirnoff err(1, "calloc"); 13823b3a8eb9SGleb Smirnoff if ((n->ifname = strdup(ifa_name)) == NULL) 13833b3a8eb9SGleb Smirnoff err(1, "strdup"); 13843b3a8eb9SGleb Smirnoff return (n); 13853b3a8eb9SGleb Smirnoff } 13863b3a8eb9SGleb Smirnoff 13873b3a8eb9SGleb Smirnoff for (n = iftab; n; n = n->next) { 13883b3a8eb9SGleb Smirnoff if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) 13893b3a8eb9SGleb Smirnoff return (n); 13903b3a8eb9SGleb Smirnoff } 13913b3a8eb9SGleb Smirnoff 13923b3a8eb9SGleb Smirnoff return (NULL); 13933b3a8eb9SGleb Smirnoff } 13943b3a8eb9SGleb Smirnoff 13950c156a3cSKristof Provost static struct node_host * 13960c156a3cSKristof Provost if_lookup(char *if_name) 13970c156a3cSKristof Provost { 13980c156a3cSKristof Provost struct node_host *p, *n; 13990c156a3cSKristof Provost 14000c156a3cSKristof Provost for (p = iftab; p; p = p->next) { 14010c156a3cSKristof Provost if (! strcmp(if_name, p->ifname)) { 14020c156a3cSKristof Provost n = calloc(1, sizeof(struct node_host)); 14030c156a3cSKristof Provost bcopy(p, n, sizeof(struct node_host)); 14040c156a3cSKristof Provost 14050c156a3cSKristof Provost n->next = NULL; 14060c156a3cSKristof Provost n->tail = n; 14070c156a3cSKristof Provost 14080c156a3cSKristof Provost return (n); 14090c156a3cSKristof Provost } 14100c156a3cSKristof Provost } 14110c156a3cSKristof Provost 14120c156a3cSKristof Provost return (NULL); 14130c156a3cSKristof Provost } 14140c156a3cSKristof Provost 14153b3a8eb9SGleb Smirnoff struct node_host * 14161d34c9daSPatrick Kelsey ifa_grouplookup(char *ifa_name, int flags) 14173b3a8eb9SGleb Smirnoff { 14183b3a8eb9SGleb Smirnoff struct ifg_req *ifg; 14193b3a8eb9SGleb Smirnoff struct ifgroupreq ifgr; 14203b3a8eb9SGleb Smirnoff int s, len; 14213b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 14223b3a8eb9SGleb Smirnoff 14231d34c9daSPatrick Kelsey s = get_query_socket(); 14241d34c9daSPatrick Kelsey len = is_a_group(ifa_name); 14251d34c9daSPatrick Kelsey if (len == 0) 14261d34c9daSPatrick Kelsey return (NULL); 14273b3a8eb9SGleb Smirnoff bzero(&ifgr, sizeof(ifgr)); 14283b3a8eb9SGleb Smirnoff strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); 14294c8fb952SKristof Provost ifgr.ifgr_len = len; 14303b3a8eb9SGleb Smirnoff if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 14313b3a8eb9SGleb Smirnoff err(1, "calloc"); 14323b3a8eb9SGleb Smirnoff if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 14333b3a8eb9SGleb Smirnoff err(1, "SIOCGIFGMEMB"); 14343b3a8eb9SGleb Smirnoff 14353b3a8eb9SGleb Smirnoff for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req); 14363b3a8eb9SGleb Smirnoff ifg++) { 14373b3a8eb9SGleb Smirnoff len -= sizeof(struct ifg_req); 14380c156a3cSKristof Provost if ((n = if_lookup(ifg->ifgrq_member)) == NULL) 14393b3a8eb9SGleb Smirnoff continue; 14403b3a8eb9SGleb Smirnoff if (h == NULL) 14413b3a8eb9SGleb Smirnoff h = n; 14423b3a8eb9SGleb Smirnoff else { 14433b3a8eb9SGleb Smirnoff h->tail->next = n; 14443b3a8eb9SGleb Smirnoff h->tail = n->tail; 14453b3a8eb9SGleb Smirnoff } 14463b3a8eb9SGleb Smirnoff } 14473b3a8eb9SGleb Smirnoff free(ifgr.ifgr_groups); 14483b3a8eb9SGleb Smirnoff 14493b3a8eb9SGleb Smirnoff return (h); 14503b3a8eb9SGleb Smirnoff } 14513b3a8eb9SGleb Smirnoff 14523b3a8eb9SGleb Smirnoff struct node_host * 14531d34c9daSPatrick Kelsey ifa_lookup(char *ifa_name, int flags) 14543b3a8eb9SGleb Smirnoff { 14553b3a8eb9SGleb Smirnoff struct node_host *p = NULL, *h = NULL, *n = NULL; 14563b3a8eb9SGleb Smirnoff int got4 = 0, got6 = 0; 14573b3a8eb9SGleb Smirnoff const char *last_if = NULL; 14583b3a8eb9SGleb Smirnoff 14598fd675d8SKristof Provost /* first load iftab and isgroup_map */ 14608fd675d8SKristof Provost if (iftab == NULL) 14618fd675d8SKristof Provost ifa_load(); 14628fd675d8SKristof Provost 14633b3a8eb9SGleb Smirnoff if ((h = ifa_grouplookup(ifa_name, flags)) != NULL) 14643b3a8eb9SGleb Smirnoff return (h); 14653b3a8eb9SGleb Smirnoff 14663b3a8eb9SGleb Smirnoff if (!strncmp(ifa_name, "self", IFNAMSIZ)) 14673b3a8eb9SGleb Smirnoff ifa_name = NULL; 14683b3a8eb9SGleb Smirnoff 14693b3a8eb9SGleb Smirnoff for (p = iftab; p; p = p->next) { 14703b3a8eb9SGleb Smirnoff if (ifa_skip_if(ifa_name, p)) 14713b3a8eb9SGleb Smirnoff continue; 14723b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET) 14733b3a8eb9SGleb Smirnoff continue; 14743b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_BROADCAST) && 14753b3a8eb9SGleb Smirnoff !(p->ifa_flags & IFF_BROADCAST)) 14763b3a8eb9SGleb Smirnoff continue; 14773b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_PEER) && 14783b3a8eb9SGleb Smirnoff !(p->ifa_flags & IFF_POINTOPOINT)) 14793b3a8eb9SGleb Smirnoff continue; 14803b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NETWORK) && p->ifindex > 0) 14813b3a8eb9SGleb Smirnoff continue; 14823b3a8eb9SGleb Smirnoff if (last_if == NULL || strcmp(last_if, p->ifname)) 14833b3a8eb9SGleb Smirnoff got4 = got6 = 0; 14843b3a8eb9SGleb Smirnoff last_if = p->ifname; 14853b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET && got4) 14863b3a8eb9SGleb Smirnoff continue; 148799eb0055SKristof Provost if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && 148899eb0055SKristof Provost IN6_IS_ADDR_LINKLOCAL(&p->addr.v.a.addr.v6)) 148999eb0055SKristof Provost continue; 14903b3a8eb9SGleb Smirnoff if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && got6) 14913b3a8eb9SGleb Smirnoff continue; 14923b3a8eb9SGleb Smirnoff if (p->af == AF_INET) 14933b3a8eb9SGleb Smirnoff got4 = 1; 14943b3a8eb9SGleb Smirnoff else 14953b3a8eb9SGleb Smirnoff got6 = 1; 14963b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 14973b3a8eb9SGleb Smirnoff if (n == NULL) 14983b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 14993b3a8eb9SGleb Smirnoff n->af = p->af; 15003b3a8eb9SGleb Smirnoff if (flags & PFI_AFLAG_BROADCAST) 15013b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->bcast, 15023b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 15033b3a8eb9SGleb Smirnoff else if (flags & PFI_AFLAG_PEER) 15043b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->peer, 15053b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 15063b3a8eb9SGleb Smirnoff else 15073b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, 15083b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 15093b3a8eb9SGleb Smirnoff if (flags & PFI_AFLAG_NETWORK) 15103b3a8eb9SGleb Smirnoff set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); 15113b3a8eb9SGleb Smirnoff else { 15123b3a8eb9SGleb Smirnoff if (n->af == AF_INET) { 15133b3a8eb9SGleb Smirnoff if (p->ifa_flags & IFF_LOOPBACK && 15143b3a8eb9SGleb Smirnoff p->ifa_flags & IFF_LINK1) 15153b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.mask, 15163b3a8eb9SGleb Smirnoff &p->addr.v.a.mask, 15173b3a8eb9SGleb Smirnoff sizeof(struct pf_addr)); 15183b3a8eb9SGleb Smirnoff else 15193b3a8eb9SGleb Smirnoff set_ipmask(n, 32); 15203b3a8eb9SGleb Smirnoff } else 15213b3a8eb9SGleb Smirnoff set_ipmask(n, 128); 15223b3a8eb9SGleb Smirnoff } 15233b3a8eb9SGleb Smirnoff n->ifindex = p->ifindex; 15240f9e47a9SKristof Provost n->ifname = strdup(p->ifname); 15253b3a8eb9SGleb Smirnoff 15263b3a8eb9SGleb Smirnoff n->next = NULL; 15273b3a8eb9SGleb Smirnoff n->tail = n; 15283b3a8eb9SGleb Smirnoff if (h == NULL) 15293b3a8eb9SGleb Smirnoff h = n; 15303b3a8eb9SGleb Smirnoff else { 15313b3a8eb9SGleb Smirnoff h->tail->next = n; 15323b3a8eb9SGleb Smirnoff h->tail = n; 15333b3a8eb9SGleb Smirnoff } 15343b3a8eb9SGleb Smirnoff } 15353b3a8eb9SGleb Smirnoff return (h); 15363b3a8eb9SGleb Smirnoff } 15373b3a8eb9SGleb Smirnoff 15383b3a8eb9SGleb Smirnoff int 15393b3a8eb9SGleb Smirnoff ifa_skip_if(const char *filter, struct node_host *p) 15403b3a8eb9SGleb Smirnoff { 15413b3a8eb9SGleb Smirnoff int n; 15423b3a8eb9SGleb Smirnoff 15433b3a8eb9SGleb Smirnoff if (p->af != AF_INET && p->af != AF_INET6) 15443b3a8eb9SGleb Smirnoff return (1); 15453b3a8eb9SGleb Smirnoff if (filter == NULL || !*filter) 15463b3a8eb9SGleb Smirnoff return (0); 15473b3a8eb9SGleb Smirnoff if (!strcmp(p->ifname, filter)) 15483b3a8eb9SGleb Smirnoff return (0); /* exact match */ 15493b3a8eb9SGleb Smirnoff n = strlen(filter); 15503b3a8eb9SGleb Smirnoff if (n < 1 || n >= IFNAMSIZ) 15513b3a8eb9SGleb Smirnoff return (1); /* sanity check */ 15523b3a8eb9SGleb Smirnoff if (filter[n-1] >= '0' && filter[n-1] <= '9') 15533b3a8eb9SGleb Smirnoff return (1); /* only do exact match in that case */ 15543b3a8eb9SGleb Smirnoff if (strncmp(p->ifname, filter, n)) 15553b3a8eb9SGleb Smirnoff return (1); /* prefix doesn't match */ 15563b3a8eb9SGleb Smirnoff return (p->ifname[n] < '0' || p->ifname[n] > '9'); 15573b3a8eb9SGleb Smirnoff } 15583b3a8eb9SGleb Smirnoff 15593b3a8eb9SGleb Smirnoff 15603b3a8eb9SGleb Smirnoff struct node_host * 15613b3a8eb9SGleb Smirnoff host(const char *s) 15623b3a8eb9SGleb Smirnoff { 15633b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 15643b3a8eb9SGleb Smirnoff int mask, v4mask, v6mask, cont = 1; 15653b3a8eb9SGleb Smirnoff char *p, *q, *ps; 15663b3a8eb9SGleb Smirnoff 15673b3a8eb9SGleb Smirnoff if ((p = strrchr(s, '/')) != NULL) { 15683b3a8eb9SGleb Smirnoff mask = strtol(p+1, &q, 0); 15693b3a8eb9SGleb Smirnoff if (!q || *q || mask > 128 || q == (p+1)) { 15703b3a8eb9SGleb Smirnoff fprintf(stderr, "invalid netmask '%s'\n", p); 15713b3a8eb9SGleb Smirnoff return (NULL); 15723b3a8eb9SGleb Smirnoff } 15733b3a8eb9SGleb Smirnoff if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 15743b3a8eb9SGleb Smirnoff err(1, "host: malloc"); 15753b3a8eb9SGleb Smirnoff strlcpy(ps, s, strlen(s) - strlen(p) + 1); 15763b3a8eb9SGleb Smirnoff v4mask = v6mask = mask; 15773b3a8eb9SGleb Smirnoff } else { 15783b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 15793b3a8eb9SGleb Smirnoff err(1, "host: strdup"); 15803b3a8eb9SGleb Smirnoff v4mask = 32; 15813b3a8eb9SGleb Smirnoff v6mask = 128; 15823b3a8eb9SGleb Smirnoff mask = -1; 15833b3a8eb9SGleb Smirnoff } 15843b3a8eb9SGleb Smirnoff 15853b3a8eb9SGleb Smirnoff /* IPv4 address? */ 15863b3a8eb9SGleb Smirnoff if (cont && (h = host_v4(s, mask)) != NULL) 15873b3a8eb9SGleb Smirnoff cont = 0; 15883b3a8eb9SGleb Smirnoff 15893b3a8eb9SGleb Smirnoff /* IPv6 address? */ 15903b3a8eb9SGleb Smirnoff if (cont && (h = host_v6(ps, v6mask)) != NULL) 15913b3a8eb9SGleb Smirnoff cont = 0; 15923b3a8eb9SGleb Smirnoff 1593d2568b02SKristof Provost /* interface with this name exists? */ 1594d2568b02SKristof Provost /* expensive with thousands of interfaces - prioritze IPv4/6 check */ 1595d2568b02SKristof Provost if (cont && (h = host_if(ps, mask)) != NULL) 1596d2568b02SKristof Provost cont = 0; 1597d2568b02SKristof Provost 15983b3a8eb9SGleb Smirnoff /* dns lookup */ 15993b3a8eb9SGleb Smirnoff if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL) 16003b3a8eb9SGleb Smirnoff cont = 0; 16013b3a8eb9SGleb Smirnoff free(ps); 16023b3a8eb9SGleb Smirnoff 16033b3a8eb9SGleb Smirnoff if (h == NULL || cont == 1) { 16043b3a8eb9SGleb Smirnoff fprintf(stderr, "no IP address found for %s\n", s); 16053b3a8eb9SGleb Smirnoff return (NULL); 16063b3a8eb9SGleb Smirnoff } 16073b3a8eb9SGleb Smirnoff return (h); 16083b3a8eb9SGleb Smirnoff } 16093b3a8eb9SGleb Smirnoff 16103b3a8eb9SGleb Smirnoff struct node_host * 16113b3a8eb9SGleb Smirnoff host_if(const char *s, int mask) 16123b3a8eb9SGleb Smirnoff { 16133b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 16143b3a8eb9SGleb Smirnoff char *p, *ps; 16153b3a8eb9SGleb Smirnoff int flags = 0; 16163b3a8eb9SGleb Smirnoff 16173b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 16183b3a8eb9SGleb Smirnoff err(1, "host_if: strdup"); 16193b3a8eb9SGleb Smirnoff while ((p = strrchr(ps, ':')) != NULL) { 16203b3a8eb9SGleb Smirnoff if (!strcmp(p+1, "network")) 16213b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NETWORK; 16223b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "broadcast")) 16233b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_BROADCAST; 16243b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "peer")) 16253b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_PEER; 16263b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "0")) 16273b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NOALIAS; 16283b3a8eb9SGleb Smirnoff else { 16293b3a8eb9SGleb Smirnoff free(ps); 16303b3a8eb9SGleb Smirnoff return (NULL); 16313b3a8eb9SGleb Smirnoff } 16323b3a8eb9SGleb Smirnoff *p = '\0'; 16333b3a8eb9SGleb Smirnoff } 16343b3a8eb9SGleb Smirnoff if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */ 16353b3a8eb9SGleb Smirnoff fprintf(stderr, "illegal combination of interface modifiers\n"); 16363b3a8eb9SGleb Smirnoff free(ps); 16373b3a8eb9SGleb Smirnoff return (NULL); 16383b3a8eb9SGleb Smirnoff } 16393b3a8eb9SGleb Smirnoff if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) { 16403b3a8eb9SGleb Smirnoff fprintf(stderr, "network or broadcast lookup, but " 16413b3a8eb9SGleb Smirnoff "extra netmask given\n"); 16423b3a8eb9SGleb Smirnoff free(ps); 16433b3a8eb9SGleb Smirnoff return (NULL); 16443b3a8eb9SGleb Smirnoff } 16453b3a8eb9SGleb Smirnoff if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) { 16463b3a8eb9SGleb Smirnoff /* interface with this name exists */ 16473b3a8eb9SGleb Smirnoff h = ifa_lookup(ps, flags); 16483b3a8eb9SGleb Smirnoff for (n = h; n != NULL && mask > -1; n = n->next) 16493b3a8eb9SGleb Smirnoff set_ipmask(n, mask); 16503b3a8eb9SGleb Smirnoff } 16513b3a8eb9SGleb Smirnoff 16523b3a8eb9SGleb Smirnoff free(ps); 16533b3a8eb9SGleb Smirnoff return (h); 16543b3a8eb9SGleb Smirnoff } 16553b3a8eb9SGleb Smirnoff 16563b3a8eb9SGleb Smirnoff struct node_host * 16573b3a8eb9SGleb Smirnoff host_v4(const char *s, int mask) 16583b3a8eb9SGleb Smirnoff { 16593b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 16603b3a8eb9SGleb Smirnoff struct in_addr ina; 16613b3a8eb9SGleb Smirnoff int bits = 32; 16623b3a8eb9SGleb Smirnoff 16633b3a8eb9SGleb Smirnoff memset(&ina, 0, sizeof(struct in_addr)); 16643b3a8eb9SGleb Smirnoff if (strrchr(s, '/') != NULL) { 16653b3a8eb9SGleb Smirnoff if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 16663b3a8eb9SGleb Smirnoff return (NULL); 16673b3a8eb9SGleb Smirnoff } else { 16683b3a8eb9SGleb Smirnoff if (inet_pton(AF_INET, s, &ina) != 1) 16693b3a8eb9SGleb Smirnoff return (NULL); 16703b3a8eb9SGleb Smirnoff } 16713b3a8eb9SGleb Smirnoff 16723b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(struct node_host)); 16733b3a8eb9SGleb Smirnoff if (h == NULL) 16743b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 16753b3a8eb9SGleb Smirnoff h->ifname = NULL; 16763b3a8eb9SGleb Smirnoff h->af = AF_INET; 16773b3a8eb9SGleb Smirnoff h->addr.v.a.addr.addr32[0] = ina.s_addr; 16783b3a8eb9SGleb Smirnoff set_ipmask(h, bits); 16793b3a8eb9SGleb Smirnoff h->next = NULL; 16803b3a8eb9SGleb Smirnoff h->tail = h; 16813b3a8eb9SGleb Smirnoff 16823b3a8eb9SGleb Smirnoff return (h); 16833b3a8eb9SGleb Smirnoff } 16843b3a8eb9SGleb Smirnoff 16853b3a8eb9SGleb Smirnoff struct node_host * 16863b3a8eb9SGleb Smirnoff host_v6(const char *s, int mask) 16873b3a8eb9SGleb Smirnoff { 16883b3a8eb9SGleb Smirnoff struct addrinfo hints, *res; 16893b3a8eb9SGleb Smirnoff struct node_host *h = NULL; 16903b3a8eb9SGleb Smirnoff 16913b3a8eb9SGleb Smirnoff memset(&hints, 0, sizeof(hints)); 16923b3a8eb9SGleb Smirnoff hints.ai_family = AF_INET6; 16933b3a8eb9SGleb Smirnoff hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 16943b3a8eb9SGleb Smirnoff hints.ai_flags = AI_NUMERICHOST; 16953b3a8eb9SGleb Smirnoff if (getaddrinfo(s, "0", &hints, &res) == 0) { 16963b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(struct node_host)); 16973b3a8eb9SGleb Smirnoff if (h == NULL) 16983b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 16993b3a8eb9SGleb Smirnoff h->ifname = NULL; 17003b3a8eb9SGleb Smirnoff h->af = AF_INET6; 17013b3a8eb9SGleb Smirnoff memcpy(&h->addr.v.a.addr, 17023b3a8eb9SGleb Smirnoff &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 17033b3a8eb9SGleb Smirnoff sizeof(h->addr.v.a.addr)); 17043b3a8eb9SGleb Smirnoff h->ifindex = 17053b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 17063b3a8eb9SGleb Smirnoff set_ipmask(h, mask); 17073b3a8eb9SGleb Smirnoff freeaddrinfo(res); 17083b3a8eb9SGleb Smirnoff h->next = NULL; 17093b3a8eb9SGleb Smirnoff h->tail = h; 17103b3a8eb9SGleb Smirnoff } 17113b3a8eb9SGleb Smirnoff 17123b3a8eb9SGleb Smirnoff return (h); 17133b3a8eb9SGleb Smirnoff } 17143b3a8eb9SGleb Smirnoff 17153b3a8eb9SGleb Smirnoff struct node_host * 17163b3a8eb9SGleb Smirnoff host_dns(const char *s, int v4mask, int v6mask) 17173b3a8eb9SGleb Smirnoff { 17183b3a8eb9SGleb Smirnoff struct addrinfo hints, *res0, *res; 17193b3a8eb9SGleb Smirnoff struct node_host *n, *h = NULL; 17203b3a8eb9SGleb Smirnoff int error, noalias = 0; 17213b3a8eb9SGleb Smirnoff int got4 = 0, got6 = 0; 17223b3a8eb9SGleb Smirnoff char *p, *ps; 17233b3a8eb9SGleb Smirnoff 17243b3a8eb9SGleb Smirnoff if ((ps = strdup(s)) == NULL) 17253b3a8eb9SGleb Smirnoff err(1, "host_dns: strdup"); 17263b3a8eb9SGleb Smirnoff if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) { 17273b3a8eb9SGleb Smirnoff noalias = 1; 17283b3a8eb9SGleb Smirnoff *p = '\0'; 17293b3a8eb9SGleb Smirnoff } 17303b3a8eb9SGleb Smirnoff memset(&hints, 0, sizeof(hints)); 17313b3a8eb9SGleb Smirnoff hints.ai_family = PF_UNSPEC; 17323b3a8eb9SGleb Smirnoff hints.ai_socktype = SOCK_STREAM; /* DUMMY */ 17333b3a8eb9SGleb Smirnoff error = getaddrinfo(ps, NULL, &hints, &res0); 17343b3a8eb9SGleb Smirnoff if (error) { 17353b3a8eb9SGleb Smirnoff free(ps); 17363b3a8eb9SGleb Smirnoff return (h); 17373b3a8eb9SGleb Smirnoff } 17383b3a8eb9SGleb Smirnoff 17393b3a8eb9SGleb Smirnoff for (res = res0; res; res = res->ai_next) { 17403b3a8eb9SGleb Smirnoff if (res->ai_family != AF_INET && 17413b3a8eb9SGleb Smirnoff res->ai_family != AF_INET6) 17423b3a8eb9SGleb Smirnoff continue; 17433b3a8eb9SGleb Smirnoff if (noalias) { 17443b3a8eb9SGleb Smirnoff if (res->ai_family == AF_INET) { 17453b3a8eb9SGleb Smirnoff if (got4) 17463b3a8eb9SGleb Smirnoff continue; 17473b3a8eb9SGleb Smirnoff got4 = 1; 17483b3a8eb9SGleb Smirnoff } else { 17493b3a8eb9SGleb Smirnoff if (got6) 17503b3a8eb9SGleb Smirnoff continue; 17513b3a8eb9SGleb Smirnoff got6 = 1; 17523b3a8eb9SGleb Smirnoff } 17533b3a8eb9SGleb Smirnoff } 17543b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_host)); 17553b3a8eb9SGleb Smirnoff if (n == NULL) 17563b3a8eb9SGleb Smirnoff err(1, "host_dns: calloc"); 17573b3a8eb9SGleb Smirnoff n->ifname = NULL; 17583b3a8eb9SGleb Smirnoff n->af = res->ai_family; 17593b3a8eb9SGleb Smirnoff if (res->ai_family == AF_INET) { 17603b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, 17613b3a8eb9SGleb Smirnoff &((struct sockaddr_in *) 17623b3a8eb9SGleb Smirnoff res->ai_addr)->sin_addr.s_addr, 17633b3a8eb9SGleb Smirnoff sizeof(struct in_addr)); 17643b3a8eb9SGleb Smirnoff set_ipmask(n, v4mask); 17653b3a8eb9SGleb Smirnoff } else { 17663b3a8eb9SGleb Smirnoff memcpy(&n->addr.v.a.addr, 17673b3a8eb9SGleb Smirnoff &((struct sockaddr_in6 *) 17683b3a8eb9SGleb Smirnoff res->ai_addr)->sin6_addr.s6_addr, 17693b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 17703b3a8eb9SGleb Smirnoff n->ifindex = 17713b3a8eb9SGleb Smirnoff ((struct sockaddr_in6 *) 17723b3a8eb9SGleb Smirnoff res->ai_addr)->sin6_scope_id; 17733b3a8eb9SGleb Smirnoff set_ipmask(n, v6mask); 17743b3a8eb9SGleb Smirnoff } 17753b3a8eb9SGleb Smirnoff n->next = NULL; 17763b3a8eb9SGleb Smirnoff n->tail = n; 17773b3a8eb9SGleb Smirnoff if (h == NULL) 17783b3a8eb9SGleb Smirnoff h = n; 17793b3a8eb9SGleb Smirnoff else { 17803b3a8eb9SGleb Smirnoff h->tail->next = n; 17813b3a8eb9SGleb Smirnoff h->tail = n; 17823b3a8eb9SGleb Smirnoff } 17833b3a8eb9SGleb Smirnoff } 17843b3a8eb9SGleb Smirnoff freeaddrinfo(res0); 17853b3a8eb9SGleb Smirnoff free(ps); 17863b3a8eb9SGleb Smirnoff 17873b3a8eb9SGleb Smirnoff return (h); 17883b3a8eb9SGleb Smirnoff } 17893b3a8eb9SGleb Smirnoff 17903b3a8eb9SGleb Smirnoff /* 17913b3a8eb9SGleb Smirnoff * convert a hostname to a list of addresses and put them in the given buffer. 17923b3a8eb9SGleb Smirnoff * test: 17933b3a8eb9SGleb Smirnoff * if set to 1, only simple addresses are accepted (no netblock, no "!"). 17943b3a8eb9SGleb Smirnoff */ 17953b3a8eb9SGleb Smirnoff int 17963b3a8eb9SGleb Smirnoff append_addr(struct pfr_buffer *b, char *s, int test) 17973b3a8eb9SGleb Smirnoff { 17983b3a8eb9SGleb Smirnoff char *r; 17993b3a8eb9SGleb Smirnoff struct node_host *h, *n; 18003b3a8eb9SGleb Smirnoff int rv, not = 0; 18013b3a8eb9SGleb Smirnoff 18023b3a8eb9SGleb Smirnoff for (r = s; *r == '!'; r++) 18033b3a8eb9SGleb Smirnoff not = !not; 18043b3a8eb9SGleb Smirnoff if ((n = host(r)) == NULL) { 18053b3a8eb9SGleb Smirnoff errno = 0; 18063b3a8eb9SGleb Smirnoff return (-1); 18073b3a8eb9SGleb Smirnoff } 18083b3a8eb9SGleb Smirnoff rv = append_addr_host(b, n, test, not); 18093b3a8eb9SGleb Smirnoff do { 18103b3a8eb9SGleb Smirnoff h = n; 18113b3a8eb9SGleb Smirnoff n = n->next; 18123b3a8eb9SGleb Smirnoff free(h); 18133b3a8eb9SGleb Smirnoff } while (n != NULL); 18143b3a8eb9SGleb Smirnoff return (rv); 18153b3a8eb9SGleb Smirnoff } 18163b3a8eb9SGleb Smirnoff 18173b3a8eb9SGleb Smirnoff /* 18183b3a8eb9SGleb Smirnoff * same as previous function, but with a pre-parsed input and the ability 18193b3a8eb9SGleb Smirnoff * to "negate" the result. Does not free the node_host list. 18203b3a8eb9SGleb Smirnoff * not: 18213b3a8eb9SGleb Smirnoff * setting it to 1 is equivalent to adding "!" in front of parameter s. 18223b3a8eb9SGleb Smirnoff */ 18233b3a8eb9SGleb Smirnoff int 18243b3a8eb9SGleb Smirnoff append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not) 18253b3a8eb9SGleb Smirnoff { 18263b3a8eb9SGleb Smirnoff int bits; 18273b3a8eb9SGleb Smirnoff struct pfr_addr addr; 18283b3a8eb9SGleb Smirnoff 18293b3a8eb9SGleb Smirnoff do { 18303b3a8eb9SGleb Smirnoff bzero(&addr, sizeof(addr)); 18313b3a8eb9SGleb Smirnoff addr.pfra_not = n->not ^ not; 18323b3a8eb9SGleb Smirnoff addr.pfra_af = n->af; 18333b3a8eb9SGleb Smirnoff addr.pfra_net = unmask(&n->addr.v.a.mask, n->af); 18343b3a8eb9SGleb Smirnoff switch (n->af) { 18353b3a8eb9SGleb Smirnoff case AF_INET: 18363b3a8eb9SGleb Smirnoff addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0]; 18373b3a8eb9SGleb Smirnoff bits = 32; 18383b3a8eb9SGleb Smirnoff break; 18393b3a8eb9SGleb Smirnoff case AF_INET6: 18403b3a8eb9SGleb Smirnoff memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6, 18413b3a8eb9SGleb Smirnoff sizeof(struct in6_addr)); 18423b3a8eb9SGleb Smirnoff bits = 128; 18433b3a8eb9SGleb Smirnoff break; 18443b3a8eb9SGleb Smirnoff default: 18453b3a8eb9SGleb Smirnoff errno = EINVAL; 18463b3a8eb9SGleb Smirnoff return (-1); 18473b3a8eb9SGleb Smirnoff } 18483b3a8eb9SGleb Smirnoff if ((test && (not || addr.pfra_net != bits)) || 18493b3a8eb9SGleb Smirnoff addr.pfra_net > bits) { 18503b3a8eb9SGleb Smirnoff errno = EINVAL; 18513b3a8eb9SGleb Smirnoff return (-1); 18523b3a8eb9SGleb Smirnoff } 18533b3a8eb9SGleb Smirnoff if (pfr_buf_add(b, &addr)) 18543b3a8eb9SGleb Smirnoff return (-1); 18553b3a8eb9SGleb Smirnoff } while ((n = n->next) != NULL); 18563b3a8eb9SGleb Smirnoff 18573b3a8eb9SGleb Smirnoff return (0); 18583b3a8eb9SGleb Smirnoff } 18593b3a8eb9SGleb Smirnoff 18603b3a8eb9SGleb Smirnoff int 18613b3a8eb9SGleb Smirnoff pfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor) 18623b3a8eb9SGleb Smirnoff { 18633b3a8eb9SGleb Smirnoff struct pfioc_trans_e trans; 18643b3a8eb9SGleb Smirnoff 18653b3a8eb9SGleb Smirnoff bzero(&trans, sizeof(trans)); 18663b3a8eb9SGleb Smirnoff trans.rs_num = rs_num; 18673b3a8eb9SGleb Smirnoff if (strlcpy(trans.anchor, anchor, 18683b3a8eb9SGleb Smirnoff sizeof(trans.anchor)) >= sizeof(trans.anchor)) 18693b3a8eb9SGleb Smirnoff errx(1, "pfctl_add_trans: strlcpy"); 18703b3a8eb9SGleb Smirnoff 18713b3a8eb9SGleb Smirnoff return pfr_buf_add(buf, &trans); 18723b3a8eb9SGleb Smirnoff } 18733b3a8eb9SGleb Smirnoff 18743b3a8eb9SGleb Smirnoff u_int32_t 18753b3a8eb9SGleb Smirnoff pfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor) 18763b3a8eb9SGleb Smirnoff { 18773b3a8eb9SGleb Smirnoff struct pfioc_trans_e *p; 18783b3a8eb9SGleb Smirnoff 18793b3a8eb9SGleb Smirnoff PFRB_FOREACH(p, buf) 18803b3a8eb9SGleb Smirnoff if (rs_num == p->rs_num && !strcmp(anchor, p->anchor)) 18813b3a8eb9SGleb Smirnoff return (p->ticket); 18823b3a8eb9SGleb Smirnoff errx(1, "pfctl_get_ticket: assertion failed"); 18833b3a8eb9SGleb Smirnoff } 18843b3a8eb9SGleb Smirnoff 18853b3a8eb9SGleb Smirnoff int 18863b3a8eb9SGleb Smirnoff pfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from) 18873b3a8eb9SGleb Smirnoff { 18883b3a8eb9SGleb Smirnoff struct pfioc_trans trans; 18893b3a8eb9SGleb Smirnoff 18903b3a8eb9SGleb Smirnoff bzero(&trans, sizeof(trans)); 18913b3a8eb9SGleb Smirnoff trans.size = buf->pfrb_size - from; 18923b3a8eb9SGleb Smirnoff trans.esize = sizeof(struct pfioc_trans_e); 18933b3a8eb9SGleb Smirnoff trans.array = ((struct pfioc_trans_e *)buf->pfrb_caddr) + from; 18943b3a8eb9SGleb Smirnoff return ioctl(dev, cmd, &trans); 18953b3a8eb9SGleb Smirnoff } 1896