1*132c30ccShenning /* $OpenBSD: pfctl_parser.c,v 1.147 2003/03/27 18:01:57 henning 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 *); 58*132c30ccShenning void print_port (u_int8_t, u_int16_t, u_int16_t, const 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); 66383ebbbfShenning struct node_host *host_v4(const char *, int); 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); 3048da4e377Smcbride else if (op == PF_OP_RRG) 3058da4e377Smcbride printf("%s:%s ", a1, a2); 3065d9ac2dcSdhartmei } 3075d9ac2dcSdhartmei 3085d9ac2dcSdhartmei void 309*132c30ccShenning print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto) 31014a9b182Skjell { 311e31d21c9Sdhartmei char a1[6], a2[6]; 312e4ebe044Shenning struct servent *s; 31381a15e5dSderaadt 314e4ebe044Shenning s = getservbyport(p1, proto); 31514a9b182Skjell p1 = ntohs(p1); 31614a9b182Skjell p2 = ntohs(p2); 3175d9ac2dcSdhartmei snprintf(a1, sizeof(a1), "%u", p1); 3185d9ac2dcSdhartmei snprintf(a2, sizeof(a2), "%u", p2); 31914a9b182Skjell printf("port "); 3205d9ac2dcSdhartmei if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE)) 3215d9ac2dcSdhartmei print_op(op, s->s_name, a2); 32214a9b182Skjell else 3235d9ac2dcSdhartmei print_op(op, a1, a2); 3245d9ac2dcSdhartmei } 3255d9ac2dcSdhartmei 3265d9ac2dcSdhartmei void 3275d9ac2dcSdhartmei print_uid(u_int8_t op, uid_t u1, uid_t u2, const char *t) 3285d9ac2dcSdhartmei { 329d8fcd2dfSdhartmei char a1[11], a2[11]; 3305d9ac2dcSdhartmei 3315d9ac2dcSdhartmei snprintf(a1, sizeof(a1), "%u", u1); 3325d9ac2dcSdhartmei snprintf(a2, sizeof(a2), "%u", u2); 3335d9ac2dcSdhartmei printf("%s ", t); 3345d9ac2dcSdhartmei if (u1 == UID_MAX && (op == PF_OP_EQ || op == PF_OP_NE)) 3355d9ac2dcSdhartmei print_op(op, "unknown", a2); 33614a9b182Skjell else 3375d9ac2dcSdhartmei print_op(op, a1, a2); 33814a9b182Skjell } 33914a9b182Skjell 34081a15e5dSderaadt void 341c16ab608Sdhartmei print_gid(u_int8_t op, gid_t g1, gid_t g2, const char *t) 342c16ab608Sdhartmei { 343d8fcd2dfSdhartmei char a1[11], a2[11]; 344c16ab608Sdhartmei 345c16ab608Sdhartmei snprintf(a1, sizeof(a1), "%u", g1); 346c16ab608Sdhartmei snprintf(a2, sizeof(a2), "%u", g2); 347c16ab608Sdhartmei printf("%s ", t); 348c16ab608Sdhartmei if (g1 == GID_MAX && (op == PF_OP_EQ || op == PF_OP_NE)) 349c16ab608Sdhartmei print_op(op, "unknown", a2); 350c16ab608Sdhartmei else 351c16ab608Sdhartmei print_op(op, a1, a2); 352c16ab608Sdhartmei } 353c16ab608Sdhartmei 354c16ab608Sdhartmei void 35514a9b182Skjell print_flags(u_int8_t f) 35614a9b182Skjell { 35714a9b182Skjell int i; 35881a15e5dSderaadt 359bc795af0Shugh for (i = 0; tcpflags[i]; ++i) 36014a9b182Skjell if (f & (1 << i)) 36114a9b182Skjell printf("%c", tcpflags[i]); 36214a9b182Skjell } 36314a9b182Skjell 36414a9b182Skjell void 36515e76891Sdhartmei print_fromto(struct pf_rule_addr *src, struct pf_rule_addr *dst, 36644f5ed0aScedric sa_family_t af, u_int8_t proto, int verbose) 36715e76891Sdhartmei { 368d0b1df00Sdhartmei if (src->addr.type != PF_ADDR_NOROUTE && 369d0b1df00Sdhartmei dst->addr.type != PF_ADDR_NOROUTE && 370bcf142a4Sdhartmei PF_AZERO(&src->addr.v.a.addr, AF_INET6) && 371bcf142a4Sdhartmei PF_AZERO(&src->addr.v.a.mask, AF_INET6) && 372bcf142a4Sdhartmei !src->port_op && PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && 373bcf142a4Sdhartmei PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && !dst->port_op) 37415e76891Sdhartmei printf("all "); 37515e76891Sdhartmei else { 37615e76891Sdhartmei printf("from "); 377d0b1df00Sdhartmei if (src->addr.type == PF_ADDR_NOROUTE) 37815e76891Sdhartmei printf("no-route "); 379bcf142a4Sdhartmei else if (PF_AZERO(&src->addr.v.a.addr, AF_INET6) && 380bcf142a4Sdhartmei PF_AZERO(&src->addr.v.a.mask, AF_INET6)) 38115e76891Sdhartmei printf("any "); 38215e76891Sdhartmei else { 38315e76891Sdhartmei if (src->not) 38415e76891Sdhartmei printf("! "); 38544f5ed0aScedric print_addr(&src->addr, af, verbose); 38615e76891Sdhartmei printf(" "); 38715e76891Sdhartmei } 38815e76891Sdhartmei if (src->port_op) 38915e76891Sdhartmei print_port(src->port_op, src->port[0], 39015e76891Sdhartmei src->port[1], 39115e76891Sdhartmei proto == IPPROTO_TCP ? "tcp" : "udp"); 39215e76891Sdhartmei 39315e76891Sdhartmei printf("to "); 394d0b1df00Sdhartmei if (dst->addr.type == PF_ADDR_NOROUTE) 39515e76891Sdhartmei printf("no-route "); 396bcf142a4Sdhartmei else if (PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && 397bcf142a4Sdhartmei PF_AZERO(&dst->addr.v.a.mask, AF_INET6)) 39815e76891Sdhartmei printf("any "); 39915e76891Sdhartmei else { 40015e76891Sdhartmei if (dst->not) 40115e76891Sdhartmei printf("! "); 40244f5ed0aScedric print_addr(&dst->addr, af, verbose); 40315e76891Sdhartmei printf(" "); 40415e76891Sdhartmei } 40515e76891Sdhartmei if (dst->port_op) 40615e76891Sdhartmei print_port(dst->port_op, dst->port[0], 40715e76891Sdhartmei dst->port[1], 40815e76891Sdhartmei proto == IPPROTO_TCP ? "tcp" : "udp"); 40915e76891Sdhartmei } 41015e76891Sdhartmei } 41115e76891Sdhartmei 41215e76891Sdhartmei void 413e8793aa9Smcbride print_rule(struct pf_rule *r, int verbose) 414e8793aa9Smcbride { 415e8793aa9Smcbride switch (r->action) { 416e8793aa9Smcbride case PF_NAT: 417e8793aa9Smcbride case PF_NONAT: 41860927d26Sdhartmei print_nat(r, verbose); 419e8793aa9Smcbride break; 420e8793aa9Smcbride case PF_BINAT: 421e8793aa9Smcbride case PF_NOBINAT: 42260927d26Sdhartmei print_binat(r, verbose); 423e8793aa9Smcbride break; 424e8793aa9Smcbride case PF_RDR: 425e8793aa9Smcbride case PF_NORDR: 42660927d26Sdhartmei print_rdr(r, verbose); 427e8793aa9Smcbride break; 428e8793aa9Smcbride default: 429e8793aa9Smcbride case PF_PASS: 430e8793aa9Smcbride case PF_DROP: 431e8793aa9Smcbride case PF_SCRUB: 432e8793aa9Smcbride print_filter(r, verbose); 433e8793aa9Smcbride break; 434e8793aa9Smcbride } 435e8793aa9Smcbride } 436e8793aa9Smcbride 437e8793aa9Smcbride void 438e0c302d0Smcbride print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2, 439e0c302d0Smcbride sa_family_t af, int id) 4403a44df3cSmcbride { 4413a44df3cSmcbride struct pf_pooladdr *pooladdr; 4423a44df3cSmcbride 4436c917913Smcbride if ((TAILQ_FIRST(&pool->list) != NULL) && 4446c917913Smcbride TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4453a44df3cSmcbride printf("{ "); 4463a44df3cSmcbride TAILQ_FOREACH(pooladdr, &pool->list, entries){ 4473a44df3cSmcbride switch (id) { 448e8793aa9Smcbride case PF_NAT: 449e8793aa9Smcbride case PF_RDR: 450e8793aa9Smcbride case PF_BINAT: 45144f5ed0aScedric print_addr(&pooladdr->addr.addr, af, 0); 4523a44df3cSmcbride break; 453e8793aa9Smcbride case PF_PASS: 454bcf142a4Sdhartmei if (PF_AZERO(&pooladdr->addr.addr.v.a.addr, af)) 4553b9b234fSmcbride printf("%s", pooladdr->ifname); 456790504a6Sdhartmei else { 4573a44df3cSmcbride printf("(%s ", pooladdr->ifname); 45844f5ed0aScedric print_addr(&pooladdr->addr.addr, af, 0); 4593a44df3cSmcbride printf(")"); 4603b9b234fSmcbride } 4613a44df3cSmcbride break; 462e8793aa9Smcbride default: 463e8793aa9Smcbride break; 4643a44df3cSmcbride } 4653a44df3cSmcbride if (TAILQ_NEXT(pooladdr, entries) != NULL) 4663a44df3cSmcbride printf(", "); 4673a44df3cSmcbride else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 4683a44df3cSmcbride printf(" }"); 4693a44df3cSmcbride } 470e0c302d0Smcbride switch (id) { 471e8793aa9Smcbride case PF_NAT: 472e0c302d0Smcbride if (p1 != PF_NAT_PROXY_PORT_LOW || 473e0c302d0Smcbride p2 != PF_NAT_PROXY_PORT_HIGH) { 474e0c302d0Smcbride if (p1 == p2) 475e0c302d0Smcbride printf(" port %u", p1); 476e0c302d0Smcbride else 477e0c302d0Smcbride printf(" port %u:%u", p1, p2); 478e0c302d0Smcbride } 479e0c302d0Smcbride break; 480e8793aa9Smcbride case PF_RDR: 481e0c302d0Smcbride if (p1) { 4828da4e377Smcbride printf(" port %u", p1); 4838da4e377Smcbride if (p2 && (p2 != p1)) 4848da4e377Smcbride printf(":%u", p2); 485e0c302d0Smcbride } 486e0c302d0Smcbride break; 487e0c302d0Smcbride default: 488e0c302d0Smcbride break; 489e0c302d0Smcbride } 490e0c302d0Smcbride switch (pool->opts & PF_POOL_TYPEMASK) { 491e0c302d0Smcbride case PF_POOL_NONE: 492e0c302d0Smcbride break; 493e0c302d0Smcbride case PF_POOL_BITMASK: 494e0c302d0Smcbride printf(" bitmask"); 495e0c302d0Smcbride break; 496e0c302d0Smcbride case PF_POOL_RANDOM: 497e0c302d0Smcbride printf(" random"); 498e0c302d0Smcbride break; 499e0c302d0Smcbride case PF_POOL_SRCHASH: 5000436fa02Smcbride printf(" source-hash 0x%08x%08x%08x%08x", 501e0c302d0Smcbride pool->key.key32[0], pool->key.key32[1], 502e0c302d0Smcbride pool->key.key32[2], pool->key.key32[3]); 503e0c302d0Smcbride break; 504e0c302d0Smcbride case PF_POOL_ROUNDROBIN: 505e0c302d0Smcbride printf(" round-robin"); 506e0c302d0Smcbride break; 507e0c302d0Smcbride } 508e0c302d0Smcbride if (pool->opts & PF_POOL_STATICPORT) 509e0c302d0Smcbride printf(" static-port"); 5103a44df3cSmcbride } 5113a44df3cSmcbride 5123a44df3cSmcbride void 51360927d26Sdhartmei print_nat(struct pf_rule *n, int verbose) 51414a9b182Skjell { 51560927d26Sdhartmei if (verbose) 51660927d26Sdhartmei printf("@%d ", n->nr); 5176ac94451Sdhartmei if (n->anchorname[0]) 5186ac94451Sdhartmei printf("nat-anchor %s ", n->anchorname); 5196ac94451Sdhartmei else { 520e8793aa9Smcbride if (n->action == PF_NONAT) 521f27db9bcSdhartmei printf("no "); 522f27db9bcSdhartmei printf("nat "); 5236ac94451Sdhartmei } 52428964e80Sdhartmei if (n->ifname[0]) { 52528964e80Sdhartmei printf("on "); 526870b51d7Schris if (n->ifnot) 527870b51d7Schris printf("! "); 528870b51d7Schris printf("%s ", n->ifname); 52928964e80Sdhartmei } 530032e40b7Sdhartmei if (n->af) { 531032e40b7Sdhartmei if (n->af == AF_INET) 532032e40b7Sdhartmei printf("inet "); 533032e40b7Sdhartmei else 534032e40b7Sdhartmei printf("inet6 "); 535032e40b7Sdhartmei } 53680edb1f0Sdhartmei if (n->proto) { 537e4ebe044Shenning struct protoent *p; 538ed99c291Sderaadt 539e4ebe044Shenning if ((p = getprotobynumber(n->proto)) != NULL) 54080edb1f0Sdhartmei printf("proto %s ", p->p_name); 54180edb1f0Sdhartmei else 54280edb1f0Sdhartmei printf("proto %u ", n->proto); 54380edb1f0Sdhartmei } 54444f5ed0aScedric print_fromto(&n->src, &n->dst, n->af, n->proto, verbose); 545e8793aa9Smcbride if (!n->anchorname[0] && (n->action == PF_NAT)) { 54628964e80Sdhartmei printf("-> "); 547e8793aa9Smcbride print_pool(&n->rpool, n->rpool.proxy_port[0], 548e8793aa9Smcbride n->rpool.proxy_port[1], n->af, PF_NAT); 549f27db9bcSdhartmei } 55014a9b182Skjell printf("\n"); 55114a9b182Skjell } 55214a9b182Skjell 55314a9b182Skjell void 55460927d26Sdhartmei print_binat(struct pf_rule *b, int verbose) 555a3e657d0Sjasoni { 55660927d26Sdhartmei if (verbose) 55760927d26Sdhartmei printf("@%d ", b->nr); 5586ac94451Sdhartmei if (b->anchorname[0]) 5596ac94451Sdhartmei printf("binat-anchor %s ", b->anchorname); 5606ac94451Sdhartmei else { 561e8793aa9Smcbride if (b->action == PF_NOBINAT) 562f27db9bcSdhartmei printf("no "); 563f27db9bcSdhartmei printf("binat "); 5646ac94451Sdhartmei } 565a3e657d0Sjasoni if (b->ifname[0]) { 566a3e657d0Sjasoni printf("on "); 567a3e657d0Sjasoni printf("%s ", b->ifname); 568a3e657d0Sjasoni } 569032e40b7Sdhartmei if (b->af) { 570032e40b7Sdhartmei if (b->af == AF_INET) 571032e40b7Sdhartmei printf("inet "); 572032e40b7Sdhartmei else 573032e40b7Sdhartmei printf("inet6 "); 574032e40b7Sdhartmei } 57580edb1f0Sdhartmei if (b->proto) { 576e4ebe044Shenning struct protoent *p; 577ed99c291Sderaadt 578e4ebe044Shenning if ((p = getprotobynumber(b->proto)) != NULL) 57980edb1f0Sdhartmei printf("proto %s ", p->p_name); 58080edb1f0Sdhartmei else 58180edb1f0Sdhartmei printf("proto %u ", b->proto); 582a3e657d0Sjasoni } 583fc8e917aScedric print_fromto(&b->src, &b->dst, b->af, b->proto, verbose); 584e8793aa9Smcbride if (!b->anchorname[0] && (b->action == PF_BINAT)) { 585a3e657d0Sjasoni printf("-> "); 586e8793aa9Smcbride print_pool(&b->rpool, 0, 0, b->af, PF_BINAT); 587f27db9bcSdhartmei } 588a3e657d0Sjasoni printf("\n"); 589a3e657d0Sjasoni } 590a3e657d0Sjasoni 591a3e657d0Sjasoni void 59260927d26Sdhartmei print_rdr(struct pf_rule *r, int verbose) 59314a9b182Skjell { 59460927d26Sdhartmei if (verbose) 59560927d26Sdhartmei printf("@%d ", r->nr); 5966ac94451Sdhartmei if (r->anchorname[0]) 5976ac94451Sdhartmei printf("rdr-anchor %s ", r->anchorname); 5986ac94451Sdhartmei else { 599e8793aa9Smcbride if (r->action == PF_NORDR) 600f27db9bcSdhartmei printf("no "); 601f27db9bcSdhartmei printf("rdr "); 6026ac94451Sdhartmei } 60328964e80Sdhartmei if (r->ifname[0]) { 60428964e80Sdhartmei printf("on "); 605870b51d7Schris if (r->ifnot) 606870b51d7Schris printf("! "); 607870b51d7Schris printf("%s ", r->ifname); 60828964e80Sdhartmei } 609032e40b7Sdhartmei if (r->af) { 610032e40b7Sdhartmei if (r->af == AF_INET) 611032e40b7Sdhartmei printf("inet "); 612032e40b7Sdhartmei else 613032e40b7Sdhartmei printf("inet6 "); 614032e40b7Sdhartmei } 61580edb1f0Sdhartmei if (r->proto) { 616e4ebe044Shenning struct protoent *p; 617ed99c291Sderaadt 618e4ebe044Shenning if ((p = getprotobynumber(r->proto)) != NULL) 61980edb1f0Sdhartmei printf("proto %s ", p->p_name); 62080edb1f0Sdhartmei else 62180edb1f0Sdhartmei printf("proto %u ", r->proto); 622e3d52469Smillert } 6238da4e377Smcbride print_fromto(&r->src, &r->dst, r->af, r->proto, verbose); 624e8793aa9Smcbride if (!r->anchorname[0] && (r->action == PF_RDR)) { 625cb07131dSkjell printf("-> "); 626e8793aa9Smcbride print_pool(&r->rpool, r->rpool.proxy_port[0], 627120f430eSmcbride r->rpool.proxy_port[1], r->af, PF_RDR); 628f27db9bcSdhartmei } 62914a9b182Skjell printf("\n"); 63014a9b182Skjell } 63114a9b182Skjell 632*132c30ccShenning const char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 633*132c30ccShenning const char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 63499a73934Sderaadt 63514a9b182Skjell void 63681a15e5dSderaadt print_status(struct pf_status *s) 63714a9b182Skjell { 638e4ebe044Shenning char statline[80]; 639c474e331Shenning time_t runtime; 64099a73934Sderaadt int i; 64199a73934Sderaadt 642c474e331Shenning runtime = time(NULL) - s->since; 643c474e331Shenning 644d85e4ad6Sdhartmei if (s->running) { 645d85e4ad6Sdhartmei unsigned sec, min, hrs, day = runtime; 646d85e4ad6Sdhartmei 647d85e4ad6Sdhartmei sec = day % 60; 648d85e4ad6Sdhartmei day /= 60; 649d85e4ad6Sdhartmei min = day % 60; 650d85e4ad6Sdhartmei day /= 60; 651d85e4ad6Sdhartmei hrs = day % 24; 652d85e4ad6Sdhartmei day /= 24; 653c474e331Shenning snprintf(statline, sizeof(statline), 654d85e4ad6Sdhartmei "Status: Enabled for %u days %.2u:%.2u:%.2u", 655d85e4ad6Sdhartmei day, hrs, min, sec); 656d85e4ad6Sdhartmei } else 657c474e331Shenning snprintf(statline, sizeof(statline), "Status: Disabled"); 658c97b4ee1Shenning printf("%-44s", statline); 659ae58c8acSdhartmei switch (s->debug) { 660ae58c8acSdhartmei case 0: 661c97b4ee1Shenning printf("%15s\n\n", "Debug: None"); 662ae58c8acSdhartmei break; 663ae58c8acSdhartmei case 1: 664c97b4ee1Shenning printf("%15s\n\n", "Debug: Urgent"); 665ae58c8acSdhartmei break; 666ae58c8acSdhartmei case 2: 667c97b4ee1Shenning printf("%15s\n\n", "Debug: Misc"); 668ae58c8acSdhartmei break; 669ae58c8acSdhartmei } 670c474e331Shenning if (s->ifname[0] != 0) { 671c474e331Shenning printf("Interface Stats for %-16s %5s %16s\n", 672c474e331Shenning s->ifname, "IPv4", "IPv6"); 673c474e331Shenning printf(" %-25s %14llu %16llu\n", "Bytes In", 6747189e280Sdhartmei s->bcounters[0][0], s->bcounters[1][0]); 675c474e331Shenning printf(" %-25s %14llu %16llu\n", "Bytes Out", 6767189e280Sdhartmei s->bcounters[0][1], s->bcounters[1][1]); 677c474e331Shenning printf(" Packets In\n"); 678c474e331Shenning printf(" %-23s %14llu %16llu\n", "Passed", 6797189e280Sdhartmei s->pcounters[0][0][PF_PASS], 6807189e280Sdhartmei s->pcounters[1][0][PF_PASS]); 681c474e331Shenning printf(" %-23s %14llu %16llu\n", "Blocked", 6827189e280Sdhartmei s->pcounters[0][0][PF_DROP], 6837189e280Sdhartmei s->pcounters[1][0][PF_DROP]); 684c474e331Shenning printf(" Packets Out\n"); 685c474e331Shenning printf(" %-23s %14llu %16llu\n", "Passed", 6867189e280Sdhartmei s->pcounters[0][1][PF_PASS], 6877189e280Sdhartmei s->pcounters[1][1][PF_PASS]); 688c474e331Shenning printf(" %-23s %14llu %16llu\n\n", "Blocked", 6897189e280Sdhartmei s->pcounters[0][1][PF_DROP], 6907189e280Sdhartmei s->pcounters[1][1][PF_DROP]); 691c474e331Shenning } 692c474e331Shenning printf("%-27s %14s %16s\n", "State Table", "Total", "Rate"); 693c474e331Shenning printf(" %-25s %14u %14s\n", "current entries", s->states, ""); 694c474e331Shenning for (i = 0; i < FCNT_MAX; i++) { 695c474e331Shenning printf(" %-25s %14lld ", pf_fcounters[i], 69684976600Sderaadt s->fcounters[i]); 697c474e331Shenning if (runtime > 0) 698c474e331Shenning printf("%14.1f/s\n", 699c474e331Shenning (double)s->fcounters[i] / (double)runtime); 700c474e331Shenning else 701c474e331Shenning printf("%14s\n", ""); 702c474e331Shenning } 70399a73934Sderaadt printf("Counters\n"); 704c474e331Shenning for (i = 0; i < PFRES_MAX; i++) { 705c474e331Shenning printf(" %-25s %14lld ", pf_reasons[i], 70699a73934Sderaadt s->counters[i]); 707c474e331Shenning if (runtime > 0) 708c474e331Shenning printf("%14.1f/s\n", 709c474e331Shenning (double)s->counters[i] / (double)runtime); 710c474e331Shenning else 711c474e331Shenning printf("%14s\n", ""); 712c474e331Shenning } 71314a9b182Skjell } 71414a9b182Skjell 71514a9b182Skjell void 716e8793aa9Smcbride print_filter(struct pf_rule *r, int verbose) 71714a9b182Skjell { 718cc5f0329Sdhartmei int i, opts; 719cc5f0329Sdhartmei 72074dc4fddShenning if (verbose) 72178baf774Sdhartmei printf("@%d ", r->nr); 7226ac94451Sdhartmei if (r->anchorname[0]) 7236ac94451Sdhartmei printf("anchor %s ", r->anchorname); 7246ac94451Sdhartmei else if (r->action == PF_PASS) 72514a9b182Skjell printf("pass "); 726b996d042Sdhartmei else if (r->action == PF_DROP) { 72714a9b182Skjell printf("block "); 7288a87542aShenning if (r->rule_flag & PFRULE_RETURN) 7298a87542aShenning printf("return "); 7308a87542aShenning else if (r->rule_flag & PFRULE_RETURNRST) { 7311f77cc8aSpb if (!r->return_ttl) 73214a9b182Skjell printf("return-rst "); 7331f77cc8aSpb else 7341f77cc8aSpb printf("return-rst(ttl %d) ", r->return_ttl); 735328b2decShenning } else if (r->rule_flag & PFRULE_RETURNICMP) { 736328b2decShenning const struct icmpcodeent *ic, *ic6; 737b996d042Sdhartmei 738b996d042Sdhartmei ic = geticmpcodebynumber(r->return_icmp >> 8, 739328b2decShenning r->return_icmp & 255, AF_INET); 740328b2decShenning ic6 = geticmpcodebynumber(r->return_icmp6 >> 8, 741328b2decShenning r->return_icmp6 & 255, AF_INET6); 742d14c53d7Swilfried 743328b2decShenning switch(r->af) { 744328b2decShenning case AF_INET: 745328b2decShenning printf("return-icmp"); 746d14c53d7Swilfried if (ic == NULL) 747d14c53d7Swilfried printf("(%u) ", r->return_icmp & 255); 748b996d042Sdhartmei else 749328b2decShenning printf("(%s) ", ic->name); 750328b2decShenning break; 751328b2decShenning case AF_INET6: 752328b2decShenning printf("return-icmp6"); 753328b2decShenning if (ic6 == NULL) 754328b2decShenning printf("(%u) ", r->return_icmp6 & 255); 755328b2decShenning else 756328b2decShenning printf("(%s) ", ic6->name); 757328b2decShenning break; 758328b2decShenning default: 759328b2decShenning printf("return-icmp"); 760328b2decShenning if (ic == NULL) 761328b2decShenning printf("(%u, ", r->return_icmp & 255); 762328b2decShenning else 763328b2decShenning printf("(%s, ", ic->name); 764328b2decShenning if (ic6 == NULL) 765328b2decShenning printf("%u) ", r->return_icmp6 & 255); 766328b2decShenning else 767328b2decShenning printf("%s) ", ic6->name); 768328b2decShenning break; 769328b2decShenning } 770acf2444cShenning } else 771acf2444cShenning printf("drop "); 7726ac94451Sdhartmei } else 773b996d042Sdhartmei printf("scrub "); 7747189e280Sdhartmei if (r->direction == PF_IN) 77514a9b182Skjell printf("in "); 7767189e280Sdhartmei else if (r->direction == PF_OUT) 77714a9b182Skjell printf("out "); 7787242ce7aSdhartmei if (r->log == 1) 77914a9b182Skjell printf("log "); 7807242ce7aSdhartmei else if (r->log == 2) 7817242ce7aSdhartmei printf("log-all "); 78214a9b182Skjell if (r->quick) 78314a9b182Skjell printf("quick "); 7847d0c9138Shenning if (r->ifname[0]) { 7857d0c9138Shenning if (r->ifnot) 7867d0c9138Shenning printf("on ! %s ", r->ifname); 7877d0c9138Shenning else 78814a9b182Skjell printf("on %s ", r->ifname); 7897d0c9138Shenning } 790cb3a4e31Sjasoni if (r->rt) { 791cb3a4e31Sjasoni if (r->rt == PF_ROUTETO) 792cb3a4e31Sjasoni printf("route-to "); 793fa1cdd09Sdhartmei else if (r->rt == PF_REPLYTO) 794fa1cdd09Sdhartmei printf("reply-to "); 795cb3a4e31Sjasoni else if (r->rt == PF_DUPTO) 796cb3a4e31Sjasoni printf("dup-to "); 797cb3a4e31Sjasoni else if (r->rt == PF_FASTROUTE) 798cb3a4e31Sjasoni printf("fastroute "); 799790504a6Sdhartmei if (r->rt != PF_FASTROUTE) { 800e8793aa9Smcbride print_pool(&r->rpool, 0, 0, r->af, PF_PASS); 801790504a6Sdhartmei printf(" "); 802790504a6Sdhartmei } 803cb3a4e31Sjasoni } 80430620b12Sfrantzen if (r->af) { 80530620b12Sfrantzen if (r->af == AF_INET) 80630620b12Sfrantzen printf("inet "); 80730620b12Sfrantzen else 80830620b12Sfrantzen printf("inet6 "); 80930620b12Sfrantzen } 81014a9b182Skjell if (r->proto) { 811e4ebe044Shenning struct protoent *p; 812ed99c291Sderaadt 813e4ebe044Shenning if ((p = getprotobynumber(r->proto)) != NULL) 81414a9b182Skjell printf("proto %s ", p->p_name); 81514a9b182Skjell else 81614a9b182Skjell printf("proto %u ", r->proto); 81714a9b182Skjell } 81844f5ed0aScedric print_fromto(&r->src, &r->dst, r->af, r->proto, verbose); 819c16ab608Sdhartmei if (r->uid.op) 820c16ab608Sdhartmei print_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user"); 821c16ab608Sdhartmei if (r->gid.op) 822c16ab608Sdhartmei print_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group"); 82314a9b182Skjell if (r->flags || r->flagset) { 82414a9b182Skjell printf("flags "); 82514a9b182Skjell print_flags(r->flags); 82614a9b182Skjell printf("/"); 82714a9b182Skjell print_flags(r->flagset); 82814a9b182Skjell printf(" "); 82914a9b182Skjell } 830082ebc44Swilfried if (r->type) { 831b49ca6bbShenning const struct icmptypeent *it; 832082ebc44Swilfried 833b49ca6bbShenning it = geticmptypebynumber(r->type-1, r->af); 834d14c53d7Swilfried if (r->af != AF_INET6) 835d14c53d7Swilfried printf("icmp-type"); 836082ebc44Swilfried else 837d0cb3502Smcbride printf("icmp6-type"); 838b49ca6bbShenning if (it != NULL) 839b49ca6bbShenning printf(" %s ", it->name); 840d14c53d7Swilfried else 841d14c53d7Swilfried printf(" %u ", r->type-1); 842082ebc44Swilfried if (r->code) { 843b49ca6bbShenning const struct icmpcodeent *ic; 844082ebc44Swilfried 845b49ca6bbShenning ic = geticmpcodebynumber(r->type-1, r->code-1, r->af); 846b49ca6bbShenning if (ic != NULL) 847b49ca6bbShenning printf("code %s ", ic->name); 848082ebc44Swilfried else 84914a9b182Skjell printf("code %u ", r->code-1); 850082ebc44Swilfried } 851082ebc44Swilfried } 852e4cbe364Sdhartmei if (r->tos) 853e4cbe364Sdhartmei printf("tos 0x%2.2x ", r->tos); 854b96c47abSfrantzen if (r->keep_state == PF_STATE_NORMAL) 85514a9b182Skjell printf("keep state "); 856b96c47abSfrantzen else if (r->keep_state == PF_STATE_MODULATE) 857b96c47abSfrantzen printf("modulate state "); 858cc5f0329Sdhartmei opts = 0; 859b3c86969Sdhartmei if (r->max_states) 860cc5f0329Sdhartmei opts = 1; 861cc5f0329Sdhartmei for (i = 0; !opts && i < PFTM_MAX; ++i) 862cc5f0329Sdhartmei if (r->timeout[i]) 863cc5f0329Sdhartmei opts = 1; 864cc5f0329Sdhartmei if (opts) { 865cc5f0329Sdhartmei printf("("); 866cc5f0329Sdhartmei if (r->max_states) { 867cc5f0329Sdhartmei printf("max %u", r->max_states); 868cc5f0329Sdhartmei opts = 0; 869cc5f0329Sdhartmei } 870cc5f0329Sdhartmei for (i = 0; i < PFTM_MAX; ++i) 871cc5f0329Sdhartmei if (r->timeout[i]) { 872cc5f0329Sdhartmei if (!opts) 873cc5f0329Sdhartmei printf(", "); 874cc5f0329Sdhartmei opts = 0; 875cc5f0329Sdhartmei printf("%s %u", pf_timeouts[i].name, 876cc5f0329Sdhartmei r->timeout[i]); 877cc5f0329Sdhartmei } 878cc5f0329Sdhartmei printf(") "); 879cc5f0329Sdhartmei } 8806673dee2Sdhartmei if (r->rule_flag & PFRULE_FRAGMENT) 8816673dee2Sdhartmei printf("fragment "); 88267d2a440Sprovos if (r->rule_flag & PFRULE_NODF) 88367d2a440Sprovos printf("no-df "); 884edbe3066Sdhartmei if (r->rule_flag & PFRULE_RANDOMID) 885edbe3066Sdhartmei printf("random-id "); 886e258bfd4Sprovos if (r->min_ttl) 88734c76dcbSprovos printf("min-ttl %d ", r->min_ttl); 888cfa91859Sjasoni if (r->max_mss) 889cfa91859Sjasoni printf("max-mss %d ", r->max_mss); 890f48d62b3Sdhartmei if (r->allow_opts) 891f48d62b3Sdhartmei printf("allow-opts "); 892b02af636Sfrantzen if (r->action == PF_SCRUB) { 893b02af636Sfrantzen if (r->rule_flag & PFRULE_FRAGDROP) 894b02af636Sfrantzen printf("fragment drop-ovl "); 895b02af636Sfrantzen else if (r->rule_flag & PFRULE_FRAGCROP) 896b02af636Sfrantzen printf("fragment crop "); 897b02af636Sfrantzen else 898b02af636Sfrantzen printf("fragment reassemble "); 899b02af636Sfrantzen } 900455ef0c1Sdhartmei if (r->label[0]) 901ff45dfa8Scamield printf("label \"%s\" ", r->label); 902f98324c6Shenning if (r->qname[0] && r->pqname[0]) 903f98324c6Shenning printf("queue(%s, %s) ", r->qname, r->pqname); 904f98324c6Shenning else if (r->qname[0]) 90578e1d2a6Shenning printf("queue %s ", r->qname); 90667d2a440Sprovos 90714a9b182Skjell printf("\n"); 90814a9b182Skjell } 90914a9b182Skjell 9101f8f21bdSmillert int 911ff352a37Smarkus parse_flags(char *s) 91214a9b182Skjell { 913ff352a37Smarkus char *p, *q; 91414a9b182Skjell u_int8_t f = 0; 91581a15e5dSderaadt 916ff352a37Smarkus for (p = s; *p; p++) { 917ff352a37Smarkus if ((q = strchr(tcpflags, *p)) == NULL) 918ff352a37Smarkus return -1; 919ff352a37Smarkus else 920ff352a37Smarkus f |= 1 << (q - tcpflags); 92114a9b182Skjell } 922bc795af0Shugh return (f ? f : PF_TH_ALL); 92314a9b182Skjell } 92494e9410bShenning 92594e9410bShenning void 92694e9410bShenning set_ipmask(struct node_host *h, u_int8_t b) 92794e9410bShenning { 92894e9410bShenning struct pf_addr *m, *n; 92994e9410bShenning int i, j = 0; 93094e9410bShenning 93194e9410bShenning m = &h->addr.v.a.mask; 93294e9410bShenning 93394e9410bShenning for (i = 0; i < 4; i++) 93494e9410bShenning m->addr32[i] = 0; 93594e9410bShenning 93694e9410bShenning while (b >= 32) { 93794e9410bShenning m->addr32[j++] = 0xffffffff; 93894e9410bShenning b -= 32; 93994e9410bShenning } 94094e9410bShenning for (i = 31; i > 31-b; --i) 94194e9410bShenning m->addr32[j] |= (1 << i); 94294e9410bShenning if (b) 94394e9410bShenning m->addr32[j] = htonl(m->addr32[j]); 94494e9410bShenning 94594e9410bShenning /* Mask off bits of the address that will never be used. */ 94694e9410bShenning n = &h->addr.v.a.addr; 94794e9410bShenning for (i = 0; i < 4; i++) 94894e9410bShenning n->addr32[i] = n->addr32[i] & m->addr32[i]; 94994e9410bShenning } 95094e9410bShenning 95194e9410bShenning /* interface lookup routines */ 95294e9410bShenning 95394e9410bShenning struct node_host *iftab; 95494e9410bShenning 95594e9410bShenning void 95694e9410bShenning ifa_load(void) 95794e9410bShenning { 95894e9410bShenning struct ifaddrs *ifap, *ifa; 95994e9410bShenning struct node_host *n = NULL, *h = NULL; 96094e9410bShenning 96194e9410bShenning if (getifaddrs(&ifap) < 0) 96294e9410bShenning err(1, "getifaddrs"); 96394e9410bShenning 96494e9410bShenning for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 96594e9410bShenning if (!(ifa->ifa_addr->sa_family == AF_INET || 96694e9410bShenning ifa->ifa_addr->sa_family == AF_INET6 || 96794e9410bShenning ifa->ifa_addr->sa_family == AF_LINK)) 96894e9410bShenning continue; 96994e9410bShenning n = calloc(1, sizeof(struct node_host)); 97094e9410bShenning if (n == NULL) 97194e9410bShenning err(1, "address: calloc"); 97294e9410bShenning n->af = ifa->ifa_addr->sa_family; 97394e9410bShenning n->ifa_flags = ifa->ifa_flags; 97494e9410bShenning #ifdef __KAME__ 97594e9410bShenning if (n->af == AF_INET6 && 97694e9410bShenning IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) 97794e9410bShenning ifa->ifa_addr)->sin6_addr) && 97894e9410bShenning ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 0) { 97994e9410bShenning struct sockaddr_in6 *sin6; 98094e9410bShenning 98194e9410bShenning sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 98294e9410bShenning sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | 98394e9410bShenning sin6->sin6_addr.s6_addr[3]; 98494e9410bShenning sin6->sin6_addr.s6_addr[2] = 0; 98594e9410bShenning sin6->sin6_addr.s6_addr[3] = 0; 98694e9410bShenning } 98794e9410bShenning #endif 98894e9410bShenning n->ifindex = 0; 98994e9410bShenning if (n->af == AF_INET) { 99094e9410bShenning memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) 99194e9410bShenning ifa->ifa_addr)->sin_addr.s_addr, 99294e9410bShenning sizeof(struct in_addr)); 99394e9410bShenning memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) 99494e9410bShenning ifa->ifa_netmask)->sin_addr.s_addr, 99594e9410bShenning sizeof(struct in_addr)); 99694e9410bShenning if (ifa->ifa_broadaddr != NULL) 99794e9410bShenning memcpy(&n->bcast, &((struct sockaddr_in *) 99894e9410bShenning ifa->ifa_broadaddr)->sin_addr.s_addr, 99994e9410bShenning sizeof(struct in_addr)); 100094e9410bShenning } else if (n->af == AF_INET6) { 100194e9410bShenning memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) 100294e9410bShenning ifa->ifa_addr)->sin6_addr.s6_addr, 100394e9410bShenning sizeof(struct in6_addr)); 100494e9410bShenning memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) 100594e9410bShenning ifa->ifa_netmask)->sin6_addr.s6_addr, 100694e9410bShenning sizeof(struct in6_addr)); 100794e9410bShenning if (ifa->ifa_broadaddr != NULL) 100894e9410bShenning memcpy(&n->bcast, &((struct sockaddr_in6 *) 100994e9410bShenning ifa->ifa_broadaddr)->sin6_addr.s6_addr, 101094e9410bShenning sizeof(struct in6_addr)); 101194e9410bShenning n->ifindex = ((struct sockaddr_in6 *) 101294e9410bShenning ifa->ifa_addr)->sin6_scope_id; 101394e9410bShenning } 101494e9410bShenning if ((n->ifname = strdup(ifa->ifa_name)) == NULL) 101594e9410bShenning err(1, "ifa_load: strdup"); 101694e9410bShenning n->next = NULL; 101794e9410bShenning n->tail = n; 101894e9410bShenning if (h == NULL) 101994e9410bShenning h = n; 102094e9410bShenning else { 102194e9410bShenning h->tail->next = n; 102294e9410bShenning h->tail = n; 102394e9410bShenning } 102494e9410bShenning } 102594e9410bShenning iftab = h; 102694e9410bShenning freeifaddrs(ifap); 102794e9410bShenning } 102894e9410bShenning 102994e9410bShenning struct node_host * 10306cba701cShenning ifa_exists(const char *ifa_name) 103194e9410bShenning { 103294e9410bShenning struct node_host *n; 103394e9410bShenning 103494e9410bShenning if (iftab == NULL) 103594e9410bShenning ifa_load(); 103694e9410bShenning 103794e9410bShenning for (n = iftab; n; n = n->next) { 103894e9410bShenning if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) 103994e9410bShenning return (n); 104094e9410bShenning } 104194e9410bShenning return (NULL); 104294e9410bShenning } 104394e9410bShenning 104494e9410bShenning struct node_host * 10456cba701cShenning ifa_lookup(const char *ifa_name, enum pfctl_iflookup_mode mode) 104694e9410bShenning { 104794e9410bShenning struct node_host *p = NULL, *h = NULL, *n = NULL; 104894e9410bShenning int return_all = 0; 104994e9410bShenning 105094e9410bShenning if (!strncmp(ifa_name, "self", IFNAMSIZ)) 105194e9410bShenning return_all = 1; 105294e9410bShenning 105394e9410bShenning if (iftab == NULL) 105494e9410bShenning ifa_load(); 105594e9410bShenning 105694e9410bShenning for (p = iftab; p; p = p->next) { 105794e9410bShenning if (!((p->af == AF_INET || p->af == AF_INET6) && 105894e9410bShenning (!strncmp(p->ifname, ifa_name, IFNAMSIZ) || return_all))) 105994e9410bShenning continue; 106094e9410bShenning if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET) 106194e9410bShenning continue; 106294e9410bShenning if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0) 106394e9410bShenning continue; 106494e9410bShenning n = calloc(1, sizeof(struct node_host)); 106594e9410bShenning if (n == NULL) 106694e9410bShenning err(1, "address: calloc"); 106794e9410bShenning n->af = p->af; 106894e9410bShenning if (mode == PFCTL_IFLOOKUP_BCAST) 106994e9410bShenning memcpy(&n->addr.v.a.addr, &p->bcast, 107094e9410bShenning sizeof(struct pf_addr)); 107194e9410bShenning else 107294e9410bShenning memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, 107394e9410bShenning sizeof(struct pf_addr)); 107494e9410bShenning if (mode == PFCTL_IFLOOKUP_NET) 107594e9410bShenning set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); 107694e9410bShenning else { 107794e9410bShenning if (n->af == AF_INET) { 107894e9410bShenning if (p->ifa_flags & IFF_LOOPBACK && 107994e9410bShenning p->ifa_flags & IFF_LINK1) 108094e9410bShenning memcpy(&n->addr.v.a.mask, 108194e9410bShenning &p->addr.v.a.mask, 108294e9410bShenning sizeof(struct pf_addr)); 108394e9410bShenning else 108494e9410bShenning set_ipmask(n, 32); 108594e9410bShenning } else 108694e9410bShenning set_ipmask(n, 128); 108794e9410bShenning } 108894e9410bShenning n->ifindex = p->ifindex; 108994e9410bShenning 109094e9410bShenning n->next = NULL; 109194e9410bShenning n->tail = n; 109294e9410bShenning if (h == NULL) 109394e9410bShenning h = n; 109494e9410bShenning else { 109594e9410bShenning h->tail->next = n; 109694e9410bShenning h->tail = n; 109794e9410bShenning } 109894e9410bShenning } 109994e9410bShenning if (h == NULL && mode == PFCTL_IFLOOKUP_HOST) { 110094e9410bShenning fprintf(stderr, "no IP address found for %s\n", ifa_name); 110194e9410bShenning } 110294e9410bShenning return (h); 110394e9410bShenning } 110494e9410bShenning 110594e9410bShenning struct node_host * 11066cba701cShenning host(const char *s, int mask) 110794e9410bShenning { 11082a6c1abaShenning struct node_host *h = NULL; 11092a6c1abaShenning int v4mask, v6mask, cont = 1; 111094e9410bShenning char *buf = NULL, *p, *q, *ps; 111194e9410bShenning 111294e9410bShenning if ((p = strrchr(s, '/')) != NULL) { 111394e9410bShenning if (mask != -1) { 111494e9410bShenning fprintf(stderr, "address with netmask specified" 111594e9410bShenning " and extra netmask supplied\n"); 111694e9410bShenning return (NULL); 111794e9410bShenning } 111894e9410bShenning mask = strtol(p+1, &q, 0); 111994e9410bShenning if (!q || *q) { 112094e9410bShenning fprintf(stderr, "invalid netmask\n"); 112194e9410bShenning return (NULL); 112294e9410bShenning } 1123e9275b6cShenning if ((buf = strdup(s)) == NULL) 1124e9275b6cShenning err(1, "host: strdup"); 1125a81c851cShenning if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 112694e9410bShenning err(1, "host: malloc"); 112794e9410bShenning strlcpy(ps, s, strlen(s) - strlen(p) + 1); 112894e9410bShenning v4mask = v6mask = mask; 112994e9410bShenning } else { 113094e9410bShenning if (asprintf(&ps, "%s", s) == -1) 113194e9410bShenning err(1, "host: asprintf"); 113294e9410bShenning if (mask == -1) { 113394e9410bShenning if (asprintf(&buf, "%s", s) == -1) 113494e9410bShenning err(1, "host: asprintf"); 113594e9410bShenning v4mask = 32; 113694e9410bShenning v6mask = 128; 113794e9410bShenning } else if (mask <= 128) { 113894e9410bShenning if (asprintf(&buf, "%s/%d", s, mask) == -1) 113994e9410bShenning err(1, "host: asprintf"); 114094e9410bShenning v4mask = v6mask = mask; 114194e9410bShenning } else { 114211bd6590Shenning fprintf(stderr, "illegal mask %d\n", mask); 114394e9410bShenning return (NULL); 114494e9410bShenning } 114594e9410bShenning } 114694e9410bShenning 11472a6c1abaShenning /* interface with this name exists? */ 11484a36d485Shenning if (cont && (h = host_if(ps, mask)) != NULL) 11492a6c1abaShenning cont = 0; 11502a6c1abaShenning 11512a6c1abaShenning /* IPv4 address? */ 1152383ebbbfShenning if (cont && (h = host_v4(buf, mask)) != NULL) 11532a6c1abaShenning cont = 0; 11542a6c1abaShenning free(buf); 11552a6c1abaShenning 11562a6c1abaShenning /* IPv6 address? */ 11572a6c1abaShenning if (cont && (h = host_v6(ps, v6mask)) != NULL) 11582a6c1abaShenning cont = 0; 11592a6c1abaShenning 11602a6c1abaShenning /* dns lookup */ 11612a6c1abaShenning if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL) 11622a6c1abaShenning cont = 0; 11632a6c1abaShenning free(ps); 11642a6c1abaShenning 11652a6c1abaShenning if (h == NULL || cont == 1) { 11662a6c1abaShenning fprintf(stderr, "no IP address found for %s\n", s); 11672a6c1abaShenning return (NULL); 11682a6c1abaShenning } 11692a6c1abaShenning return (h); 11702a6c1abaShenning } 11712a6c1abaShenning 11722a6c1abaShenning struct node_host * 1173f2370d27Shenning host_if(const char *s, int mask) 11742a6c1abaShenning { 11752a6c1abaShenning struct node_host *n, *h = NULL; 11764a36d485Shenning char *p, *ps; 11774a36d485Shenning int mode = PFCTL_IFLOOKUP_HOST; 11782a6c1abaShenning 11794a36d485Shenning if ((p = strrchr(s, ':')) != NULL && 11804a36d485Shenning (!strcmp(p+1, "network") || !strcmp(p+1, "broadcast"))) { 11814a36d485Shenning if (!strcmp(p+1, "network")) 11824a36d485Shenning mode = PFCTL_IFLOOKUP_NET; 11834a36d485Shenning if (!strcmp(p+1, "broadcast")) 11844a36d485Shenning mode = PFCTL_IFLOOKUP_BCAST; 11854a36d485Shenning if (mask > -1) { 11864a36d485Shenning fprintf(stderr, "network or broadcast lookup, but " 11874a36d485Shenning "extra netmask given\n"); 11884a36d485Shenning return (NULL); 11894a36d485Shenning } 11904a36d485Shenning if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 11914a36d485Shenning err(1, "host: malloc"); 11924a36d485Shenning strlcpy(ps, s, strlen(s) - strlen(p) + 1); 11934a36d485Shenning } else 11944a36d485Shenning if ((ps = strdup(s)) == NULL) 11954a36d485Shenning err(1, "host_if: strdup"); 11964a36d485Shenning 11974a36d485Shenning if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) { 11982a6c1abaShenning /* interface with this name exists */ 11994a36d485Shenning h = ifa_lookup(ps, mode); 12002a6c1abaShenning for (n = h; n != NULL && mask > -1; n = n->next) 12012a6c1abaShenning set_ipmask(n, mask); 12022a6c1abaShenning } 12034a36d485Shenning 12044a36d485Shenning free(ps); 12052a6c1abaShenning return (h); 12062a6c1abaShenning } 12072a6c1abaShenning 12082a6c1abaShenning struct node_host * 1209383ebbbfShenning host_v4(const char *s, int mask) 12102a6c1abaShenning { 12112a6c1abaShenning struct node_host *h = NULL; 12122a6c1abaShenning struct in_addr ina; 12132a6c1abaShenning int bits; 12142a6c1abaShenning 121594e9410bShenning memset(&ina, 0, sizeof(struct in_addr)); 12163c58a40aScedric if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) > -1) { 121794e9410bShenning h = calloc(1, sizeof(struct node_host)); 121894e9410bShenning if (h == NULL) 121994e9410bShenning err(1, "address: calloc"); 122094e9410bShenning h->ifname = NULL; 122194e9410bShenning h->af = AF_INET; 122294e9410bShenning h->addr.v.a.addr.addr32[0] = ina.s_addr; 1223383ebbbfShenning /* inet_net_pton acts strange w/ multicast addresses, RFC1112 */ 1224383ebbbfShenning if (mask == -1 && h->addr.v.a.addr.addr8[0] >= 224 && 1225383ebbbfShenning h->addr.v.a.addr.addr8[0] < 240) 1226383ebbbfShenning bits = 32; 122794e9410bShenning set_ipmask(h, bits); 122894e9410bShenning h->next = NULL; 122994e9410bShenning h->tail = h; 123094e9410bShenning } 12312a6c1abaShenning 123294e9410bShenning return (h); 123394e9410bShenning } 12342a6c1abaShenning 12352a6c1abaShenning struct node_host * 1236f2370d27Shenning host_v6(const char *s, int mask) 12372a6c1abaShenning { 12382a6c1abaShenning struct addrinfo hints, *res; 12392a6c1abaShenning struct node_host *h = NULL; 124094e9410bShenning 124194e9410bShenning memset(&hints, 0, sizeof(hints)); 124294e9410bShenning hints.ai_family = AF_INET6; 124394e9410bShenning hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 124494e9410bShenning hints.ai_flags = AI_NUMERICHOST; 12452a6c1abaShenning if (getaddrinfo(s, "0", &hints, &res) == 0) { 12462a6c1abaShenning h = calloc(1, sizeof(struct node_host)); 12472a6c1abaShenning if (h == NULL) 124894e9410bShenning err(1, "address: calloc"); 12492a6c1abaShenning h->ifname = NULL; 12502a6c1abaShenning h->af = AF_INET6; 12512a6c1abaShenning memcpy(&h->addr.v.a.addr, 125294e9410bShenning &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 12532a6c1abaShenning sizeof(h->addr.v.a.addr)); 12542a6c1abaShenning h->ifindex = 12552a6c1abaShenning ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 12562a6c1abaShenning set_ipmask(h, mask); 125794e9410bShenning freeaddrinfo(res); 12582a6c1abaShenning h->next = NULL; 12592a6c1abaShenning h->tail = h; 126094e9410bShenning } 126194e9410bShenning 12622a6c1abaShenning return (h); 12632a6c1abaShenning } 12642a6c1abaShenning 12652a6c1abaShenning struct node_host * 1266f2370d27Shenning host_dns(const char *s, int v4mask, int v6mask) 12672a6c1abaShenning { 12682a6c1abaShenning struct addrinfo hints, *res0, *res; 12692a6c1abaShenning struct node_host *n, *h = NULL; 12702a6c1abaShenning int error; 12712a6c1abaShenning 127294e9410bShenning memset(&hints, 0, sizeof(hints)); 127394e9410bShenning hints.ai_family = PF_UNSPEC; 127494e9410bShenning hints.ai_socktype = SOCK_STREAM; /* DUMMY */ 12752a6c1abaShenning error = getaddrinfo(s, NULL, &hints, &res0); 12762a6c1abaShenning if (error) 12772a6c1abaShenning return (h); 12782a6c1abaShenning 127994e9410bShenning for (res = res0; res; res = res->ai_next) { 128094e9410bShenning if (res->ai_family != AF_INET && 128194e9410bShenning res->ai_family != AF_INET6) 128294e9410bShenning continue; 128394e9410bShenning n = calloc(1, sizeof(struct node_host)); 128494e9410bShenning if (n == NULL) 12852a6c1abaShenning err(1, "host_dns: calloc"); 128694e9410bShenning n->ifname = NULL; 128794e9410bShenning n->af = res->ai_family; 128894e9410bShenning if (res->ai_family == AF_INET) { 128994e9410bShenning memcpy(&n->addr.v.a.addr, 12902a6c1abaShenning &((struct sockaddr_in *) 12912a6c1abaShenning res->ai_addr)->sin_addr.s_addr, 129294e9410bShenning sizeof(struct in_addr)); 129394e9410bShenning set_ipmask(n, v4mask); 129494e9410bShenning } else { 129594e9410bShenning memcpy(&n->addr.v.a.addr, 12962a6c1abaShenning &((struct sockaddr_in6 *) 12972a6c1abaShenning res->ai_addr)->sin6_addr.s6_addr, 129894e9410bShenning sizeof(struct in6_addr)); 129994e9410bShenning n->ifindex = 13002a6c1abaShenning ((struct sockaddr_in6 *) 13012a6c1abaShenning res->ai_addr)->sin6_scope_id; 130294e9410bShenning set_ipmask(n, v6mask); 130394e9410bShenning } 130494e9410bShenning n->next = NULL; 130594e9410bShenning n->tail = n; 130694e9410bShenning if (h == NULL) 130794e9410bShenning h = n; 130894e9410bShenning else { 130994e9410bShenning h->tail->next = n; 131094e9410bShenning h->tail = n; 131194e9410bShenning } 131294e9410bShenning } 131394e9410bShenning freeaddrinfo(res0); 131494e9410bShenning 131594e9410bShenning return (h); 131694e9410bShenning } 1317