1*edbe3066Sdhartmei /* $OpenBSD: pfctl_parser.c,v 1.140 2003/02/08 20:13:20 dhartmei Exp $ */ 214a9b182Skjell 314a9b182Skjell /* 4fd3c3a0cSderaadt * Copyright (c) 2001 Daniel Hartmeier 514a9b182Skjell * All rights reserved. 614a9b182Skjell * 714a9b182Skjell * Redistribution and use in source and binary forms, with or without 814a9b182Skjell * modification, are permitted provided that the following conditions 914a9b182Skjell * are met: 1014a9b182Skjell * 1114a9b182Skjell * - Redistributions of source code must retain the above copyright 1214a9b182Skjell * notice, this list of conditions and the following disclaimer. 1314a9b182Skjell * - Redistributions in binary form must reproduce the above 1414a9b182Skjell * copyright notice, this list of conditions and the following 1514a9b182Skjell * disclaimer in the documentation and/or other materials provided 1614a9b182Skjell * with the distribution. 1714a9b182Skjell * 1814a9b182Skjell * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1914a9b182Skjell * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2014a9b182Skjell * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2114a9b182Skjell * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 225974bd37Sdhartmei * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2314a9b182Skjell * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2414a9b182Skjell * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2514a9b182Skjell * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 2614a9b182Skjell * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2714a9b182Skjell * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 2814a9b182Skjell * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2914a9b182Skjell * POSSIBILITY OF SUCH DAMAGE. 3014a9b182Skjell * 3114a9b182Skjell */ 3214a9b182Skjell 33252d784aSderaadt #include <sys/types.h> 34252d784aSderaadt #include <sys/socket.h> 35252d784aSderaadt #include <net/if.h> 36252d784aSderaadt #include <netinet/in.h> 376329fa59Sderaadt #include <netinet/in_systm.h> 386329fa59Sderaadt #include <netinet/ip.h> 396329fa59Sderaadt #include <netinet/ip_icmp.h> 4030620b12Sfrantzen #include <netinet/icmp6.h> 41252d784aSderaadt #include <net/pfvar.h> 429f13c6caSmillert #include <arpa/inet.h> 43252d784aSderaadt 4414a9b182Skjell #include <stdio.h> 4514a9b182Skjell #include <stdlib.h> 4614a9b182Skjell #include <string.h> 4714a9b182Skjell #include <ctype.h> 4814a9b182Skjell #include <netdb.h> 496329fa59Sderaadt #include <stdarg.h> 506329fa59Sderaadt #include <errno.h> 51ff352a37Smarkus #include <err.h> 5294e9410bShenning #include <ifaddrs.h> 5314a9b182Skjell 5414a9b182Skjell #include "pfctl_parser.h" 55eb824e11Sderaadt #include "pfctl.h" 5614a9b182Skjell 575d9ac2dcSdhartmei void print_op (u_int8_t, const char *, const char *); 5881a15e5dSderaadt void print_port (u_int8_t, u_int16_t, u_int16_t, char *); 595d9ac2dcSdhartmei void print_uid (u_int8_t, uid_t, uid_t, const char *); 60c16ab608Sdhartmei void print_gid (u_int8_t, gid_t, gid_t, const char *); 6181a15e5dSderaadt void print_flags (u_int8_t); 6215e76891Sdhartmei void print_fromto(struct pf_rule_addr *, struct pf_rule_addr *, 6344f5ed0aScedric u_int8_t, u_int8_t, int); 6414a9b182Skjell 65f2370d27Shenning struct node_host *host_if(const char *, int); 666cba701cShenning struct node_host *host_v4(const char *); 67f2370d27Shenning struct node_host *host_v6(const char *, int); 68f2370d27Shenning struct node_host *host_dns(const char *, int, int); 692a6c1abaShenning 70bc795af0Shugh char *tcpflags = "FSRPAUEW"; 7114a9b182Skjell 727d27d81aSdhartmei static const struct icmptypeent icmp_type[] = { 73082ebc44Swilfried { "echoreq", ICMP_ECHO }, 74082ebc44Swilfried { "echorep", ICMP_ECHOREPLY }, 75082ebc44Swilfried { "unreach", ICMP_UNREACH }, 76082ebc44Swilfried { "squench", ICMP_SOURCEQUENCH }, 77082ebc44Swilfried { "redir", ICMP_REDIRECT }, 78082ebc44Swilfried { "althost", ICMP_ALTHOSTADDR }, 79082ebc44Swilfried { "routeradv", ICMP_ROUTERADVERT }, 80082ebc44Swilfried { "routersol", ICMP_ROUTERSOLICIT }, 81082ebc44Swilfried { "timex", ICMP_TIMXCEED }, 82082ebc44Swilfried { "paramprob", ICMP_PARAMPROB }, 83082ebc44Swilfried { "timereq", ICMP_TSTAMP }, 84082ebc44Swilfried { "timerep", ICMP_TSTAMPREPLY }, 85082ebc44Swilfried { "inforeq", ICMP_IREQ }, 86082ebc44Swilfried { "inforep", ICMP_IREQREPLY }, 87082ebc44Swilfried { "maskreq", ICMP_MASKREQ }, 8802cbcc9eSwilfried { "maskrep", ICMP_MASKREPLY }, 8902cbcc9eSwilfried { "trace", ICMP_TRACEROUTE }, 9002cbcc9eSwilfried { "dataconv", ICMP_DATACONVERR }, 9102cbcc9eSwilfried { "mobredir", ICMP_MOBILE_REDIRECT }, 9202cbcc9eSwilfried { "ipv6-where", ICMP_IPV6_WHEREAREYOU }, 9302cbcc9eSwilfried { "ipv6-here", ICMP_IPV6_IAMHERE }, 9402cbcc9eSwilfried { "mobregreq", ICMP_MOBILE_REGREQUEST }, 9502cbcc9eSwilfried { "mobregrep", ICMP_MOBILE_REGREPLY }, 9602cbcc9eSwilfried { "skip", ICMP_SKIP }, 9702cbcc9eSwilfried { "photuris", ICMP_PHOTURIS } 98082ebc44Swilfried }; 99082ebc44Swilfried 1007d27d81aSdhartmei static const struct icmptypeent icmp6_type[] = { 10130620b12Sfrantzen { "unreach", ICMP6_DST_UNREACH }, 10230620b12Sfrantzen { "toobig", ICMP6_PACKET_TOO_BIG }, 10330620b12Sfrantzen { "timex", ICMP6_TIME_EXCEEDED }, 10430620b12Sfrantzen { "paramprob", ICMP6_PARAM_PROB }, 10530620b12Sfrantzen { "echoreq", ICMP6_ECHO_REQUEST }, 10630620b12Sfrantzen { "echorep", ICMP6_ECHO_REPLY }, 10730620b12Sfrantzen { "groupqry", ICMP6_MEMBERSHIP_QUERY }, 10830620b12Sfrantzen { "listqry", MLD6_LISTENER_QUERY }, 10930620b12Sfrantzen { "grouprep", ICMP6_MEMBERSHIP_REPORT }, 11030620b12Sfrantzen { "listenrep", MLD6_LISTENER_REPORT }, 11130620b12Sfrantzen { "groupterm", ICMP6_MEMBERSHIP_REDUCTION }, 11230620b12Sfrantzen { "listendone", MLD6_LISTENER_DONE }, 11330620b12Sfrantzen { "routersol", ND_ROUTER_SOLICIT }, 11430620b12Sfrantzen { "routeradv", ND_ROUTER_ADVERT }, 11530620b12Sfrantzen { "neighbrsol", ND_NEIGHBOR_SOLICIT }, 11630620b12Sfrantzen { "neighbradv", ND_NEIGHBOR_ADVERT }, 11730620b12Sfrantzen { "redir", ND_REDIRECT }, 11830620b12Sfrantzen { "routrrenum", ICMP6_ROUTER_RENUMBERING }, 11930620b12Sfrantzen { "wrureq", ICMP6_WRUREQUEST }, 12030620b12Sfrantzen { "wrurep", ICMP6_WRUREPLY }, 12130620b12Sfrantzen { "fqdnreq", ICMP6_FQDN_QUERY }, 12230620b12Sfrantzen { "fqdnrep", ICMP6_FQDN_REPLY }, 12330620b12Sfrantzen { "niqry", ICMP6_NI_QUERY }, 12430620b12Sfrantzen { "nirep", ICMP6_NI_REPLY }, 12530620b12Sfrantzen { "mtraceresp", MLD6_MTRACE_RESP }, 12630620b12Sfrantzen { "mtrace", MLD6_MTRACE } 12730620b12Sfrantzen }; 12830620b12Sfrantzen 1297d27d81aSdhartmei static const struct icmpcodeent icmp_code[] = { 130082ebc44Swilfried { "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET }, 131082ebc44Swilfried { "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST }, 132082ebc44Swilfried { "proto-unr", ICMP_UNREACH, ICMP_UNREACH_PROTOCOL }, 133082ebc44Swilfried { "port-unr", ICMP_UNREACH, ICMP_UNREACH_PORT }, 134082ebc44Swilfried { "needfrag", ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG }, 135082ebc44Swilfried { "srcfail", ICMP_UNREACH, ICMP_UNREACH_SRCFAIL }, 136082ebc44Swilfried { "net-unk", ICMP_UNREACH, ICMP_UNREACH_NET_UNKNOWN }, 137082ebc44Swilfried { "host-unk", ICMP_UNREACH, ICMP_UNREACH_HOST_UNKNOWN }, 138082ebc44Swilfried { "isolate", ICMP_UNREACH, ICMP_UNREACH_ISOLATED }, 139082ebc44Swilfried { "net-prohib", ICMP_UNREACH, ICMP_UNREACH_NET_PROHIB }, 140082ebc44Swilfried { "host-prohib", ICMP_UNREACH, ICMP_UNREACH_HOST_PROHIB }, 141082ebc44Swilfried { "net-tos", ICMP_UNREACH, ICMP_UNREACH_TOSNET }, 142082ebc44Swilfried { "host-tos", ICMP_UNREACH, ICMP_UNREACH_TOSHOST }, 143082ebc44Swilfried { "filter-prohib", ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB }, 144082ebc44Swilfried { "host-preced", ICMP_UNREACH, ICMP_UNREACH_HOST_PRECEDENCE }, 145082ebc44Swilfried { "cutoff-preced", ICMP_UNREACH, ICMP_UNREACH_PRECEDENCE_CUTOFF }, 146082ebc44Swilfried { "redir-net", ICMP_REDIRECT, ICMP_REDIRECT_NET }, 147082ebc44Swilfried { "redir-host", ICMP_REDIRECT, ICMP_REDIRECT_HOST }, 148082ebc44Swilfried { "redir-tos-net", ICMP_REDIRECT, ICMP_REDIRECT_TOSNET }, 149082ebc44Swilfried { "redir-tos-host", ICMP_REDIRECT, ICMP_REDIRECT_TOSHOST }, 15002cbcc9eSwilfried { "normal-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL }, 15102cbcc9eSwilfried { "common-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON }, 152082ebc44Swilfried { "transit", ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS }, 153082ebc44Swilfried { "reassemb", ICMP_TIMXCEED, ICMP_TIMXCEED_REASS }, 154082ebc44Swilfried { "badhead", ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR }, 155082ebc44Swilfried { "optmiss", ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT }, 15602cbcc9eSwilfried { "badlen", ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH }, 15702cbcc9eSwilfried { "unknown-ind", ICMP_PHOTURIS, ICMP_PHOTURIS_UNKNOWN_INDEX }, 15802cbcc9eSwilfried { "auth-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_AUTH_FAILED }, 15902cbcc9eSwilfried { "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED } 160082ebc44Swilfried }; 161082ebc44Swilfried 1627d27d81aSdhartmei static const struct icmpcodeent icmp6_code[] = { 1631d32ee3bSdhartmei { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN }, 1641d32ee3bSdhartmei { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE }, 16530620b12Sfrantzen { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR }, 16630620b12Sfrantzen { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE }, 16730620b12Sfrantzen { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR }, 16830620b12Sfrantzen { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT }, 16930620b12Sfrantzen { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT }, 17030620b12Sfrantzen { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY }, 17130620b12Sfrantzen { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER }, 17230620b12Sfrantzen { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER }, 17330620b12Sfrantzen { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK }, 17430620b12Sfrantzen { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER } 17530620b12Sfrantzen }; 17630620b12Sfrantzen 177d593fb91Sdrahn const struct pf_timeout pf_timeouts[] = { 178d593fb91Sdrahn { "tcp.first", PFTM_TCP_FIRST_PACKET }, 179d593fb91Sdrahn { "tcp.opening", PFTM_TCP_OPENING }, 180d593fb91Sdrahn { "tcp.established", PFTM_TCP_ESTABLISHED }, 181d593fb91Sdrahn { "tcp.closing", PFTM_TCP_CLOSING }, 182d593fb91Sdrahn { "tcp.finwait", PFTM_TCP_FIN_WAIT }, 183d593fb91Sdrahn { "tcp.closed", PFTM_TCP_CLOSED }, 184d593fb91Sdrahn { "udp.first", PFTM_UDP_FIRST_PACKET }, 185d593fb91Sdrahn { "udp.single", PFTM_UDP_SINGLE }, 186d593fb91Sdrahn { "udp.multiple", PFTM_UDP_MULTIPLE }, 187d593fb91Sdrahn { "icmp.first", PFTM_ICMP_FIRST_PACKET }, 188d593fb91Sdrahn { "icmp.error", PFTM_ICMP_ERROR_REPLY }, 189d593fb91Sdrahn { "other.first", PFTM_OTHER_FIRST_PACKET }, 190d593fb91Sdrahn { "other.single", PFTM_OTHER_SINGLE }, 191d593fb91Sdrahn { "other.multiple", PFTM_OTHER_MULTIPLE }, 192d593fb91Sdrahn { "frag", PFTM_FRAG }, 193d593fb91Sdrahn { "interval", PFTM_INTERVAL }, 194d593fb91Sdrahn { NULL, 0 } 195d593fb91Sdrahn }; 196d593fb91Sdrahn 1977d27d81aSdhartmei const struct icmptypeent * 198bb9f691eSmcbride geticmptypebynumber(u_int8_t type, sa_family_t af) 199082ebc44Swilfried { 200ed99c291Sderaadt unsigned int i; 201082ebc44Swilfried 202d14c53d7Swilfried if (af != AF_INET6) { 203e4ebe044Shenning for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); 204e4ebe044Shenning i++) { 205082ebc44Swilfried if (type == icmp_type[i].type) 206082ebc44Swilfried return (&icmp_type[i]); 207082ebc44Swilfried } 20830620b12Sfrantzen } else { 20930620b12Sfrantzen for (i=0; i < (sizeof (icmp6_type) / 21030620b12Sfrantzen sizeof(icmp6_type[0])); i++) { 21130620b12Sfrantzen if (type == icmp6_type[i].type) 21230620b12Sfrantzen return (&icmp6_type[i]); 21330620b12Sfrantzen } 21430620b12Sfrantzen } 21530620b12Sfrantzen return (NULL); 216082ebc44Swilfried } 217082ebc44Swilfried 2187d27d81aSdhartmei const struct icmptypeent * 219bb9f691eSmcbride geticmptypebyname(char *w, sa_family_t af) 220082ebc44Swilfried { 221ed99c291Sderaadt unsigned int i; 222082ebc44Swilfried 223d14c53d7Swilfried if (af != AF_INET6) { 224e4ebe044Shenning for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); 225e4ebe044Shenning i++) { 226082ebc44Swilfried if (!strcmp(w, icmp_type[i].name)) 227082ebc44Swilfried return (&icmp_type[i]); 228082ebc44Swilfried } 22930620b12Sfrantzen } else { 23030620b12Sfrantzen for (i=0; i < (sizeof (icmp6_type) / 23130620b12Sfrantzen sizeof(icmp6_type[0])); i++) { 23230620b12Sfrantzen if (!strcmp(w, icmp6_type[i].name)) 23330620b12Sfrantzen return (&icmp6_type[i]); 23430620b12Sfrantzen } 23530620b12Sfrantzen } 23630620b12Sfrantzen return (NULL); 237082ebc44Swilfried } 238082ebc44Swilfried 2397d27d81aSdhartmei const struct icmpcodeent * 240bb9f691eSmcbride geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af) 241082ebc44Swilfried { 242ed99c291Sderaadt unsigned int i; 243082ebc44Swilfried 244d14c53d7Swilfried if (af != AF_INET6) { 245e4ebe044Shenning for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); 246e4ebe044Shenning i++) { 24730620b12Sfrantzen if (type == icmp_code[i].type && 24830620b12Sfrantzen code == icmp_code[i].code) 249082ebc44Swilfried return (&icmp_code[i]); 250082ebc44Swilfried } 25130620b12Sfrantzen } else { 25230620b12Sfrantzen for (i=0; i < (sizeof (icmp6_code) / 25330620b12Sfrantzen sizeof(icmp6_code[0])); i++) { 25430620b12Sfrantzen if (type == icmp6_code[i].type && 25530620b12Sfrantzen code == icmp6_code[i].code) 25630620b12Sfrantzen return (&icmp6_code[i]); 25730620b12Sfrantzen } 25830620b12Sfrantzen } 25930620b12Sfrantzen return (NULL); 260082ebc44Swilfried } 261082ebc44Swilfried 2627d27d81aSdhartmei const struct icmpcodeent * 263bb9f691eSmcbride geticmpcodebyname(u_long type, char *w, sa_family_t af) 264082ebc44Swilfried { 265ed99c291Sderaadt unsigned int i; 266082ebc44Swilfried 267d14c53d7Swilfried if (af != AF_INET6) { 268e4ebe044Shenning for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); 269e4ebe044Shenning i++) { 27030620b12Sfrantzen if (type == icmp_code[i].type && 27130620b12Sfrantzen !strcmp(w, icmp_code[i].name)) 272082ebc44Swilfried return (&icmp_code[i]); 273082ebc44Swilfried } 27430620b12Sfrantzen } else { 27530620b12Sfrantzen for (i=0; i < (sizeof (icmp6_code) / 27630620b12Sfrantzen sizeof(icmp6_code[0])); i++) { 27730620b12Sfrantzen if (type == icmp6_code[i].type && 27830620b12Sfrantzen !strcmp(w, icmp6_code[i].name)) 27930620b12Sfrantzen return (&icmp6_code[i]); 28030620b12Sfrantzen } 28130620b12Sfrantzen } 28230620b12Sfrantzen return (NULL); 28330620b12Sfrantzen } 28430620b12Sfrantzen 28581a15e5dSderaadt void 2865d9ac2dcSdhartmei print_op(u_int8_t op, const char *a1, const char *a2) 2875d9ac2dcSdhartmei { 2885d9ac2dcSdhartmei if (op == PF_OP_IRG) 2895d9ac2dcSdhartmei printf("%s >< %s ", a1, a2); 2905d9ac2dcSdhartmei else if (op == PF_OP_XRG) 2915d9ac2dcSdhartmei printf("%s <> %s ", a1, a2); 2921308506cShenning else if (op == PF_OP_EQ) 2935d9ac2dcSdhartmei printf("= %s ", a1); 2941308506cShenning else if (op == PF_OP_NE) 2955d9ac2dcSdhartmei printf("!= %s ", a1); 2961308506cShenning else if (op == PF_OP_LT) 2975d9ac2dcSdhartmei printf("< %s ", a1); 2985d9ac2dcSdhartmei else if (op == PF_OP_LE) 2995d9ac2dcSdhartmei printf("<= %s ", a1); 3005d9ac2dcSdhartmei else if (op == PF_OP_GT) 3015d9ac2dcSdhartmei printf("> %s ", a1); 3025d9ac2dcSdhartmei else if (op == PF_OP_GE) 3035d9ac2dcSdhartmei printf(">= %s ", a1); 3045d9ac2dcSdhartmei } 3055d9ac2dcSdhartmei 3065d9ac2dcSdhartmei void 30714a9b182Skjell print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto) 30814a9b182Skjell { 309e31d21c9Sdhartmei char a1[6], a2[6]; 310e4ebe044Shenning struct servent *s; 31181a15e5dSderaadt 312e4ebe044Shenning s = getservbyport(p1, proto); 31314a9b182Skjell p1 = ntohs(p1); 31414a9b182Skjell p2 = ntohs(p2); 3155d9ac2dcSdhartmei snprintf(a1, sizeof(a1), "%u", p1); 3165d9ac2dcSdhartmei snprintf(a2, sizeof(a2), "%u", p2); 31714a9b182Skjell printf("port "); 3185d9ac2dcSdhartmei if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE)) 3195d9ac2dcSdhartmei print_op(op, s->s_name, a2); 32014a9b182Skjell else 3215d9ac2dcSdhartmei print_op(op, a1, a2); 3225d9ac2dcSdhartmei } 3235d9ac2dcSdhartmei 3245d9ac2dcSdhartmei void 3255d9ac2dcSdhartmei print_uid(u_int8_t op, uid_t u1, uid_t u2, const char *t) 3265d9ac2dcSdhartmei { 327d8fcd2dfSdhartmei char a1[11], a2[11]; 3285d9ac2dcSdhartmei 3295d9ac2dcSdhartmei snprintf(a1, sizeof(a1), "%u", u1); 3305d9ac2dcSdhartmei snprintf(a2, sizeof(a2), "%u", u2); 3315d9ac2dcSdhartmei printf("%s ", t); 3325d9ac2dcSdhartmei if (u1 == UID_MAX && (op == PF_OP_EQ || op == PF_OP_NE)) 3335d9ac2dcSdhartmei print_op(op, "unknown", a2); 33414a9b182Skjell else 3355d9ac2dcSdhartmei print_op(op, a1, a2); 33614a9b182Skjell } 33714a9b182Skjell 33881a15e5dSderaadt void 339c16ab608Sdhartmei print_gid(u_int8_t op, gid_t g1, gid_t g2, const char *t) 340c16ab608Sdhartmei { 341d8fcd2dfSdhartmei char a1[11], a2[11]; 342c16ab608Sdhartmei 343c16ab608Sdhartmei snprintf(a1, sizeof(a1), "%u", g1); 344c16ab608Sdhartmei snprintf(a2, sizeof(a2), "%u", g2); 345c16ab608Sdhartmei printf("%s ", t); 346c16ab608Sdhartmei if (g1 == GID_MAX && (op == PF_OP_EQ || op == PF_OP_NE)) 347c16ab608Sdhartmei print_op(op, "unknown", a2); 348c16ab608Sdhartmei else 349c16ab608Sdhartmei print_op(op, a1, a2); 350c16ab608Sdhartmei } 351c16ab608Sdhartmei 352c16ab608Sdhartmei void 35314a9b182Skjell print_flags(u_int8_t f) 35414a9b182Skjell { 35514a9b182Skjell int i; 35681a15e5dSderaadt 357bc795af0Shugh for (i = 0; tcpflags[i]; ++i) 35814a9b182Skjell if (f & (1 << i)) 35914a9b182Skjell printf("%c", tcpflags[i]); 36014a9b182Skjell } 36114a9b182Skjell 36214a9b182Skjell void 36315e76891Sdhartmei print_fromto(struct pf_rule_addr *src, struct pf_rule_addr *dst, 36444f5ed0aScedric sa_family_t af, u_int8_t proto, int verbose) 36515e76891Sdhartmei { 366d0b1df00Sdhartmei if (src->addr.type != PF_ADDR_NOROUTE && 367d0b1df00Sdhartmei dst->addr.type != PF_ADDR_NOROUTE && 368bcf142a4Sdhartmei PF_AZERO(&src->addr.v.a.addr, AF_INET6) && 369bcf142a4Sdhartmei PF_AZERO(&src->addr.v.a.mask, AF_INET6) && 370bcf142a4Sdhartmei !src->port_op && PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && 371bcf142a4Sdhartmei PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && !dst->port_op) 37215e76891Sdhartmei printf("all "); 37315e76891Sdhartmei else { 37415e76891Sdhartmei printf("from "); 375d0b1df00Sdhartmei if (src->addr.type == PF_ADDR_NOROUTE) 37615e76891Sdhartmei printf("no-route "); 377bcf142a4Sdhartmei else if (PF_AZERO(&src->addr.v.a.addr, AF_INET6) && 378bcf142a4Sdhartmei PF_AZERO(&src->addr.v.a.mask, AF_INET6)) 37915e76891Sdhartmei printf("any "); 38015e76891Sdhartmei else { 38115e76891Sdhartmei if (src->not) 38215e76891Sdhartmei printf("! "); 38344f5ed0aScedric print_addr(&src->addr, af, verbose); 38415e76891Sdhartmei printf(" "); 38515e76891Sdhartmei } 38615e76891Sdhartmei if (src->port_op) 38715e76891Sdhartmei print_port(src->port_op, src->port[0], 38815e76891Sdhartmei src->port[1], 38915e76891Sdhartmei proto == IPPROTO_TCP ? "tcp" : "udp"); 39015e76891Sdhartmei 39115e76891Sdhartmei printf("to "); 392d0b1df00Sdhartmei if (dst->addr.type == PF_ADDR_NOROUTE) 39315e76891Sdhartmei printf("no-route "); 394bcf142a4Sdhartmei else if (PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && 395bcf142a4Sdhartmei PF_AZERO(&dst->addr.v.a.mask, AF_INET6)) 39615e76891Sdhartmei printf("any "); 39715e76891Sdhartmei else { 39815e76891Sdhartmei if (dst->not) 39915e76891Sdhartmei printf("! "); 40044f5ed0aScedric print_addr(&dst->addr, af, verbose); 40115e76891Sdhartmei printf(" "); 40215e76891Sdhartmei } 40315e76891Sdhartmei if (dst->port_op) 40415e76891Sdhartmei print_port(dst->port_op, dst->port[0], 40515e76891Sdhartmei dst->port[1], 40615e76891Sdhartmei proto == IPPROTO_TCP ? "tcp" : "udp"); 40715e76891Sdhartmei } 40815e76891Sdhartmei } 40915e76891Sdhartmei 41015e76891Sdhartmei void 411e8793aa9Smcbride print_rule(struct pf_rule *r, int verbose) 412e8793aa9Smcbride { 413e8793aa9Smcbride switch (r->action) { 414e8793aa9Smcbride case PF_NAT: 415e8793aa9Smcbride case PF_NONAT: 41660927d26Sdhartmei print_nat(r, verbose); 417e8793aa9Smcbride break; 418e8793aa9Smcbride case PF_BINAT: 419e8793aa9Smcbride case PF_NOBINAT: 42060927d26Sdhartmei print_binat(r, verbose); 421e8793aa9Smcbride break; 422e8793aa9Smcbride case PF_RDR: 423e8793aa9Smcbride case PF_NORDR: 42460927d26Sdhartmei print_rdr(r, verbose); 425e8793aa9Smcbride break; 426e8793aa9Smcbride default: 427e8793aa9Smcbride case PF_PASS: 428e8793aa9Smcbride case PF_DROP: 429e8793aa9Smcbride case PF_SCRUB: 430e8793aa9Smcbride print_filter(r, verbose); 431e8793aa9Smcbride break; 432e8793aa9Smcbride } 433e8793aa9Smcbride } 434e8793aa9Smcbride 435e8793aa9Smcbride void 436e0c302d0Smcbride print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2, 437e0c302d0Smcbride sa_family_t af, int id) 4383a44df3cSmcbride { 4393a44df3cSmcbride struct pf_pooladdr *pooladdr; 4403a44df3cSmcbride 4416c917913Smcbride if ((TAILQ_FIRST(&pool->list) != NULL) && 4426c917913Smcbride TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4433a44df3cSmcbride printf("{ "); 4443a44df3cSmcbride TAILQ_FOREACH(pooladdr, &pool->list, entries){ 4453a44df3cSmcbride switch (id) { 446e8793aa9Smcbride case PF_NAT: 447e8793aa9Smcbride case PF_RDR: 448e8793aa9Smcbride case PF_BINAT: 44944f5ed0aScedric print_addr(&pooladdr->addr.addr, af, 0); 4503a44df3cSmcbride break; 451e8793aa9Smcbride case PF_PASS: 452bcf142a4Sdhartmei if (PF_AZERO(&pooladdr->addr.addr.v.a.addr, af)) 4533b9b234fSmcbride printf("%s", pooladdr->ifname); 454790504a6Sdhartmei else { 4553a44df3cSmcbride printf("(%s ", pooladdr->ifname); 45644f5ed0aScedric print_addr(&pooladdr->addr.addr, af, 0); 4573a44df3cSmcbride printf(")"); 4583b9b234fSmcbride } 4593a44df3cSmcbride break; 460e8793aa9Smcbride default: 461e8793aa9Smcbride break; 4623a44df3cSmcbride } 4633a44df3cSmcbride if (TAILQ_NEXT(pooladdr, entries) != NULL) 4643a44df3cSmcbride printf(", "); 4653a44df3cSmcbride else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4663a44df3cSmcbride printf(" }"); 4673a44df3cSmcbride } 468e0c302d0Smcbride switch (id) { 469e8793aa9Smcbride case PF_NAT: 470e0c302d0Smcbride if (p1 != PF_NAT_PROXY_PORT_LOW || 471e0c302d0Smcbride p2 != PF_NAT_PROXY_PORT_HIGH) { 472e0c302d0Smcbride if (p1 == p2) 473e0c302d0Smcbride printf(" port %u", p1); 474e0c302d0Smcbride else 475e0c302d0Smcbride printf(" port %u:%u", p1, p2); 476e0c302d0Smcbride } 477e0c302d0Smcbride break; 478e8793aa9Smcbride case PF_RDR: 479e0c302d0Smcbride if (p1) { 480e0c302d0Smcbride printf(" port %u", ntohs(p1)); 481120f430eSmcbride if (p2) 482120f430eSmcbride printf(":%u", ntohs(p2)); 483e0c302d0Smcbride } 484e0c302d0Smcbride break; 485e0c302d0Smcbride default: 486e0c302d0Smcbride break; 487e0c302d0Smcbride } 488e0c302d0Smcbride switch (pool->opts & PF_POOL_TYPEMASK) { 489e0c302d0Smcbride case PF_POOL_NONE: 490e0c302d0Smcbride break; 491e0c302d0Smcbride case PF_POOL_BITMASK: 492e0c302d0Smcbride printf(" bitmask"); 493e0c302d0Smcbride break; 494e0c302d0Smcbride case PF_POOL_RANDOM: 495e0c302d0Smcbride printf(" random"); 496e0c302d0Smcbride break; 497e0c302d0Smcbride case PF_POOL_SRCHASH: 4980436fa02Smcbride printf(" source-hash 0x%08x%08x%08x%08x", 499e0c302d0Smcbride pool->key.key32[0], pool->key.key32[1], 500e0c302d0Smcbride pool->key.key32[2], pool->key.key32[3]); 501e0c302d0Smcbride break; 502e0c302d0Smcbride case PF_POOL_ROUNDROBIN: 503e0c302d0Smcbride printf(" round-robin"); 504e0c302d0Smcbride break; 505e0c302d0Smcbride } 506e0c302d0Smcbride if (pool->opts & PF_POOL_STATICPORT) 507e0c302d0Smcbride printf(" static-port"); 5083a44df3cSmcbride } 5093a44df3cSmcbride 5103a44df3cSmcbride void 51160927d26Sdhartmei print_nat(struct pf_rule *n, int verbose) 51214a9b182Skjell { 51360927d26Sdhartmei if (verbose) 51460927d26Sdhartmei printf("@%d ", n->nr); 5156ac94451Sdhartmei if (n->anchorname[0]) 5166ac94451Sdhartmei printf("nat-anchor %s ", n->anchorname); 5176ac94451Sdhartmei else { 518e8793aa9Smcbride if (n->action == PF_NONAT) 519f27db9bcSdhartmei printf("no "); 520f27db9bcSdhartmei printf("nat "); 5216ac94451Sdhartmei } 52228964e80Sdhartmei if (n->ifname[0]) { 52328964e80Sdhartmei printf("on "); 524870b51d7Schris if (n->ifnot) 525870b51d7Schris printf("! "); 526870b51d7Schris printf("%s ", n->ifname); 52728964e80Sdhartmei } 528032e40b7Sdhartmei if (n->af) { 529032e40b7Sdhartmei if (n->af == AF_INET) 530032e40b7Sdhartmei printf("inet "); 531032e40b7Sdhartmei else 532032e40b7Sdhartmei printf("inet6 "); 533032e40b7Sdhartmei } 53480edb1f0Sdhartmei if (n->proto) { 535e4ebe044Shenning struct protoent *p; 536ed99c291Sderaadt 537e4ebe044Shenning if ((p = getprotobynumber(n->proto)) != NULL) 53880edb1f0Sdhartmei printf("proto %s ", p->p_name); 53980edb1f0Sdhartmei else 54080edb1f0Sdhartmei printf("proto %u ", n->proto); 54180edb1f0Sdhartmei } 54244f5ed0aScedric print_fromto(&n->src, &n->dst, n->af, n->proto, verbose); 543e8793aa9Smcbride if (!n->anchorname[0] && (n->action == PF_NAT)) { 54428964e80Sdhartmei printf("-> "); 545e8793aa9Smcbride print_pool(&n->rpool, n->rpool.proxy_port[0], 546e8793aa9Smcbride n->rpool.proxy_port[1], n->af, PF_NAT); 547f27db9bcSdhartmei } 54814a9b182Skjell printf("\n"); 54914a9b182Skjell } 55014a9b182Skjell 55114a9b182Skjell void 55260927d26Sdhartmei print_binat(struct pf_rule *b, int verbose) 553a3e657d0Sjasoni { 55460927d26Sdhartmei if (verbose) 55560927d26Sdhartmei printf("@%d ", b->nr); 5566ac94451Sdhartmei if (b->anchorname[0]) 5576ac94451Sdhartmei printf("binat-anchor %s ", b->anchorname); 5586ac94451Sdhartmei else { 559e8793aa9Smcbride if (b->action == PF_NOBINAT) 560f27db9bcSdhartmei printf("no "); 561f27db9bcSdhartmei printf("binat "); 5626ac94451Sdhartmei } 563a3e657d0Sjasoni if (b->ifname[0]) { 564a3e657d0Sjasoni printf("on "); 565a3e657d0Sjasoni printf("%s ", b->ifname); 566a3e657d0Sjasoni } 567032e40b7Sdhartmei if (b->af) { 568032e40b7Sdhartmei if (b->af == AF_INET) 569032e40b7Sdhartmei printf("inet "); 570032e40b7Sdhartmei else 571032e40b7Sdhartmei printf("inet6 "); 572032e40b7Sdhartmei } 57380edb1f0Sdhartmei if (b->proto) { 574e4ebe044Shenning struct protoent *p; 575ed99c291Sderaadt 576e4ebe044Shenning if ((p = getprotobynumber(b->proto)) != NULL) 57780edb1f0Sdhartmei printf("proto %s ", p->p_name); 57880edb1f0Sdhartmei else 57980edb1f0Sdhartmei printf("proto %u ", b->proto); 580a3e657d0Sjasoni } 581a3e657d0Sjasoni printf("from "); 582bcf142a4Sdhartmei if (!PF_AZERO(&b->src.addr.v.a.addr, b->af) || 583bcf142a4Sdhartmei !PF_AZERO(&b->src.addr.v.a.mask, b->af)) { 58444f5ed0aScedric print_addr(&b->src.addr, b->af, verbose); 585a3e657d0Sjasoni printf(" "); 5866ac94451Sdhartmei } else 5876ac94451Sdhartmei printf("any "); 588a3e657d0Sjasoni printf("to "); 589bcf142a4Sdhartmei if (!PF_AZERO(&b->dst.addr.v.a.addr, b->af) || 590bcf142a4Sdhartmei !PF_AZERO(&b->dst.addr.v.a.mask, b->af)) { 591e8793aa9Smcbride if (b->dst.not) 592a3e657d0Sjasoni printf("! "); 59344f5ed0aScedric print_addr(&b->dst.addr, b->af, verbose); 594a3e657d0Sjasoni printf(" "); 595a3e657d0Sjasoni } else 596a3e657d0Sjasoni printf("any "); 597e8793aa9Smcbride if (!b->anchorname[0] && (b->action == PF_BINAT)) { 598a3e657d0Sjasoni printf("-> "); 599e8793aa9Smcbride print_pool(&b->rpool, 0, 0, b->af, PF_BINAT); 600f27db9bcSdhartmei } 601a3e657d0Sjasoni printf("\n"); 602a3e657d0Sjasoni } 603a3e657d0Sjasoni 604a3e657d0Sjasoni void 60560927d26Sdhartmei print_rdr(struct pf_rule *r, int verbose) 60614a9b182Skjell { 60760927d26Sdhartmei if (verbose) 60860927d26Sdhartmei printf("@%d ", r->nr); 6096ac94451Sdhartmei if (r->anchorname[0]) 6106ac94451Sdhartmei printf("rdr-anchor %s ", r->anchorname); 6116ac94451Sdhartmei else { 612e8793aa9Smcbride if (r->action == PF_NORDR) 613f27db9bcSdhartmei printf("no "); 614f27db9bcSdhartmei printf("rdr "); 6156ac94451Sdhartmei } 61628964e80Sdhartmei if (r->ifname[0]) { 61728964e80Sdhartmei printf("on "); 618870b51d7Schris if (r->ifnot) 619870b51d7Schris printf("! "); 620870b51d7Schris printf("%s ", r->ifname); 62128964e80Sdhartmei } 622032e40b7Sdhartmei if (r->af) { 623032e40b7Sdhartmei if (r->af == AF_INET) 624032e40b7Sdhartmei printf("inet "); 625032e40b7Sdhartmei else 626032e40b7Sdhartmei printf("inet6 "); 627032e40b7Sdhartmei } 62880edb1f0Sdhartmei if (r->proto) { 629e4ebe044Shenning struct protoent *p; 630ed99c291Sderaadt 631e4ebe044Shenning if ((p = getprotobynumber(r->proto)) != NULL) 63280edb1f0Sdhartmei printf("proto %s ", p->p_name); 63380edb1f0Sdhartmei else 63480edb1f0Sdhartmei printf("proto %u ", r->proto); 635e3d52469Smillert } 63628964e80Sdhartmei printf("from "); 637bcf142a4Sdhartmei if (!PF_AZERO(&r->src.addr.v.a.addr, r->af) || 638bcf142a4Sdhartmei !PF_AZERO(&r->src.addr.v.a.mask, r->af)) { 639e8793aa9Smcbride if (r->src.not) 64028964e80Sdhartmei printf("! "); 64144f5ed0aScedric print_addr(&r->src.addr, r->af, verbose); 64228964e80Sdhartmei printf(" "); 64328964e80Sdhartmei } else 64428964e80Sdhartmei printf("any "); 64528964e80Sdhartmei printf("to "); 646bcf142a4Sdhartmei if (!PF_AZERO(&r->dst.addr.v.a.addr, r->af) || 647bcf142a4Sdhartmei !PF_AZERO(&r->dst.addr.v.a.mask, r->af)) { 648e8793aa9Smcbride if (r->dst.not) 64914a9b182Skjell printf("! "); 65044f5ed0aScedric print_addr(&r->dst.addr, r->af, verbose); 65128964e80Sdhartmei printf(" "); 65228964e80Sdhartmei } else 65328964e80Sdhartmei printf("any "); 654e8793aa9Smcbride if (r->dst.port[0]) { 655e8793aa9Smcbride printf("port %u", ntohs(r->dst.port[0])); 656120f430eSmcbride if (r->dst.port_op & PF_OP_RRG) 657e8793aa9Smcbride printf(":%u", ntohs(r->dst.port[1])); 6580436fa02Smcbride printf(" "); 65980edb1f0Sdhartmei } 660e8793aa9Smcbride if (!r->anchorname[0] && (r->action == PF_RDR)) { 661cb07131dSkjell printf("-> "); 662e8793aa9Smcbride print_pool(&r->rpool, r->rpool.proxy_port[0], 663120f430eSmcbride r->rpool.proxy_port[1], r->af, PF_RDR); 664f27db9bcSdhartmei } 66514a9b182Skjell printf("\n"); 66614a9b182Skjell } 66714a9b182Skjell 668bca2bf17Sdhartmei char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 669bca2bf17Sdhartmei char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 67099a73934Sderaadt 67114a9b182Skjell void 67281a15e5dSderaadt print_status(struct pf_status *s) 67314a9b182Skjell { 674e4ebe044Shenning char statline[80]; 675c474e331Shenning time_t runtime; 67699a73934Sderaadt int i; 67799a73934Sderaadt 678c474e331Shenning runtime = time(NULL) - s->since; 679c474e331Shenning 680d85e4ad6Sdhartmei if (s->running) { 681d85e4ad6Sdhartmei unsigned sec, min, hrs, day = runtime; 682d85e4ad6Sdhartmei 683d85e4ad6Sdhartmei sec = day % 60; 684d85e4ad6Sdhartmei day /= 60; 685d85e4ad6Sdhartmei min = day % 60; 686d85e4ad6Sdhartmei day /= 60; 687d85e4ad6Sdhartmei hrs = day % 24; 688d85e4ad6Sdhartmei day /= 24; 689c474e331Shenning snprintf(statline, sizeof(statline), 690d85e4ad6Sdhartmei "Status: Enabled for %u days %.2u:%.2u:%.2u", 691d85e4ad6Sdhartmei day, hrs, min, sec); 692d85e4ad6Sdhartmei } else 693c474e331Shenning snprintf(statline, sizeof(statline), "Status: Disabled"); 694c97b4ee1Shenning printf("%-44s", statline); 695ae58c8acSdhartmei switch (s->debug) { 696ae58c8acSdhartmei case 0: 697c97b4ee1Shenning printf("%15s\n\n", "Debug: None"); 698ae58c8acSdhartmei break; 699ae58c8acSdhartmei case 1: 700c97b4ee1Shenning printf("%15s\n\n", "Debug: Urgent"); 701ae58c8acSdhartmei break; 702ae58c8acSdhartmei case 2: 703c97b4ee1Shenning printf("%15s\n\n", "Debug: Misc"); 704ae58c8acSdhartmei break; 705ae58c8acSdhartmei } 706c474e331Shenning if (s->ifname[0] != 0) { 707c474e331Shenning printf("Interface Stats for %-16s %5s %16s\n", 708c474e331Shenning s->ifname, "IPv4", "IPv6"); 709c474e331Shenning printf(" %-25s %14llu %16llu\n", "Bytes In", 7107189e280Sdhartmei s->bcounters[0][0], s->bcounters[1][0]); 711c474e331Shenning printf(" %-25s %14llu %16llu\n", "Bytes Out", 7127189e280Sdhartmei s->bcounters[0][1], s->bcounters[1][1]); 713c474e331Shenning printf(" Packets In\n"); 714c474e331Shenning printf(" %-23s %14llu %16llu\n", "Passed", 7157189e280Sdhartmei s->pcounters[0][0][PF_PASS], 7167189e280Sdhartmei s->pcounters[1][0][PF_PASS]); 717c474e331Shenning printf(" %-23s %14llu %16llu\n", "Blocked", 7187189e280Sdhartmei s->pcounters[0][0][PF_DROP], 7197189e280Sdhartmei s->pcounters[1][0][PF_DROP]); 720c474e331Shenning printf(" Packets Out\n"); 721c474e331Shenning printf(" %-23s %14llu %16llu\n", "Passed", 7227189e280Sdhartmei s->pcounters[0][1][PF_PASS], 7237189e280Sdhartmei s->pcounters[1][1][PF_PASS]); 724c474e331Shenning printf(" %-23s %14llu %16llu\n\n", "Blocked", 7257189e280Sdhartmei s->pcounters[0][1][PF_DROP], 7267189e280Sdhartmei s->pcounters[1][1][PF_DROP]); 727c474e331Shenning } 728c474e331Shenning printf("%-27s %14s %16s\n", "State Table", "Total", "Rate"); 729c474e331Shenning printf(" %-25s %14u %14s\n", "current entries", s->states, ""); 730c474e331Shenning for (i = 0; i < FCNT_MAX; i++) { 731c474e331Shenning printf(" %-25s %14lld ", pf_fcounters[i], 73284976600Sderaadt s->fcounters[i]); 733c474e331Shenning if (runtime > 0) 734c474e331Shenning printf("%14.1f/s\n", 735c474e331Shenning (double)s->fcounters[i] / (double)runtime); 736c474e331Shenning else 737c474e331Shenning printf("%14s\n", ""); 738c474e331Shenning } 73999a73934Sderaadt printf("Counters\n"); 740c474e331Shenning for (i = 0; i < PFRES_MAX; i++) { 741c474e331Shenning printf(" %-25s %14lld ", pf_reasons[i], 74299a73934Sderaadt s->counters[i]); 743c474e331Shenning if (runtime > 0) 744c474e331Shenning printf("%14.1f/s\n", 745c474e331Shenning (double)s->counters[i] / (double)runtime); 746c474e331Shenning else 747c474e331Shenning printf("%14s\n", ""); 748c474e331Shenning } 74914a9b182Skjell } 75014a9b182Skjell 75114a9b182Skjell void 752e8793aa9Smcbride print_filter(struct pf_rule *r, int verbose) 75314a9b182Skjell { 754cc5f0329Sdhartmei int i, opts; 755cc5f0329Sdhartmei 75674dc4fddShenning if (verbose) 75778baf774Sdhartmei printf("@%d ", r->nr); 7586ac94451Sdhartmei if (r->anchorname[0]) 7596ac94451Sdhartmei printf("anchor %s ", r->anchorname); 7606ac94451Sdhartmei else if (r->action == PF_PASS) 76114a9b182Skjell printf("pass "); 762b996d042Sdhartmei else if (r->action == PF_DROP) { 76314a9b182Skjell printf("block "); 7648a87542aShenning if (r->rule_flag & PFRULE_RETURN) 7658a87542aShenning printf("return "); 7668a87542aShenning else if (r->rule_flag & PFRULE_RETURNRST) { 7671f77cc8aSpb if (!r->return_ttl) 76814a9b182Skjell printf("return-rst "); 7691f77cc8aSpb else 7701f77cc8aSpb printf("return-rst(ttl %d) ", r->return_ttl); 771328b2decShenning } else if (r->rule_flag & PFRULE_RETURNICMP) { 772328b2decShenning const struct icmpcodeent *ic, *ic6; 773b996d042Sdhartmei 774b996d042Sdhartmei ic = geticmpcodebynumber(r->return_icmp >> 8, 775328b2decShenning r->return_icmp & 255, AF_INET); 776328b2decShenning ic6 = geticmpcodebynumber(r->return_icmp6 >> 8, 777328b2decShenning r->return_icmp6 & 255, AF_INET6); 778d14c53d7Swilfried 779328b2decShenning switch(r->af) { 780328b2decShenning case AF_INET: 781328b2decShenning printf("return-icmp"); 782d14c53d7Swilfried if (ic == NULL) 783d14c53d7Swilfried printf("(%u) ", r->return_icmp & 255); 784b996d042Sdhartmei else 785328b2decShenning printf("(%s) ", ic->name); 786328b2decShenning break; 787328b2decShenning case AF_INET6: 788328b2decShenning printf("return-icmp6"); 789328b2decShenning if (ic6 == NULL) 790328b2decShenning printf("(%u) ", r->return_icmp6 & 255); 791328b2decShenning else 792328b2decShenning printf("(%s) ", ic6->name); 793328b2decShenning break; 794328b2decShenning default: 795328b2decShenning printf("return-icmp"); 796328b2decShenning if (ic == NULL) 797328b2decShenning printf("(%u, ", r->return_icmp & 255); 798328b2decShenning else 799328b2decShenning printf("(%s, ", ic->name); 800328b2decShenning if (ic6 == NULL) 801328b2decShenning printf("%u) ", r->return_icmp6 & 255); 802328b2decShenning else 803328b2decShenning printf("%s) ", ic6->name); 804328b2decShenning break; 805328b2decShenning } 806acf2444cShenning } else 807acf2444cShenning printf("drop "); 8086ac94451Sdhartmei } else 809b996d042Sdhartmei printf("scrub "); 8107189e280Sdhartmei if (r->direction == PF_IN) 81114a9b182Skjell printf("in "); 8127189e280Sdhartmei else if (r->direction == PF_OUT) 81314a9b182Skjell printf("out "); 8147242ce7aSdhartmei if (r->log == 1) 81514a9b182Skjell printf("log "); 8167242ce7aSdhartmei else if (r->log == 2) 8177242ce7aSdhartmei printf("log-all "); 81814a9b182Skjell if (r->quick) 81914a9b182Skjell printf("quick "); 8207d0c9138Shenning if (r->ifname[0]) { 8217d0c9138Shenning if (r->ifnot) 8227d0c9138Shenning printf("on ! %s ", r->ifname); 8237d0c9138Shenning else 82414a9b182Skjell printf("on %s ", r->ifname); 8257d0c9138Shenning } 826cb3a4e31Sjasoni if (r->rt) { 827cb3a4e31Sjasoni if (r->rt == PF_ROUTETO) 828cb3a4e31Sjasoni printf("route-to "); 829fa1cdd09Sdhartmei else if (r->rt == PF_REPLYTO) 830fa1cdd09Sdhartmei printf("reply-to "); 831cb3a4e31Sjasoni else if (r->rt == PF_DUPTO) 832cb3a4e31Sjasoni printf("dup-to "); 833cb3a4e31Sjasoni else if (r->rt == PF_FASTROUTE) 834cb3a4e31Sjasoni printf("fastroute "); 835790504a6Sdhartmei if (r->rt != PF_FASTROUTE) { 836e8793aa9Smcbride print_pool(&r->rpool, 0, 0, r->af, PF_PASS); 837790504a6Sdhartmei printf(" "); 838790504a6Sdhartmei } 839cb3a4e31Sjasoni } 84030620b12Sfrantzen if (r->af) { 84130620b12Sfrantzen if (r->af == AF_INET) 84230620b12Sfrantzen printf("inet "); 84330620b12Sfrantzen else 84430620b12Sfrantzen printf("inet6 "); 84530620b12Sfrantzen } 84614a9b182Skjell if (r->proto) { 847e4ebe044Shenning struct protoent *p; 848ed99c291Sderaadt 849e4ebe044Shenning if ((p = getprotobynumber(r->proto)) != NULL) 85014a9b182Skjell printf("proto %s ", p->p_name); 85114a9b182Skjell else 85214a9b182Skjell printf("proto %u ", r->proto); 85314a9b182Skjell } 85444f5ed0aScedric print_fromto(&r->src, &r->dst, r->af, r->proto, verbose); 855c16ab608Sdhartmei if (r->uid.op) 856c16ab608Sdhartmei print_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user"); 857c16ab608Sdhartmei if (r->gid.op) 858c16ab608Sdhartmei print_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group"); 85914a9b182Skjell if (r->flags || r->flagset) { 86014a9b182Skjell printf("flags "); 86114a9b182Skjell print_flags(r->flags); 86214a9b182Skjell printf("/"); 86314a9b182Skjell print_flags(r->flagset); 86414a9b182Skjell printf(" "); 86514a9b182Skjell } 866082ebc44Swilfried if (r->type) { 867b49ca6bbShenning const struct icmptypeent *it; 868082ebc44Swilfried 869b49ca6bbShenning it = geticmptypebynumber(r->type-1, r->af); 870d14c53d7Swilfried if (r->af != AF_INET6) 871d14c53d7Swilfried printf("icmp-type"); 872082ebc44Swilfried else 873d0cb3502Smcbride printf("icmp6-type"); 874b49ca6bbShenning if (it != NULL) 875b49ca6bbShenning printf(" %s ", it->name); 876d14c53d7Swilfried else 877d14c53d7Swilfried printf(" %u ", r->type-1); 878082ebc44Swilfried if (r->code) { 879b49ca6bbShenning const struct icmpcodeent *ic; 880082ebc44Swilfried 881b49ca6bbShenning ic = geticmpcodebynumber(r->type-1, r->code-1, r->af); 882b49ca6bbShenning if (ic != NULL) 883b49ca6bbShenning printf("code %s ", ic->name); 884082ebc44Swilfried else 88514a9b182Skjell printf("code %u ", r->code-1); 886082ebc44Swilfried } 887082ebc44Swilfried } 888e4cbe364Sdhartmei if (r->tos) 889e4cbe364Sdhartmei printf("tos 0x%2.2x ", r->tos); 890b96c47abSfrantzen if (r->keep_state == PF_STATE_NORMAL) 89114a9b182Skjell printf("keep state "); 892b96c47abSfrantzen else if (r->keep_state == PF_STATE_MODULATE) 893b96c47abSfrantzen printf("modulate state "); 894cc5f0329Sdhartmei opts = 0; 895b3c86969Sdhartmei if (r->max_states) 896cc5f0329Sdhartmei opts = 1; 897cc5f0329Sdhartmei for (i = 0; !opts && i < PFTM_MAX; ++i) 898cc5f0329Sdhartmei if (r->timeout[i]) 899cc5f0329Sdhartmei opts = 1; 900cc5f0329Sdhartmei if (opts) { 901cc5f0329Sdhartmei printf("("); 902cc5f0329Sdhartmei if (r->max_states) { 903cc5f0329Sdhartmei printf("max %u", r->max_states); 904cc5f0329Sdhartmei opts = 0; 905cc5f0329Sdhartmei } 906cc5f0329Sdhartmei for (i = 0; i < PFTM_MAX; ++i) 907cc5f0329Sdhartmei if (r->timeout[i]) { 908cc5f0329Sdhartmei if (!opts) 909cc5f0329Sdhartmei printf(", "); 910cc5f0329Sdhartmei opts = 0; 911cc5f0329Sdhartmei printf("%s %u", pf_timeouts[i].name, 912cc5f0329Sdhartmei r->timeout[i]); 913cc5f0329Sdhartmei } 914cc5f0329Sdhartmei printf(") "); 915cc5f0329Sdhartmei } 9166673dee2Sdhartmei if (r->rule_flag & PFRULE_FRAGMENT) 9176673dee2Sdhartmei printf("fragment "); 91867d2a440Sprovos if (r->rule_flag & PFRULE_NODF) 91967d2a440Sprovos printf("no-df "); 920*edbe3066Sdhartmei if (r->rule_flag & PFRULE_RANDOMID) 921*edbe3066Sdhartmei printf("random-id "); 922e258bfd4Sprovos if (r->min_ttl) 92334c76dcbSprovos printf("min-ttl %d ", r->min_ttl); 924cfa91859Sjasoni if (r->max_mss) 925cfa91859Sjasoni printf("max-mss %d ", r->max_mss); 926f48d62b3Sdhartmei if (r->allow_opts) 927f48d62b3Sdhartmei printf("allow-opts "); 928b02af636Sfrantzen if (r->action == PF_SCRUB) { 929b02af636Sfrantzen if (r->rule_flag & PFRULE_FRAGDROP) 930b02af636Sfrantzen printf("fragment drop-ovl "); 931b02af636Sfrantzen else if (r->rule_flag & PFRULE_FRAGCROP) 932b02af636Sfrantzen printf("fragment crop "); 933b02af636Sfrantzen else 934b02af636Sfrantzen printf("fragment reassemble "); 935b02af636Sfrantzen } 936455ef0c1Sdhartmei if (r->label[0]) 937ff45dfa8Scamield printf("label \"%s\" ", r->label); 938f98324c6Shenning if (r->qname[0] && r->pqname[0]) 939f98324c6Shenning printf("queue(%s, %s) ", r->qname, r->pqname); 940f98324c6Shenning else if (r->qname[0]) 94178e1d2a6Shenning printf("queue %s ", r->qname); 94267d2a440Sprovos 94314a9b182Skjell printf("\n"); 94414a9b182Skjell } 94514a9b182Skjell 9461f8f21bdSmillert int 947ff352a37Smarkus parse_flags(char *s) 94814a9b182Skjell { 949ff352a37Smarkus char *p, *q; 95014a9b182Skjell u_int8_t f = 0; 95181a15e5dSderaadt 952ff352a37Smarkus for (p = s; *p; p++) { 953ff352a37Smarkus if ((q = strchr(tcpflags, *p)) == NULL) 954ff352a37Smarkus return -1; 955ff352a37Smarkus else 956ff352a37Smarkus f |= 1 << (q - tcpflags); 95714a9b182Skjell } 958bc795af0Shugh return (f ? f : PF_TH_ALL); 95914a9b182Skjell } 96094e9410bShenning 96194e9410bShenning void 96294e9410bShenning set_ipmask(struct node_host *h, u_int8_t b) 96394e9410bShenning { 96494e9410bShenning struct pf_addr *m, *n; 96594e9410bShenning int i, j = 0; 96694e9410bShenning 96794e9410bShenning m = &h->addr.v.a.mask; 96894e9410bShenning 96994e9410bShenning for (i = 0; i < 4; i++) 97094e9410bShenning m->addr32[i] = 0; 97194e9410bShenning 97294e9410bShenning while (b >= 32) { 97394e9410bShenning m->addr32[j++] = 0xffffffff; 97494e9410bShenning b -= 32; 97594e9410bShenning } 97694e9410bShenning for (i = 31; i > 31-b; --i) 97794e9410bShenning m->addr32[j] |= (1 << i); 97894e9410bShenning if (b) 97994e9410bShenning m->addr32[j] = htonl(m->addr32[j]); 98094e9410bShenning 98194e9410bShenning /* Mask off bits of the address that will never be used. */ 98294e9410bShenning n = &h->addr.v.a.addr; 98394e9410bShenning for (i = 0; i < 4; i++) 98494e9410bShenning n->addr32[i] = n->addr32[i] & m->addr32[i]; 98594e9410bShenning } 98694e9410bShenning 98794e9410bShenning /* interface lookup routines */ 98894e9410bShenning 98994e9410bShenning struct node_host *iftab; 99094e9410bShenning 99194e9410bShenning void 99294e9410bShenning ifa_load(void) 99394e9410bShenning { 99494e9410bShenning struct ifaddrs *ifap, *ifa; 99594e9410bShenning struct node_host *n = NULL, *h = NULL; 99694e9410bShenning 99794e9410bShenning if (getifaddrs(&ifap) < 0) 99894e9410bShenning err(1, "getifaddrs"); 99994e9410bShenning 100094e9410bShenning for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 100194e9410bShenning if (!(ifa->ifa_addr->sa_family == AF_INET || 100294e9410bShenning ifa->ifa_addr->sa_family == AF_INET6 || 100394e9410bShenning ifa->ifa_addr->sa_family == AF_LINK)) 100494e9410bShenning continue; 100594e9410bShenning n = calloc(1, sizeof(struct node_host)); 100694e9410bShenning if (n == NULL) 100794e9410bShenning err(1, "address: calloc"); 100894e9410bShenning n->af = ifa->ifa_addr->sa_family; 100994e9410bShenning n->ifa_flags = ifa->ifa_flags; 101094e9410bShenning #ifdef __KAME__ 101194e9410bShenning if (n->af == AF_INET6 && 101294e9410bShenning IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) 101394e9410bShenning ifa->ifa_addr)->sin6_addr) && 101494e9410bShenning ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 0) { 101594e9410bShenning struct sockaddr_in6 *sin6; 101694e9410bShenning 101794e9410bShenning sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 101894e9410bShenning sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | 101994e9410bShenning sin6->sin6_addr.s6_addr[3]; 102094e9410bShenning sin6->sin6_addr.s6_addr[2] = 0; 102194e9410bShenning sin6->sin6_addr.s6_addr[3] = 0; 102294e9410bShenning } 102394e9410bShenning #endif 102494e9410bShenning n->ifindex = 0; 102594e9410bShenning if (n->af == AF_INET) { 102694e9410bShenning memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) 102794e9410bShenning ifa->ifa_addr)->sin_addr.s_addr, 102894e9410bShenning sizeof(struct in_addr)); 102994e9410bShenning memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) 103094e9410bShenning ifa->ifa_netmask)->sin_addr.s_addr, 103194e9410bShenning sizeof(struct in_addr)); 103294e9410bShenning if (ifa->ifa_broadaddr != NULL) 103394e9410bShenning memcpy(&n->bcast, &((struct sockaddr_in *) 103494e9410bShenning ifa->ifa_broadaddr)->sin_addr.s_addr, 103594e9410bShenning sizeof(struct in_addr)); 103694e9410bShenning } else if (n->af == AF_INET6) { 103794e9410bShenning memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) 103894e9410bShenning ifa->ifa_addr)->sin6_addr.s6_addr, 103994e9410bShenning sizeof(struct in6_addr)); 104094e9410bShenning memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) 104194e9410bShenning ifa->ifa_netmask)->sin6_addr.s6_addr, 104294e9410bShenning sizeof(struct in6_addr)); 104394e9410bShenning if (ifa->ifa_broadaddr != NULL) 104494e9410bShenning memcpy(&n->bcast, &((struct sockaddr_in6 *) 104594e9410bShenning ifa->ifa_broadaddr)->sin6_addr.s6_addr, 104694e9410bShenning sizeof(struct in6_addr)); 104794e9410bShenning n->ifindex = ((struct sockaddr_in6 *) 104894e9410bShenning ifa->ifa_addr)->sin6_scope_id; 104994e9410bShenning } 105094e9410bShenning if ((n->ifname = strdup(ifa->ifa_name)) == NULL) 105194e9410bShenning err(1, "ifa_load: strdup"); 105294e9410bShenning n->next = NULL; 105394e9410bShenning n->tail = n; 105494e9410bShenning if (h == NULL) 105594e9410bShenning h = n; 105694e9410bShenning else { 105794e9410bShenning h->tail->next = n; 105894e9410bShenning h->tail = n; 105994e9410bShenning } 106094e9410bShenning } 106194e9410bShenning iftab = h; 106294e9410bShenning freeifaddrs(ifap); 106394e9410bShenning } 106494e9410bShenning 106594e9410bShenning struct node_host * 10666cba701cShenning ifa_exists(const char *ifa_name) 106794e9410bShenning { 106894e9410bShenning struct node_host *n; 106994e9410bShenning 107094e9410bShenning if (iftab == NULL) 107194e9410bShenning ifa_load(); 107294e9410bShenning 107394e9410bShenning for (n = iftab; n; n = n->next) { 107494e9410bShenning if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) 107594e9410bShenning return (n); 107694e9410bShenning } 107794e9410bShenning return (NULL); 107894e9410bShenning } 107994e9410bShenning 108094e9410bShenning struct node_host * 10816cba701cShenning ifa_lookup(const char *ifa_name, enum pfctl_iflookup_mode mode) 108294e9410bShenning { 108394e9410bShenning struct node_host *p = NULL, *h = NULL, *n = NULL; 108494e9410bShenning int return_all = 0; 108594e9410bShenning 108694e9410bShenning if (!strncmp(ifa_name, "self", IFNAMSIZ)) 108794e9410bShenning return_all = 1; 108894e9410bShenning 108994e9410bShenning if (iftab == NULL) 109094e9410bShenning ifa_load(); 109194e9410bShenning 109294e9410bShenning for (p = iftab; p; p = p->next) { 109394e9410bShenning if (!((p->af == AF_INET || p->af == AF_INET6) && 109494e9410bShenning (!strncmp(p->ifname, ifa_name, IFNAMSIZ) || return_all))) 109594e9410bShenning continue; 109694e9410bShenning if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET) 109794e9410bShenning continue; 109894e9410bShenning if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0) 109994e9410bShenning continue; 110094e9410bShenning n = calloc(1, sizeof(struct node_host)); 110194e9410bShenning if (n == NULL) 110294e9410bShenning err(1, "address: calloc"); 110394e9410bShenning n->af = p->af; 110494e9410bShenning if (mode == PFCTL_IFLOOKUP_BCAST) 110594e9410bShenning memcpy(&n->addr.v.a.addr, &p->bcast, 110694e9410bShenning sizeof(struct pf_addr)); 110794e9410bShenning else 110894e9410bShenning memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, 110994e9410bShenning sizeof(struct pf_addr)); 111094e9410bShenning if (mode == PFCTL_IFLOOKUP_NET) 111194e9410bShenning set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); 111294e9410bShenning else { 111394e9410bShenning if (n->af == AF_INET) { 111494e9410bShenning if (p->ifa_flags & IFF_LOOPBACK && 111594e9410bShenning p->ifa_flags & IFF_LINK1) 111694e9410bShenning memcpy(&n->addr.v.a.mask, 111794e9410bShenning &p->addr.v.a.mask, 111894e9410bShenning sizeof(struct pf_addr)); 111994e9410bShenning else 112094e9410bShenning set_ipmask(n, 32); 112194e9410bShenning } else 112294e9410bShenning set_ipmask(n, 128); 112394e9410bShenning } 112494e9410bShenning n->ifindex = p->ifindex; 112594e9410bShenning 112694e9410bShenning n->next = NULL; 112794e9410bShenning n->tail = n; 112894e9410bShenning if (h == NULL) 112994e9410bShenning h = n; 113094e9410bShenning else { 113194e9410bShenning h->tail->next = n; 113294e9410bShenning h->tail = n; 113394e9410bShenning } 113494e9410bShenning } 113594e9410bShenning if (h == NULL && mode == PFCTL_IFLOOKUP_HOST) { 113694e9410bShenning fprintf(stderr, "no IP address found for %s\n", ifa_name); 113794e9410bShenning } 113894e9410bShenning return (h); 113994e9410bShenning } 114094e9410bShenning 114194e9410bShenning struct node_host * 11426cba701cShenning host(const char *s, int mask) 114394e9410bShenning { 11442a6c1abaShenning struct node_host *h = NULL; 11452a6c1abaShenning int v4mask, v6mask, cont = 1; 114694e9410bShenning char *buf = NULL, *p, *q, *ps; 114794e9410bShenning 114894e9410bShenning if ((p = strrchr(s, '/')) != NULL) { 114994e9410bShenning if (mask != -1) { 115094e9410bShenning fprintf(stderr, "address with netmask specified" 115194e9410bShenning "and extra netmask supplied\n"); 115294e9410bShenning return (NULL); 115394e9410bShenning } 115494e9410bShenning mask = strtol(p+1, &q, 0); 115594e9410bShenning if (!q || *q) { 115694e9410bShenning fprintf(stderr, "invalid netmask\n"); 115794e9410bShenning return (NULL); 115894e9410bShenning } 1159e9275b6cShenning if ((buf = strdup(s)) == NULL) 1160e9275b6cShenning err(1, "host: strdup"); 1161a81c851cShenning if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 116294e9410bShenning err(1, "host: malloc"); 116394e9410bShenning strlcpy(ps, s, strlen(s) - strlen(p) + 1); 116494e9410bShenning v4mask = v6mask = mask; 116594e9410bShenning } else { 116694e9410bShenning if (asprintf(&ps, "%s", s) == -1) 116794e9410bShenning err(1, "host: asprintf"); 116894e9410bShenning if (mask == -1) { 116994e9410bShenning if (asprintf(&buf, "%s", s) == -1) 117094e9410bShenning err(1, "host: asprintf"); 117194e9410bShenning v4mask = 32; 117294e9410bShenning v6mask = 128; 117394e9410bShenning } else if (mask <= 128) { 117494e9410bShenning if (asprintf(&buf, "%s/%d", s, mask) == -1) 117594e9410bShenning err(1, "host: asprintf"); 117694e9410bShenning v4mask = v6mask = mask; 117794e9410bShenning } else { 117894e9410bShenning fprintf(stderr, "illegal mask\n"); 117994e9410bShenning return (NULL); 118094e9410bShenning } 118194e9410bShenning } 118294e9410bShenning 11832a6c1abaShenning /* interface with this name exists? */ 11844a36d485Shenning if (cont && (h = host_if(ps, mask)) != NULL) 11852a6c1abaShenning cont = 0; 11862a6c1abaShenning 11872a6c1abaShenning /* IPv4 address? */ 11882a6c1abaShenning if (cont && (h = host_v4(buf)) != NULL) 11892a6c1abaShenning cont = 0; 11902a6c1abaShenning free(buf); 11912a6c1abaShenning 11922a6c1abaShenning /* IPv6 address? */ 11932a6c1abaShenning if (cont && (h = host_v6(ps, v6mask)) != NULL) 11942a6c1abaShenning cont = 0; 11952a6c1abaShenning 11962a6c1abaShenning /* dns lookup */ 11972a6c1abaShenning if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL) 11982a6c1abaShenning cont = 0; 11992a6c1abaShenning free(ps); 12002a6c1abaShenning 12012a6c1abaShenning if (h == NULL || cont == 1) { 12022a6c1abaShenning fprintf(stderr, "no IP address found for %s\n", s); 12032a6c1abaShenning return (NULL); 12042a6c1abaShenning } 12052a6c1abaShenning return (h); 12062a6c1abaShenning } 12072a6c1abaShenning 12082a6c1abaShenning struct node_host * 1209f2370d27Shenning host_if(const char *s, int mask) 12102a6c1abaShenning { 12112a6c1abaShenning struct node_host *n, *h = NULL; 12124a36d485Shenning char *p, *ps; 12134a36d485Shenning int mode = PFCTL_IFLOOKUP_HOST; 12142a6c1abaShenning 12154a36d485Shenning if ((p = strrchr(s, ':')) != NULL && 12164a36d485Shenning (!strcmp(p+1, "network") || !strcmp(p+1, "broadcast"))) { 12174a36d485Shenning if (!strcmp(p+1, "network")) 12184a36d485Shenning mode = PFCTL_IFLOOKUP_NET; 12194a36d485Shenning if (!strcmp(p+1, "broadcast")) 12204a36d485Shenning mode = PFCTL_IFLOOKUP_BCAST; 12214a36d485Shenning if (mask > -1) { 12224a36d485Shenning fprintf(stderr, "network or broadcast lookup, but " 12234a36d485Shenning "extra netmask given\n"); 12244a36d485Shenning return (NULL); 12254a36d485Shenning } 12264a36d485Shenning if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 12274a36d485Shenning err(1, "host: malloc"); 12284a36d485Shenning strlcpy(ps, s, strlen(s) - strlen(p) + 1); 12294a36d485Shenning } else 12304a36d485Shenning if ((ps = strdup(s)) == NULL) 12314a36d485Shenning err(1, "host_if: strdup"); 12324a36d485Shenning 12334a36d485Shenning if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) { 12342a6c1abaShenning /* interface with this name exists */ 12354a36d485Shenning h = ifa_lookup(ps, mode); 12362a6c1abaShenning for (n = h; n != NULL && mask > -1; n = n->next) 12372a6c1abaShenning set_ipmask(n, mask); 12382a6c1abaShenning } 12394a36d485Shenning 12404a36d485Shenning free(ps); 12412a6c1abaShenning return (h); 12422a6c1abaShenning } 12432a6c1abaShenning 12442a6c1abaShenning struct node_host * 12456cba701cShenning host_v4(const char *s) 12462a6c1abaShenning { 12472a6c1abaShenning struct node_host *h = NULL; 12482a6c1abaShenning struct in_addr ina; 12492a6c1abaShenning int bits; 12502a6c1abaShenning 125194e9410bShenning memset(&ina, 0, sizeof(struct in_addr)); 12522a6c1abaShenning if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(&ina))) > -1) { 125394e9410bShenning h = calloc(1, sizeof(struct node_host)); 125494e9410bShenning if (h == NULL) 125594e9410bShenning err(1, "address: calloc"); 125694e9410bShenning h->ifname = NULL; 125794e9410bShenning h->af = AF_INET; 125894e9410bShenning h->addr.v.a.addr.addr32[0] = ina.s_addr; 125994e9410bShenning set_ipmask(h, bits); 126094e9410bShenning h->next = NULL; 126194e9410bShenning h->tail = h; 126294e9410bShenning } 12632a6c1abaShenning 126494e9410bShenning return (h); 126594e9410bShenning } 12662a6c1abaShenning 12672a6c1abaShenning struct node_host * 1268f2370d27Shenning host_v6(const char *s, int mask) 12692a6c1abaShenning { 12702a6c1abaShenning struct addrinfo hints, *res; 12712a6c1abaShenning struct node_host *h = NULL; 127294e9410bShenning 127394e9410bShenning memset(&hints, 0, sizeof(hints)); 127494e9410bShenning hints.ai_family = AF_INET6; 127594e9410bShenning hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 127694e9410bShenning hints.ai_flags = AI_NUMERICHOST; 12772a6c1abaShenning if (getaddrinfo(s, "0", &hints, &res) == 0) { 12782a6c1abaShenning h = calloc(1, sizeof(struct node_host)); 12792a6c1abaShenning if (h == NULL) 128094e9410bShenning err(1, "address: calloc"); 12812a6c1abaShenning h->ifname = NULL; 12822a6c1abaShenning h->af = AF_INET6; 12832a6c1abaShenning memcpy(&h->addr.v.a.addr, 128494e9410bShenning &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 12852a6c1abaShenning sizeof(h->addr.v.a.addr)); 12862a6c1abaShenning h->ifindex = 12872a6c1abaShenning ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 12882a6c1abaShenning set_ipmask(h, mask); 128994e9410bShenning freeaddrinfo(res); 12902a6c1abaShenning h->next = NULL; 12912a6c1abaShenning h->tail = h; 129294e9410bShenning } 129394e9410bShenning 12942a6c1abaShenning return (h); 12952a6c1abaShenning } 12962a6c1abaShenning 12972a6c1abaShenning struct node_host * 1298f2370d27Shenning host_dns(const char *s, int v4mask, int v6mask) 12992a6c1abaShenning { 13002a6c1abaShenning struct addrinfo hints, *res0, *res; 13012a6c1abaShenning struct node_host *n, *h = NULL; 13022a6c1abaShenning int error; 13032a6c1abaShenning 130494e9410bShenning memset(&hints, 0, sizeof(hints)); 130594e9410bShenning hints.ai_family = PF_UNSPEC; 130694e9410bShenning hints.ai_socktype = SOCK_STREAM; /* DUMMY */ 13072a6c1abaShenning error = getaddrinfo(s, NULL, &hints, &res0); 13082a6c1abaShenning if (error) 13092a6c1abaShenning return (h); 13102a6c1abaShenning 131194e9410bShenning for (res = res0; res; res = res->ai_next) { 131294e9410bShenning if (res->ai_family != AF_INET && 131394e9410bShenning res->ai_family != AF_INET6) 131494e9410bShenning continue; 131594e9410bShenning n = calloc(1, sizeof(struct node_host)); 131694e9410bShenning if (n == NULL) 13172a6c1abaShenning err(1, "host_dns: calloc"); 131894e9410bShenning n->ifname = NULL; 131994e9410bShenning n->af = res->ai_family; 132094e9410bShenning if (res->ai_family == AF_INET) { 132194e9410bShenning memcpy(&n->addr.v.a.addr, 13222a6c1abaShenning &((struct sockaddr_in *) 13232a6c1abaShenning res->ai_addr)->sin_addr.s_addr, 132494e9410bShenning sizeof(struct in_addr)); 132594e9410bShenning set_ipmask(n, v4mask); 132694e9410bShenning } else { 132794e9410bShenning memcpy(&n->addr.v.a.addr, 13282a6c1abaShenning &((struct sockaddr_in6 *) 13292a6c1abaShenning res->ai_addr)->sin6_addr.s6_addr, 133094e9410bShenning sizeof(struct in6_addr)); 133194e9410bShenning n->ifindex = 13322a6c1abaShenning ((struct sockaddr_in6 *) 13332a6c1abaShenning res->ai_addr)->sin6_scope_id; 133494e9410bShenning set_ipmask(n, v6mask); 133594e9410bShenning } 133694e9410bShenning n->next = NULL; 133794e9410bShenning n->tail = n; 133894e9410bShenning if (h == NULL) 133994e9410bShenning h = n; 134094e9410bShenning else { 134194e9410bShenning h->tail->next = n; 134294e9410bShenning h->tail = n; 134394e9410bShenning } 134494e9410bShenning } 134594e9410bShenning freeaddrinfo(res0); 134694e9410bShenning 134794e9410bShenning return (h); 134894e9410bShenning } 1349