1223637Sbz/* $OpenBSD: pfctl_parser.c,v 1.240 2008/06/10 20:55:02 mcbride Exp $ */ 2126353Smlaier 3330449Seadler/*- 4330449Seadler * SPDX-License-Identifier: BSD-2-Clause 5330449Seadler * 6126353Smlaier * Copyright (c) 2001 Daniel Hartmeier 7130617Smlaier * Copyright (c) 2002,2003 Henning Brauer 8126353Smlaier * All rights reserved. 9126353Smlaier * 10126353Smlaier * Redistribution and use in source and binary forms, with or without 11126353Smlaier * modification, are permitted provided that the following conditions 12126353Smlaier * are met: 13126353Smlaier * 14126353Smlaier * - Redistributions of source code must retain the above copyright 15126353Smlaier * notice, this list of conditions and the following disclaimer. 16126353Smlaier * - Redistributions in binary form must reproduce the above 17126353Smlaier * copyright notice, this list of conditions and the following 18126353Smlaier * disclaimer in the documentation and/or other materials provided 19126353Smlaier * with the distribution. 20126353Smlaier * 21126353Smlaier * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22126353Smlaier * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23126353Smlaier * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24126353Smlaier * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25126353Smlaier * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26126353Smlaier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27126353Smlaier * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28126353Smlaier * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29126353Smlaier * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30126353Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31126353Smlaier * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32126353Smlaier * POSSIBILITY OF SUCH DAMAGE. 33126353Smlaier * 34126353Smlaier */ 35126353Smlaier 36127082Sobrien#include <sys/cdefs.h> 37127082Sobrien__FBSDID("$FreeBSD: stable/11/sbin/pfctl/pfctl_parser.c 359573 2020-04-02 18:37:15Z kp $"); 38127082Sobrien 39126353Smlaier#include <sys/types.h> 40130617Smlaier#include <sys/ioctl.h> 41126353Smlaier#include <sys/socket.h> 42145840Smlaier#include <sys/param.h> 43145840Smlaier#include <sys/proc.h> 44126353Smlaier#include <net/if.h> 45126353Smlaier#include <netinet/in.h> 46126353Smlaier#include <netinet/in_systm.h> 47126353Smlaier#include <netinet/ip.h> 48126353Smlaier#include <netinet/ip_icmp.h> 49126353Smlaier#include <netinet/icmp6.h> 50126353Smlaier#include <net/pfvar.h> 51126353Smlaier#include <arpa/inet.h> 52126353Smlaier 53126353Smlaier#include <stdio.h> 54126353Smlaier#include <stdlib.h> 55126353Smlaier#include <string.h> 56126353Smlaier#include <ctype.h> 57126353Smlaier#include <netdb.h> 58126353Smlaier#include <stdarg.h> 59126353Smlaier#include <errno.h> 60126353Smlaier#include <err.h> 61126353Smlaier#include <ifaddrs.h> 62171172Smlaier#include <unistd.h> 63126353Smlaier 64126353Smlaier#include "pfctl_parser.h" 65126353Smlaier#include "pfctl.h" 66126353Smlaier 67126353Smlaiervoid print_op (u_int8_t, const char *, const char *); 68223057Sbzvoid print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int); 69126353Smlaiervoid print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned); 70126353Smlaiervoid print_flags (u_int8_t); 71126353Smlaiervoid print_fromto(struct pf_rule_addr *, pf_osfp_t, 72223057Sbz struct pf_rule_addr *, u_int8_t, u_int8_t, int, int); 73145840Smlaierint ifa_skip_if(const char *filter, struct node_host *p); 74126353Smlaier 75171172Smlaierstruct node_host *ifa_grouplookup(const char *, int); 76126353Smlaierstruct node_host *host_if(const char *, int); 77126353Smlaierstruct node_host *host_v4(const char *, int); 78126353Smlaierstruct node_host *host_v6(const char *, int); 79126353Smlaierstruct node_host *host_dns(const char *, int, int); 80126353Smlaier 81126353Smlaierconst char *tcpflags = "FSRPAUEW"; 82126353Smlaier 83126353Smlaierstatic const struct icmptypeent icmp_type[] = { 84126353Smlaier { "echoreq", ICMP_ECHO }, 85126353Smlaier { "echorep", ICMP_ECHOREPLY }, 86126353Smlaier { "unreach", ICMP_UNREACH }, 87126353Smlaier { "squench", ICMP_SOURCEQUENCH }, 88126353Smlaier { "redir", ICMP_REDIRECT }, 89126353Smlaier { "althost", ICMP_ALTHOSTADDR }, 90126353Smlaier { "routeradv", ICMP_ROUTERADVERT }, 91126353Smlaier { "routersol", ICMP_ROUTERSOLICIT }, 92126353Smlaier { "timex", ICMP_TIMXCEED }, 93126353Smlaier { "paramprob", ICMP_PARAMPROB }, 94126353Smlaier { "timereq", ICMP_TSTAMP }, 95126353Smlaier { "timerep", ICMP_TSTAMPREPLY }, 96126353Smlaier { "inforeq", ICMP_IREQ }, 97126353Smlaier { "inforep", ICMP_IREQREPLY }, 98126353Smlaier { "maskreq", ICMP_MASKREQ }, 99126353Smlaier { "maskrep", ICMP_MASKREPLY }, 100126353Smlaier { "trace", ICMP_TRACEROUTE }, 101126353Smlaier { "dataconv", ICMP_DATACONVERR }, 102126353Smlaier { "mobredir", ICMP_MOBILE_REDIRECT }, 103126353Smlaier { "ipv6-where", ICMP_IPV6_WHEREAREYOU }, 104126353Smlaier { "ipv6-here", ICMP_IPV6_IAMHERE }, 105126353Smlaier { "mobregreq", ICMP_MOBILE_REGREQUEST }, 106126353Smlaier { "mobregrep", ICMP_MOBILE_REGREPLY }, 107126353Smlaier { "skip", ICMP_SKIP }, 108126353Smlaier { "photuris", ICMP_PHOTURIS } 109126353Smlaier}; 110126353Smlaier 111126353Smlaierstatic const struct icmptypeent icmp6_type[] = { 112126353Smlaier { "unreach", ICMP6_DST_UNREACH }, 113126353Smlaier { "toobig", ICMP6_PACKET_TOO_BIG }, 114126353Smlaier { "timex", ICMP6_TIME_EXCEEDED }, 115126353Smlaier { "paramprob", ICMP6_PARAM_PROB }, 116126353Smlaier { "echoreq", ICMP6_ECHO_REQUEST }, 117126353Smlaier { "echorep", ICMP6_ECHO_REPLY }, 118126353Smlaier { "groupqry", ICMP6_MEMBERSHIP_QUERY }, 119126353Smlaier { "listqry", MLD_LISTENER_QUERY }, 120126353Smlaier { "grouprep", ICMP6_MEMBERSHIP_REPORT }, 121126353Smlaier { "listenrep", MLD_LISTENER_REPORT }, 122126353Smlaier { "groupterm", ICMP6_MEMBERSHIP_REDUCTION }, 123126353Smlaier { "listendone", MLD_LISTENER_DONE }, 124126353Smlaier { "routersol", ND_ROUTER_SOLICIT }, 125126353Smlaier { "routeradv", ND_ROUTER_ADVERT }, 126126353Smlaier { "neighbrsol", ND_NEIGHBOR_SOLICIT }, 127126353Smlaier { "neighbradv", ND_NEIGHBOR_ADVERT }, 128126353Smlaier { "redir", ND_REDIRECT }, 129126353Smlaier { "routrrenum", ICMP6_ROUTER_RENUMBERING }, 130126353Smlaier { "wrureq", ICMP6_WRUREQUEST }, 131126353Smlaier { "wrurep", ICMP6_WRUREPLY }, 132126353Smlaier { "fqdnreq", ICMP6_FQDN_QUERY }, 133126353Smlaier { "fqdnrep", ICMP6_FQDN_REPLY }, 134126353Smlaier { "niqry", ICMP6_NI_QUERY }, 135126353Smlaier { "nirep", ICMP6_NI_REPLY }, 136126353Smlaier { "mtraceresp", MLD_MTRACE_RESP }, 137126353Smlaier { "mtrace", MLD_MTRACE } 138126353Smlaier}; 139126353Smlaier 140126353Smlaierstatic const struct icmpcodeent icmp_code[] = { 141126353Smlaier { "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET }, 142126353Smlaier { "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST }, 143126353Smlaier { "proto-unr", ICMP_UNREACH, ICMP_UNREACH_PROTOCOL }, 144126353Smlaier { "port-unr", ICMP_UNREACH, ICMP_UNREACH_PORT }, 145126353Smlaier { "needfrag", ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG }, 146126353Smlaier { "srcfail", ICMP_UNREACH, ICMP_UNREACH_SRCFAIL }, 147126353Smlaier { "net-unk", ICMP_UNREACH, ICMP_UNREACH_NET_UNKNOWN }, 148126353Smlaier { "host-unk", ICMP_UNREACH, ICMP_UNREACH_HOST_UNKNOWN }, 149126353Smlaier { "isolate", ICMP_UNREACH, ICMP_UNREACH_ISOLATED }, 150126353Smlaier { "net-prohib", ICMP_UNREACH, ICMP_UNREACH_NET_PROHIB }, 151126353Smlaier { "host-prohib", ICMP_UNREACH, ICMP_UNREACH_HOST_PROHIB }, 152126353Smlaier { "net-tos", ICMP_UNREACH, ICMP_UNREACH_TOSNET }, 153126353Smlaier { "host-tos", ICMP_UNREACH, ICMP_UNREACH_TOSHOST }, 154126353Smlaier { "filter-prohib", ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB }, 155126353Smlaier { "host-preced", ICMP_UNREACH, ICMP_UNREACH_HOST_PRECEDENCE }, 156126353Smlaier { "cutoff-preced", ICMP_UNREACH, ICMP_UNREACH_PRECEDENCE_CUTOFF }, 157126353Smlaier { "redir-net", ICMP_REDIRECT, ICMP_REDIRECT_NET }, 158126353Smlaier { "redir-host", ICMP_REDIRECT, ICMP_REDIRECT_HOST }, 159126353Smlaier { "redir-tos-net", ICMP_REDIRECT, ICMP_REDIRECT_TOSNET }, 160126353Smlaier { "redir-tos-host", ICMP_REDIRECT, ICMP_REDIRECT_TOSHOST }, 161126353Smlaier { "normal-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL }, 162126353Smlaier { "common-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON }, 163126353Smlaier { "transit", ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS }, 164126353Smlaier { "reassemb", ICMP_TIMXCEED, ICMP_TIMXCEED_REASS }, 165126353Smlaier { "badhead", ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR }, 166126353Smlaier { "optmiss", ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT }, 167126353Smlaier { "badlen", ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH }, 168126353Smlaier { "unknown-ind", ICMP_PHOTURIS, ICMP_PHOTURIS_UNKNOWN_INDEX }, 169126353Smlaier { "auth-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_AUTH_FAILED }, 170126353Smlaier { "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED } 171126353Smlaier}; 172126353Smlaier 173126353Smlaierstatic const struct icmpcodeent icmp6_code[] = { 174126353Smlaier { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN }, 175126353Smlaier { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE }, 176126353Smlaier { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR }, 177126353Smlaier { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE }, 178126353Smlaier { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR }, 179126353Smlaier { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT }, 180126353Smlaier { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT }, 181126353Smlaier { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY }, 182126353Smlaier { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER }, 183126353Smlaier { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER }, 184126353Smlaier { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK }, 185126353Smlaier { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER } 186126353Smlaier}; 187126353Smlaier 188126353Smlaierconst struct pf_timeout pf_timeouts[] = { 189126353Smlaier { "tcp.first", PFTM_TCP_FIRST_PACKET }, 190126353Smlaier { "tcp.opening", PFTM_TCP_OPENING }, 191126353Smlaier { "tcp.established", PFTM_TCP_ESTABLISHED }, 192126353Smlaier { "tcp.closing", PFTM_TCP_CLOSING }, 193126353Smlaier { "tcp.finwait", PFTM_TCP_FIN_WAIT }, 194126353Smlaier { "tcp.closed", PFTM_TCP_CLOSED }, 195145840Smlaier { "tcp.tsdiff", PFTM_TS_DIFF }, 196126353Smlaier { "udp.first", PFTM_UDP_FIRST_PACKET }, 197126353Smlaier { "udp.single", PFTM_UDP_SINGLE }, 198126353Smlaier { "udp.multiple", PFTM_UDP_MULTIPLE }, 199126353Smlaier { "icmp.first", PFTM_ICMP_FIRST_PACKET }, 200126353Smlaier { "icmp.error", PFTM_ICMP_ERROR_REPLY }, 201126353Smlaier { "other.first", PFTM_OTHER_FIRST_PACKET }, 202126353Smlaier { "other.single", PFTM_OTHER_SINGLE }, 203126353Smlaier { "other.multiple", PFTM_OTHER_MULTIPLE }, 204126353Smlaier { "frag", PFTM_FRAG }, 205126353Smlaier { "interval", PFTM_INTERVAL }, 206126353Smlaier { "adaptive.start", PFTM_ADAPTIVE_START }, 207126353Smlaier { "adaptive.end", PFTM_ADAPTIVE_END }, 208130617Smlaier { "src.track", PFTM_SRC_NODE }, 209126353Smlaier { NULL, 0 } 210126353Smlaier}; 211126353Smlaier 212126353Smlaierconst struct icmptypeent * 213126353Smlaiergeticmptypebynumber(u_int8_t type, sa_family_t af) 214126353Smlaier{ 215126353Smlaier unsigned int i; 216126353Smlaier 217126353Smlaier if (af != AF_INET6) { 218298255Saraujo for (i=0; i < nitems(icmp_type); i++) { 219126353Smlaier if (type == icmp_type[i].type) 220126353Smlaier return (&icmp_type[i]); 221126353Smlaier } 222126353Smlaier } else { 223298255Saraujo for (i=0; i < nitems(icmp6_type); i++) { 224126353Smlaier if (type == icmp6_type[i].type) 225126353Smlaier return (&icmp6_type[i]); 226126353Smlaier } 227126353Smlaier } 228126353Smlaier return (NULL); 229126353Smlaier} 230126353Smlaier 231126353Smlaierconst struct icmptypeent * 232126353Smlaiergeticmptypebyname(char *w, sa_family_t af) 233126353Smlaier{ 234126353Smlaier unsigned int i; 235126353Smlaier 236126353Smlaier if (af != AF_INET6) { 237298255Saraujo for (i=0; i < nitems(icmp_type); i++) { 238126353Smlaier if (!strcmp(w, icmp_type[i].name)) 239126353Smlaier return (&icmp_type[i]); 240126353Smlaier } 241126353Smlaier } else { 242298255Saraujo for (i=0; i < nitems(icmp6_type); i++) { 243126353Smlaier if (!strcmp(w, icmp6_type[i].name)) 244126353Smlaier return (&icmp6_type[i]); 245126353Smlaier } 246126353Smlaier } 247126353Smlaier return (NULL); 248126353Smlaier} 249126353Smlaier 250126353Smlaierconst struct icmpcodeent * 251126353Smlaiergeticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af) 252126353Smlaier{ 253126353Smlaier unsigned int i; 254126353Smlaier 255126353Smlaier if (af != AF_INET6) { 256298255Saraujo for (i=0; i < nitems(icmp_code); i++) { 257126353Smlaier if (type == icmp_code[i].type && 258126353Smlaier code == icmp_code[i].code) 259126353Smlaier return (&icmp_code[i]); 260126353Smlaier } 261126353Smlaier } else { 262298255Saraujo for (i=0; i < nitems(icmp6_code); i++) { 263126353Smlaier if (type == icmp6_code[i].type && 264126353Smlaier code == icmp6_code[i].code) 265126353Smlaier return (&icmp6_code[i]); 266126353Smlaier } 267126353Smlaier } 268126353Smlaier return (NULL); 269126353Smlaier} 270126353Smlaier 271126353Smlaierconst struct icmpcodeent * 272126353Smlaiergeticmpcodebyname(u_long type, char *w, sa_family_t af) 273126353Smlaier{ 274126353Smlaier unsigned int i; 275126353Smlaier 276126353Smlaier if (af != AF_INET6) { 277298255Saraujo for (i=0; i < nitems(icmp_code); i++) { 278126353Smlaier if (type == icmp_code[i].type && 279126353Smlaier !strcmp(w, icmp_code[i].name)) 280126353Smlaier return (&icmp_code[i]); 281126353Smlaier } 282126353Smlaier } else { 283298255Saraujo for (i=0; i < nitems(icmp6_code); i++) { 284126353Smlaier if (type == icmp6_code[i].type && 285126353Smlaier !strcmp(w, icmp6_code[i].name)) 286126353Smlaier return (&icmp6_code[i]); 287126353Smlaier } 288126353Smlaier } 289126353Smlaier return (NULL); 290126353Smlaier} 291126353Smlaier 292126353Smlaiervoid 293126353Smlaierprint_op(u_int8_t op, const char *a1, const char *a2) 294126353Smlaier{ 295126353Smlaier if (op == PF_OP_IRG) 296126353Smlaier printf(" %s >< %s", a1, a2); 297126353Smlaier else if (op == PF_OP_XRG) 298126353Smlaier printf(" %s <> %s", a1, a2); 299126353Smlaier else if (op == PF_OP_EQ) 300126353Smlaier printf(" = %s", a1); 301126353Smlaier else if (op == PF_OP_NE) 302126353Smlaier printf(" != %s", a1); 303126353Smlaier else if (op == PF_OP_LT) 304126353Smlaier printf(" < %s", a1); 305126353Smlaier else if (op == PF_OP_LE) 306126353Smlaier printf(" <= %s", a1); 307126353Smlaier else if (op == PF_OP_GT) 308126353Smlaier printf(" > %s", a1); 309126353Smlaier else if (op == PF_OP_GE) 310126353Smlaier printf(" >= %s", a1); 311126353Smlaier else if (op == PF_OP_RRG) 312126353Smlaier printf(" %s:%s", a1, a2); 313126353Smlaier} 314126353Smlaier 315126353Smlaiervoid 316223057Sbzprint_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int numeric) 317126353Smlaier{ 318126353Smlaier char a1[6], a2[6]; 319126353Smlaier struct servent *s; 320126353Smlaier 321223057Sbz if (!numeric) 322223057Sbz s = getservbyport(p1, proto); 323223057Sbz else 324223057Sbz s = NULL; 325126353Smlaier p1 = ntohs(p1); 326126353Smlaier p2 = ntohs(p2); 327126353Smlaier snprintf(a1, sizeof(a1), "%u", p1); 328126353Smlaier snprintf(a2, sizeof(a2), "%u", p2); 329126353Smlaier printf(" port"); 330126353Smlaier if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE)) 331126353Smlaier print_op(op, s->s_name, a2); 332126353Smlaier else 333126353Smlaier print_op(op, a1, a2); 334126353Smlaier} 335126353Smlaier 336126353Smlaiervoid 337126353Smlaierprint_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax) 338126353Smlaier{ 339126353Smlaier char a1[11], a2[11]; 340126353Smlaier 341126353Smlaier snprintf(a1, sizeof(a1), "%u", u1); 342126353Smlaier snprintf(a2, sizeof(a2), "%u", u2); 343126353Smlaier printf(" %s", t); 344126353Smlaier if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE)) 345126353Smlaier print_op(op, "unknown", a2); 346126353Smlaier else 347126353Smlaier print_op(op, a1, a2); 348126353Smlaier} 349126353Smlaier 350126353Smlaiervoid 351126353Smlaierprint_flags(u_int8_t f) 352126353Smlaier{ 353126353Smlaier int i; 354126353Smlaier 355126353Smlaier for (i = 0; tcpflags[i]; ++i) 356126353Smlaier if (f & (1 << i)) 357126353Smlaier printf("%c", tcpflags[i]); 358126353Smlaier} 359126353Smlaier 360126353Smlaiervoid 361126353Smlaierprint_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, 362223057Sbz sa_family_t af, u_int8_t proto, int verbose, int numeric) 363126353Smlaier{ 364126353Smlaier char buf[PF_OSFP_LEN*3]; 365126353Smlaier if (src->addr.type == PF_ADDR_ADDRMASK && 366126353Smlaier dst->addr.type == PF_ADDR_ADDRMASK && 367126353Smlaier PF_AZERO(&src->addr.v.a.addr, AF_INET6) && 368126353Smlaier PF_AZERO(&src->addr.v.a.mask, AF_INET6) && 369126353Smlaier PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && 370126353Smlaier PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && 371145840Smlaier !src->neg && !dst->neg && 372126353Smlaier !src->port_op && !dst->port_op && 373126353Smlaier osfp == PF_OSFP_ANY) 374126353Smlaier printf(" all"); 375126353Smlaier else { 376126353Smlaier printf(" from "); 377145840Smlaier if (src->neg) 378126353Smlaier printf("! "); 379126353Smlaier print_addr(&src->addr, af, verbose); 380126353Smlaier if (src->port_op) 381126353Smlaier print_port(src->port_op, src->port[0], 382126353Smlaier src->port[1], 383223057Sbz proto == IPPROTO_TCP ? "tcp" : "udp", 384223057Sbz numeric); 385126353Smlaier if (osfp != PF_OSFP_ANY) 386126353Smlaier printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf, 387126353Smlaier sizeof(buf))); 388126353Smlaier 389126353Smlaier printf(" to "); 390145840Smlaier if (dst->neg) 391126353Smlaier printf("! "); 392126353Smlaier print_addr(&dst->addr, af, verbose); 393126353Smlaier if (dst->port_op) 394126353Smlaier print_port(dst->port_op, dst->port[0], 395126353Smlaier dst->port[1], 396223057Sbz proto == IPPROTO_TCP ? "tcp" : "udp", 397223057Sbz numeric); 398126353Smlaier } 399126353Smlaier} 400126353Smlaier 401126353Smlaiervoid 402126353Smlaierprint_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2, 403126353Smlaier sa_family_t af, int id) 404126353Smlaier{ 405126353Smlaier struct pf_pooladdr *pooladdr; 406126353Smlaier 407126353Smlaier if ((TAILQ_FIRST(&pool->list) != NULL) && 408126353Smlaier TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 409126353Smlaier printf("{ "); 410126353Smlaier TAILQ_FOREACH(pooladdr, &pool->list, entries){ 411126353Smlaier switch (id) { 412126353Smlaier case PF_NAT: 413126353Smlaier case PF_RDR: 414126353Smlaier case PF_BINAT: 415126353Smlaier print_addr(&pooladdr->addr, af, 0); 416126353Smlaier break; 417126353Smlaier case PF_PASS: 418126353Smlaier if (PF_AZERO(&pooladdr->addr.v.a.addr, af)) 419126353Smlaier printf("%s", pooladdr->ifname); 420126353Smlaier else { 421126353Smlaier printf("(%s ", pooladdr->ifname); 422126353Smlaier print_addr(&pooladdr->addr, af, 0); 423126353Smlaier printf(")"); 424126353Smlaier } 425126353Smlaier break; 426126353Smlaier default: 427126353Smlaier break; 428126353Smlaier } 429126353Smlaier if (TAILQ_NEXT(pooladdr, entries) != NULL) 430126353Smlaier printf(", "); 431126353Smlaier else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 432126353Smlaier printf(" }"); 433126353Smlaier } 434126353Smlaier switch (id) { 435126353Smlaier case PF_NAT: 436126353Smlaier if ((p1 != PF_NAT_PROXY_PORT_LOW || 437126353Smlaier p2 != PF_NAT_PROXY_PORT_HIGH) && (p1 != 0 || p2 != 0)) { 438126353Smlaier if (p1 == p2) 439126353Smlaier printf(" port %u", p1); 440126353Smlaier else 441126353Smlaier printf(" port %u:%u", p1, p2); 442126353Smlaier } 443126353Smlaier break; 444126353Smlaier case PF_RDR: 445126353Smlaier if (p1) { 446126353Smlaier printf(" port %u", p1); 447126353Smlaier if (p2 && (p2 != p1)) 448126353Smlaier printf(":%u", p2); 449126353Smlaier } 450126353Smlaier break; 451126353Smlaier default: 452126353Smlaier break; 453126353Smlaier } 454126353Smlaier switch (pool->opts & PF_POOL_TYPEMASK) { 455126353Smlaier case PF_POOL_NONE: 456126353Smlaier break; 457126353Smlaier case PF_POOL_BITMASK: 458126353Smlaier printf(" bitmask"); 459126353Smlaier break; 460126353Smlaier case PF_POOL_RANDOM: 461126353Smlaier printf(" random"); 462126353Smlaier break; 463126353Smlaier case PF_POOL_SRCHASH: 464126353Smlaier printf(" source-hash 0x%08x%08x%08x%08x", 465126353Smlaier pool->key.key32[0], pool->key.key32[1], 466126353Smlaier pool->key.key32[2], pool->key.key32[3]); 467126353Smlaier break; 468126353Smlaier case PF_POOL_ROUNDROBIN: 469126353Smlaier printf(" round-robin"); 470126353Smlaier break; 471126353Smlaier } 472130617Smlaier if (pool->opts & PF_POOL_STICKYADDR) 473130617Smlaier printf(" sticky-address"); 474126353Smlaier if (id == PF_NAT && p1 == 0 && p2 == 0) 475126353Smlaier printf(" static-port"); 476126353Smlaier} 477126353Smlaier 478126353Smlaierconst char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 479145840Smlaierconst char *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES; 480126353Smlaierconst char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 481130617Smlaierconst char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES; 482126353Smlaier 483126353Smlaiervoid 484130617Smlaierprint_status(struct pf_status *s, int opts) 485126353Smlaier{ 486171172Smlaier char statline[80], *running; 487171172Smlaier time_t runtime; 488171172Smlaier int i; 489171172Smlaier char buf[PF_MD5_DIGEST_LENGTH * 2 + 1]; 490171172Smlaier static const char hex[] = "0123456789abcdef"; 491126353Smlaier 492126353Smlaier runtime = time(NULL) - s->since; 493130617Smlaier running = s->running ? "Enabled" : "Disabled"; 494126353Smlaier 495130617Smlaier if (s->since) { 496223637Sbz unsigned int sec, min, hrs, day = runtime; 497126353Smlaier 498126353Smlaier sec = day % 60; 499126353Smlaier day /= 60; 500126353Smlaier min = day % 60; 501126353Smlaier day /= 60; 502126353Smlaier hrs = day % 24; 503126353Smlaier day /= 24; 504126353Smlaier snprintf(statline, sizeof(statline), 505130617Smlaier "Status: %s for %u days %.2u:%.2u:%.2u", 506130617Smlaier running, day, hrs, min, sec); 507126353Smlaier } else 508130617Smlaier snprintf(statline, sizeof(statline), "Status: %s", running); 509126353Smlaier printf("%-44s", statline); 510126353Smlaier switch (s->debug) { 511130617Smlaier case PF_DEBUG_NONE: 512126353Smlaier printf("%15s\n\n", "Debug: None"); 513126353Smlaier break; 514130617Smlaier case PF_DEBUG_URGENT: 515126353Smlaier printf("%15s\n\n", "Debug: Urgent"); 516126353Smlaier break; 517130617Smlaier case PF_DEBUG_MISC: 518126353Smlaier printf("%15s\n\n", "Debug: Misc"); 519126353Smlaier break; 520130617Smlaier case PF_DEBUG_NOISY: 521130617Smlaier printf("%15s\n\n", "Debug: Loud"); 522130617Smlaier break; 523126353Smlaier } 524171172Smlaier 525171172Smlaier if (opts & PF_OPT_VERBOSE) { 526171172Smlaier printf("Hostid: 0x%08x\n", ntohl(s->hostid)); 527171172Smlaier 528171172Smlaier for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) { 529171172Smlaier buf[i + i] = hex[s->pf_chksum[i] >> 4]; 530171172Smlaier buf[i + i + 1] = hex[s->pf_chksum[i] & 0x0f]; 531171172Smlaier } 532171172Smlaier buf[i + i] = '\0'; 533171172Smlaier printf("Checksum: 0x%s\n\n", buf); 534171172Smlaier } 535171172Smlaier 536126353Smlaier if (s->ifname[0] != 0) { 537126353Smlaier printf("Interface Stats for %-16s %5s %16s\n", 538126353Smlaier s->ifname, "IPv4", "IPv6"); 539127024Smlaier printf(" %-25s %14llu %16llu\n", "Bytes In", 540127024Smlaier (unsigned long long)s->bcounters[0][0], 541127024Smlaier (unsigned long long)s->bcounters[1][0]); 542127024Smlaier printf(" %-25s %14llu %16llu\n", "Bytes Out", 543127024Smlaier (unsigned long long)s->bcounters[0][1], 544127024Smlaier (unsigned long long)s->bcounters[1][1]); 545126353Smlaier printf(" Packets In\n"); 546127024Smlaier printf(" %-23s %14llu %16llu\n", "Passed", 547127024Smlaier (unsigned long long)s->pcounters[0][0][PF_PASS], 548127024Smlaier (unsigned long long)s->pcounters[1][0][PF_PASS]); 549127024Smlaier printf(" %-23s %14llu %16llu\n", "Blocked", 550127024Smlaier (unsigned long long)s->pcounters[0][0][PF_DROP], 551127024Smlaier (unsigned long long)s->pcounters[1][0][PF_DROP]); 552126353Smlaier printf(" Packets Out\n"); 553127024Smlaier printf(" %-23s %14llu %16llu\n", "Passed", 554127024Smlaier (unsigned long long)s->pcounters[0][1][PF_PASS], 555127024Smlaier (unsigned long long)s->pcounters[1][1][PF_PASS]); 556127024Smlaier printf(" %-23s %14llu %16llu\n\n", "Blocked", 557127024Smlaier (unsigned long long)s->pcounters[0][1][PF_DROP], 558127024Smlaier (unsigned long long)s->pcounters[1][1][PF_DROP]); 559126353Smlaier } 560126353Smlaier printf("%-27s %14s %16s\n", "State Table", "Total", "Rate"); 561126353Smlaier printf(" %-25s %14u %14s\n", "current entries", s->states, ""); 562126353Smlaier for (i = 0; i < FCNT_MAX; i++) { 563127024Smlaier printf(" %-25s %14llu ", pf_fcounters[i], 564127024Smlaier (unsigned long long)s->fcounters[i]); 565126353Smlaier if (runtime > 0) 566126353Smlaier printf("%14.1f/s\n", 567126353Smlaier (double)s->fcounters[i] / (double)runtime); 568126353Smlaier else 569126353Smlaier printf("%14s\n", ""); 570126353Smlaier } 571130617Smlaier if (opts & PF_OPT_VERBOSE) { 572130617Smlaier printf("Source Tracking Table\n"); 573130617Smlaier printf(" %-25s %14u %14s\n", "current entries", 574130617Smlaier s->src_nodes, ""); 575130617Smlaier for (i = 0; i < SCNT_MAX; i++) { 576130617Smlaier printf(" %-25s %14lld ", pf_scounters[i], 577223637Sbz#ifdef __FreeBSD__ 578223637Sbz (long long)s->scounters[i]); 579223637Sbz#else 580223637Sbz s->scounters[i]); 581223637Sbz#endif 582130617Smlaier if (runtime > 0) 583130617Smlaier printf("%14.1f/s\n", 584130617Smlaier (double)s->scounters[i] / (double)runtime); 585130617Smlaier else 586130617Smlaier printf("%14s\n", ""); 587130617Smlaier } 588130617Smlaier } 589126353Smlaier printf("Counters\n"); 590126353Smlaier for (i = 0; i < PFRES_MAX; i++) { 591127024Smlaier printf(" %-25s %14llu ", pf_reasons[i], 592127024Smlaier (unsigned long long)s->counters[i]); 593126353Smlaier if (runtime > 0) 594126353Smlaier printf("%14.1f/s\n", 595126353Smlaier (double)s->counters[i] / (double)runtime); 596126353Smlaier else 597126353Smlaier printf("%14s\n", ""); 598126353Smlaier } 599145840Smlaier if (opts & PF_OPT_VERBOSE) { 600145840Smlaier printf("Limit Counters\n"); 601145840Smlaier for (i = 0; i < LCNT_MAX; i++) { 602145840Smlaier printf(" %-25s %14lld ", pf_lcounters[i], 603145840Smlaier#ifdef __FreeBSD__ 604145840Smlaier (unsigned long long)s->lcounters[i]); 605145840Smlaier#else 606145840Smlaier s->lcounters[i]); 607145840Smlaier#endif 608145840Smlaier if (runtime > 0) 609145840Smlaier printf("%14.1f/s\n", 610145840Smlaier (double)s->lcounters[i] / (double)runtime); 611145840Smlaier else 612145840Smlaier printf("%14s\n", ""); 613145840Smlaier } 614145840Smlaier } 615126353Smlaier} 616126353Smlaier 617126353Smlaiervoid 618335058Skpprint_running(struct pf_status *status) 619335058Skp{ 620335058Skp printf("%s\n", status->running ? "Enabled" : "Disabled"); 621335058Skp} 622335058Skp 623335058Skpvoid 624130617Smlaierprint_src_node(struct pf_src_node *sn, int opts) 625130617Smlaier{ 626130617Smlaier struct pf_addr_wrap aw; 627130617Smlaier int min, sec; 628130617Smlaier 629130617Smlaier memset(&aw, 0, sizeof(aw)); 630130617Smlaier if (sn->af == AF_INET) 631130617Smlaier aw.v.a.mask.addr32[0] = 0xffffffff; 632130617Smlaier else 633130617Smlaier memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask)); 634130617Smlaier 635130617Smlaier aw.v.a.addr = sn->addr; 636130617Smlaier print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); 637130617Smlaier printf(" -> "); 638130617Smlaier aw.v.a.addr = sn->raddr; 639130617Smlaier print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2); 640145840Smlaier printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states, 641145840Smlaier sn->conn, sn->conn_rate.count / 1000, 642145840Smlaier (sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds); 643130617Smlaier if (opts & PF_OPT_VERBOSE) { 644130617Smlaier sec = sn->creation % 60; 645130617Smlaier sn->creation /= 60; 646130617Smlaier min = sn->creation % 60; 647130617Smlaier sn->creation /= 60; 648130617Smlaier printf(" age %.2u:%.2u:%.2u", sn->creation, min, sec); 649130617Smlaier if (sn->states == 0) { 650130617Smlaier sec = sn->expire % 60; 651130617Smlaier sn->expire /= 60; 652130617Smlaier min = sn->expire % 60; 653130617Smlaier sn->expire /= 60; 654130617Smlaier printf(", expires in %.2u:%.2u:%.2u", 655130617Smlaier sn->expire, min, sec); 656130617Smlaier } 657171172Smlaier printf(", %llu pkts, %llu bytes", 658171172Smlaier#ifdef __FreeBSD__ 659171172Smlaier (unsigned long long)(sn->packets[0] + sn->packets[1]), 660171172Smlaier (unsigned long long)(sn->bytes[0] + sn->bytes[1])); 661171172Smlaier#else 662171172Smlaier sn->packets[0] + sn->packets[1], 663171172Smlaier sn->bytes[0] + sn->bytes[1]); 664171172Smlaier#endif 665130617Smlaier switch (sn->ruletype) { 666130617Smlaier case PF_NAT: 667130617Smlaier if (sn->rule.nr != -1) 668130617Smlaier printf(", nat rule %u", sn->rule.nr); 669130617Smlaier break; 670130617Smlaier case PF_RDR: 671130617Smlaier if (sn->rule.nr != -1) 672130617Smlaier printf(", rdr rule %u", sn->rule.nr); 673130617Smlaier break; 674130617Smlaier case PF_PASS: 675130617Smlaier if (sn->rule.nr != -1) 676130617Smlaier printf(", filter rule %u", sn->rule.nr); 677130617Smlaier break; 678130617Smlaier } 679130617Smlaier printf("\n"); 680130617Smlaier } 681130617Smlaier} 682130617Smlaier 683130617Smlaiervoid 684223057Sbzprint_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) 685126353Smlaier{ 686145840Smlaier static const char *actiontypes[] = { "pass", "block", "scrub", 687145840Smlaier "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" }; 688126353Smlaier static const char *anchortypes[] = { "anchor", "anchor", "anchor", 689145840Smlaier "anchor", "nat-anchor", "nat-anchor", "binat-anchor", 690145840Smlaier "binat-anchor", "rdr-anchor", "rdr-anchor" }; 691126353Smlaier int i, opts; 692126353Smlaier 693126353Smlaier if (verbose) 694126353Smlaier printf("@%d ", r->nr); 695126353Smlaier if (r->action > PF_NORDR) 696126353Smlaier printf("action(%d)", r->action); 697171172Smlaier else if (anchor_call[0]) { 698171172Smlaier if (anchor_call[0] == '_') { 699171172Smlaier printf("%s", anchortypes[r->action]); 700171172Smlaier } else 701171172Smlaier printf("%s \"%s\"", anchortypes[r->action], 702171172Smlaier anchor_call); 703171172Smlaier } else { 704126353Smlaier printf("%s", actiontypes[r->action]); 705126353Smlaier if (r->natpass) 706126353Smlaier printf(" pass"); 707126353Smlaier } 708126353Smlaier if (r->action == PF_DROP) { 709126353Smlaier if (r->rule_flag & PFRULE_RETURN) 710126353Smlaier printf(" return"); 711126353Smlaier else if (r->rule_flag & PFRULE_RETURNRST) { 712126353Smlaier if (!r->return_ttl) 713126353Smlaier printf(" return-rst"); 714126353Smlaier else 715126353Smlaier printf(" return-rst(ttl %d)", r->return_ttl); 716126353Smlaier } else if (r->rule_flag & PFRULE_RETURNICMP) { 717126353Smlaier const struct icmpcodeent *ic, *ic6; 718126353Smlaier 719126353Smlaier ic = geticmpcodebynumber(r->return_icmp >> 8, 720126353Smlaier r->return_icmp & 255, AF_INET); 721126353Smlaier ic6 = geticmpcodebynumber(r->return_icmp6 >> 8, 722126353Smlaier r->return_icmp6 & 255, AF_INET6); 723126353Smlaier 724130617Smlaier switch (r->af) { 725126353Smlaier case AF_INET: 726126353Smlaier printf(" return-icmp"); 727126353Smlaier if (ic == NULL) 728126353Smlaier printf("(%u)", r->return_icmp & 255); 729126353Smlaier else 730126353Smlaier printf("(%s)", ic->name); 731126353Smlaier break; 732126353Smlaier case AF_INET6: 733126353Smlaier printf(" return-icmp6"); 734126353Smlaier if (ic6 == NULL) 735126353Smlaier printf("(%u)", r->return_icmp6 & 255); 736126353Smlaier else 737126353Smlaier printf("(%s)", ic6->name); 738126353Smlaier break; 739126353Smlaier default: 740126353Smlaier printf(" return-icmp"); 741126353Smlaier if (ic == NULL) 742126353Smlaier printf("(%u, ", r->return_icmp & 255); 743126353Smlaier else 744126353Smlaier printf("(%s, ", ic->name); 745126353Smlaier if (ic6 == NULL) 746126353Smlaier printf("%u)", r->return_icmp6 & 255); 747126353Smlaier else 748126353Smlaier printf("%s)", ic6->name); 749126353Smlaier break; 750126353Smlaier } 751126353Smlaier } else 752126353Smlaier printf(" drop"); 753126353Smlaier } 754126353Smlaier if (r->direction == PF_IN) 755126353Smlaier printf(" in"); 756126353Smlaier else if (r->direction == PF_OUT) 757126353Smlaier printf(" out"); 758171172Smlaier if (r->log) { 759126353Smlaier printf(" log"); 760171172Smlaier if (r->log & ~PF_LOG || r->logif) { 761171172Smlaier int count = 0; 762171172Smlaier 763171172Smlaier printf(" ("); 764171172Smlaier if (r->log & PF_LOG_ALL) 765171172Smlaier printf("%sall", count++ ? ", " : ""); 766171172Smlaier if (r->log & PF_LOG_SOCKET_LOOKUP) 767171172Smlaier printf("%suser", count++ ? ", " : ""); 768171172Smlaier if (r->logif) 769171172Smlaier printf("%sto pflog%u", count++ ? ", " : "", 770171172Smlaier r->logif); 771171172Smlaier printf(")"); 772171172Smlaier } 773171172Smlaier } 774126353Smlaier if (r->quick) 775126353Smlaier printf(" quick"); 776126353Smlaier if (r->ifname[0]) { 777126353Smlaier if (r->ifnot) 778126353Smlaier printf(" on ! %s", r->ifname); 779126353Smlaier else 780126353Smlaier printf(" on %s", r->ifname); 781126353Smlaier } 782126353Smlaier if (r->rt) { 783126353Smlaier if (r->rt == PF_ROUTETO) 784126353Smlaier printf(" route-to"); 785126353Smlaier else if (r->rt == PF_REPLYTO) 786126353Smlaier printf(" reply-to"); 787126353Smlaier else if (r->rt == PF_DUPTO) 788126353Smlaier printf(" dup-to"); 789126353Smlaier else if (r->rt == PF_FASTROUTE) 790126353Smlaier printf(" fastroute"); 791126353Smlaier if (r->rt != PF_FASTROUTE) { 792126353Smlaier printf(" "); 793126353Smlaier print_pool(&r->rpool, 0, 0, r->af, PF_PASS); 794126353Smlaier } 795126353Smlaier } 796126353Smlaier if (r->af) { 797126353Smlaier if (r->af == AF_INET) 798126353Smlaier printf(" inet"); 799126353Smlaier else 800126353Smlaier printf(" inet6"); 801126353Smlaier } 802126353Smlaier if (r->proto) { 803126353Smlaier struct protoent *p; 804126353Smlaier 805126353Smlaier if ((p = getprotobynumber(r->proto)) != NULL) 806126353Smlaier printf(" proto %s", p->p_name); 807126353Smlaier else 808126353Smlaier printf(" proto %u", r->proto); 809126353Smlaier } 810126353Smlaier print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto, 811223057Sbz verbose, numeric); 812126353Smlaier if (r->uid.op) 813126353Smlaier print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user", 814126353Smlaier UID_MAX); 815126353Smlaier if (r->gid.op) 816126353Smlaier print_ugid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group", 817126353Smlaier GID_MAX); 818126353Smlaier if (r->flags || r->flagset) { 819126353Smlaier printf(" flags "); 820126353Smlaier print_flags(r->flags); 821126353Smlaier printf("/"); 822126353Smlaier print_flags(r->flagset); 823171172Smlaier } else if (r->action == PF_PASS && 824171172Smlaier (!r->proto || r->proto == IPPROTO_TCP) && 825171172Smlaier !(r->rule_flag & PFRULE_FRAGMENT) && 826171172Smlaier !anchor_call[0] && r->keep_state) 827171172Smlaier printf(" flags any"); 828126353Smlaier if (r->type) { 829126353Smlaier const struct icmptypeent *it; 830126353Smlaier 831126353Smlaier it = geticmptypebynumber(r->type-1, r->af); 832126353Smlaier if (r->af != AF_INET6) 833126353Smlaier printf(" icmp-type"); 834126353Smlaier else 835126353Smlaier printf(" icmp6-type"); 836126353Smlaier if (it != NULL) 837126353Smlaier printf(" %s", it->name); 838126353Smlaier else 839126353Smlaier printf(" %u", r->type-1); 840126353Smlaier if (r->code) { 841126353Smlaier const struct icmpcodeent *ic; 842126353Smlaier 843126353Smlaier ic = geticmpcodebynumber(r->type-1, r->code-1, r->af); 844126353Smlaier if (ic != NULL) 845126353Smlaier printf(" code %s", ic->name); 846126353Smlaier else 847126353Smlaier printf(" code %u", r->code-1); 848126353Smlaier } 849126353Smlaier } 850126353Smlaier if (r->tos) 851126353Smlaier printf(" tos 0x%2.2x", r->tos); 852301998Skp if (r->prio) 853301998Skp printf(" prio %u", r->prio == PF_PRIO_ZERO ? 0 : r->prio); 854301998Skp if (r->scrub_flags & PFSTATE_SETMASK) { 855301998Skp char *comma = ""; 856301998Skp printf(" set ("); 857301998Skp if (r->scrub_flags & PFSTATE_SETPRIO) { 858301998Skp if (r->set_prio[0] == r->set_prio[1]) 859301998Skp printf("%s prio %u", comma, r->set_prio[0]); 860301998Skp else 861301998Skp printf("%s prio(%u, %u)", comma, r->set_prio[0], 862301998Skp r->set_prio[1]); 863301998Skp comma = ","; 864301998Skp } 865301998Skp printf(" )"); 866301998Skp } 867171172Smlaier if (!r->keep_state && r->action == PF_PASS && !anchor_call[0]) 868171172Smlaier printf(" no state"); 869171172Smlaier else if (r->keep_state == PF_STATE_NORMAL) 870126353Smlaier printf(" keep state"); 871126353Smlaier else if (r->keep_state == PF_STATE_MODULATE) 872126353Smlaier printf(" modulate state"); 873126353Smlaier else if (r->keep_state == PF_STATE_SYNPROXY) 874126353Smlaier printf(" synproxy state"); 875145840Smlaier if (r->prob) { 876145840Smlaier char buf[20]; 877145840Smlaier 878145840Smlaier snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0)); 879145840Smlaier for (i = strlen(buf)-1; i > 0; i--) { 880145840Smlaier if (buf[i] == '0') 881145840Smlaier buf[i] = '\0'; 882145840Smlaier else { 883145840Smlaier if (buf[i] == '.') 884145840Smlaier buf[i] = '\0'; 885145840Smlaier break; 886145840Smlaier } 887145840Smlaier } 888145840Smlaier printf(" probability %s%%", buf); 889145840Smlaier } 890126353Smlaier opts = 0; 891130617Smlaier if (r->max_states || r->max_src_nodes || r->max_src_states) 892126353Smlaier opts = 1; 893130617Smlaier if (r->rule_flag & PFRULE_NOSYNC) 894130617Smlaier opts = 1; 895130617Smlaier if (r->rule_flag & PFRULE_SRCTRACK) 896130617Smlaier opts = 1; 897171172Smlaier if (r->rule_flag & PFRULE_IFBOUND) 898130617Smlaier opts = 1; 899200930Sdelphij if (r->rule_flag & PFRULE_STATESLOPPY) 900200930Sdelphij opts = 1; 901126353Smlaier for (i = 0; !opts && i < PFTM_MAX; ++i) 902126353Smlaier if (r->timeout[i]) 903126353Smlaier opts = 1; 904126353Smlaier if (opts) { 905126353Smlaier printf(" ("); 906126353Smlaier if (r->max_states) { 907126353Smlaier printf("max %u", r->max_states); 908126353Smlaier opts = 0; 909126353Smlaier } 910130617Smlaier if (r->rule_flag & PFRULE_NOSYNC) { 911130617Smlaier if (!opts) 912130617Smlaier printf(", "); 913130617Smlaier printf("no-sync"); 914130617Smlaier opts = 0; 915130617Smlaier } 916130617Smlaier if (r->rule_flag & PFRULE_SRCTRACK) { 917130617Smlaier if (!opts) 918130617Smlaier printf(", "); 919130617Smlaier printf("source-track"); 920130617Smlaier if (r->rule_flag & PFRULE_RULESRCTRACK) 921130617Smlaier printf(" rule"); 922130617Smlaier else 923130617Smlaier printf(" global"); 924130617Smlaier opts = 0; 925130617Smlaier } 926130617Smlaier if (r->max_src_states) { 927130617Smlaier if (!opts) 928130617Smlaier printf(", "); 929130617Smlaier printf("max-src-states %u", r->max_src_states); 930130617Smlaier opts = 0; 931130617Smlaier } 932145840Smlaier if (r->max_src_conn) { 933145840Smlaier if (!opts) 934145840Smlaier printf(", "); 935145840Smlaier printf("max-src-conn %u", r->max_src_conn); 936145840Smlaier opts = 0; 937145840Smlaier } 938145840Smlaier if (r->max_src_conn_rate.limit) { 939145840Smlaier if (!opts) 940145840Smlaier printf(", "); 941145840Smlaier printf("max-src-conn-rate %u/%u", 942145840Smlaier r->max_src_conn_rate.limit, 943145840Smlaier r->max_src_conn_rate.seconds); 944145840Smlaier opts = 0; 945145840Smlaier } 946130617Smlaier if (r->max_src_nodes) { 947130617Smlaier if (!opts) 948130617Smlaier printf(", "); 949130617Smlaier printf("max-src-nodes %u", r->max_src_nodes); 950130617Smlaier opts = 0; 951130617Smlaier } 952145840Smlaier if (r->overload_tblname[0]) { 953145840Smlaier if (!opts) 954145840Smlaier printf(", "); 955145840Smlaier printf("overload <%s>", r->overload_tblname); 956145840Smlaier if (r->flush) 957145840Smlaier printf(" flush"); 958145840Smlaier if (r->flush & PF_FLUSH_GLOBAL) 959145840Smlaier printf(" global"); 960145840Smlaier } 961130617Smlaier if (r->rule_flag & PFRULE_IFBOUND) { 962130617Smlaier if (!opts) 963130617Smlaier printf(", "); 964130617Smlaier printf("if-bound"); 965130617Smlaier opts = 0; 966130617Smlaier } 967200930Sdelphij if (r->rule_flag & PFRULE_STATESLOPPY) { 968200930Sdelphij if (!opts) 969200930Sdelphij printf(", "); 970200930Sdelphij printf("sloppy"); 971200930Sdelphij opts = 0; 972200930Sdelphij } 973126353Smlaier for (i = 0; i < PFTM_MAX; ++i) 974126353Smlaier if (r->timeout[i]) { 975145840Smlaier int j; 976145840Smlaier 977126353Smlaier if (!opts) 978126353Smlaier printf(", "); 979126353Smlaier opts = 0; 980171172Smlaier for (j = 0; pf_timeouts[j].name != NULL; 981171172Smlaier ++j) 982145840Smlaier if (pf_timeouts[j].timeout == i) 983145840Smlaier break; 984171172Smlaier printf("%s %u", pf_timeouts[j].name == NULL ? 985171172Smlaier "inv.timeout" : pf_timeouts[j].name, 986171172Smlaier r->timeout[i]); 987126353Smlaier } 988126353Smlaier printf(")"); 989126353Smlaier } 990126353Smlaier if (r->rule_flag & PFRULE_FRAGMENT) 991126353Smlaier printf(" fragment"); 992126353Smlaier if (r->rule_flag & PFRULE_NODF) 993126353Smlaier printf(" no-df"); 994126353Smlaier if (r->rule_flag & PFRULE_RANDOMID) 995126353Smlaier printf(" random-id"); 996126353Smlaier if (r->min_ttl) 997126353Smlaier printf(" min-ttl %d", r->min_ttl); 998126353Smlaier if (r->max_mss) 999126353Smlaier printf(" max-mss %d", r->max_mss); 1000223637Sbz if (r->rule_flag & PFRULE_SET_TOS) 1001223637Sbz printf(" set-tos 0x%2.2x", r->set_tos); 1002126353Smlaier if (r->allow_opts) 1003126353Smlaier printf(" allow-opts"); 1004126353Smlaier if (r->action == PF_SCRUB) { 1005126353Smlaier if (r->rule_flag & PFRULE_REASSEMBLE_TCP) 1006126353Smlaier printf(" reassemble tcp"); 1007126353Smlaier 1008287222Skp printf(" fragment reassemble"); 1009126353Smlaier } 1010126353Smlaier if (r->label[0]) 1011126353Smlaier printf(" label \"%s\"", r->label); 1012126353Smlaier if (r->qname[0] && r->pqname[0]) 1013126353Smlaier printf(" queue(%s, %s)", r->qname, r->pqname); 1014126353Smlaier else if (r->qname[0]) 1015126353Smlaier printf(" queue %s", r->qname); 1016126353Smlaier if (r->tagname[0]) 1017126353Smlaier printf(" tag %s", r->tagname); 1018126353Smlaier if (r->match_tagname[0]) { 1019126353Smlaier if (r->match_tag_not) 1020126353Smlaier printf(" !"); 1021126353Smlaier printf(" tagged %s", r->match_tagname); 1022126353Smlaier } 1023171172Smlaier if (r->rtableid != -1) 1024171172Smlaier printf(" rtable %u", r->rtableid); 1025223637Sbz if (r->divert.port) { 1026223637Sbz#ifdef __FreeBSD__ 1027223637Sbz printf(" divert-to %u", ntohs(r->divert.port)); 1028223637Sbz#else 1029223637Sbz if (PF_AZERO(&r->divert.addr, r->af)) { 1030223637Sbz printf(" divert-reply"); 1031223637Sbz } else { 1032223637Sbz /* XXX cut&paste from print_addr */ 1033223637Sbz char buf[48]; 1034223637Sbz 1035223637Sbz printf(" divert-to "); 1036223637Sbz if (inet_ntop(r->af, &r->divert.addr, buf, 1037223637Sbz sizeof(buf)) == NULL) 1038223637Sbz printf("?"); 1039223637Sbz else 1040223637Sbz printf("%s", buf); 1041223637Sbz printf(" port %u", ntohs(r->divert.port)); 1042223637Sbz } 1043223637Sbz#endif 1044223637Sbz } 1045145840Smlaier if (!anchor_call[0] && (r->action == PF_NAT || 1046126353Smlaier r->action == PF_BINAT || r->action == PF_RDR)) { 1047126353Smlaier printf(" -> "); 1048126353Smlaier print_pool(&r->rpool, r->rpool.proxy_port[0], 1049126353Smlaier r->rpool.proxy_port[1], r->af, r->action); 1050126353Smlaier } 1051126353Smlaier} 1052126353Smlaier 1053126353Smlaiervoid 1054126353Smlaierprint_tabledef(const char *name, int flags, int addrs, 1055126353Smlaier struct node_tinithead *nodes) 1056126353Smlaier{ 1057126353Smlaier struct node_tinit *ti, *nti; 1058126353Smlaier struct node_host *h; 1059126353Smlaier 1060126353Smlaier printf("table <%s>", name); 1061126353Smlaier if (flags & PFR_TFLAG_CONST) 1062126353Smlaier printf(" const"); 1063126353Smlaier if (flags & PFR_TFLAG_PERSIST) 1064126353Smlaier printf(" persist"); 1065223637Sbz if (flags & PFR_TFLAG_COUNTERS) 1066223637Sbz printf(" counters"); 1067126353Smlaier SIMPLEQ_FOREACH(ti, nodes, entries) { 1068126353Smlaier if (ti->file) { 1069126353Smlaier printf(" file \"%s\"", ti->file); 1070126353Smlaier continue; 1071126353Smlaier } 1072126353Smlaier printf(" {"); 1073126353Smlaier for (;;) { 1074126353Smlaier for (h = ti->host; h != NULL; h = h->next) { 1075126353Smlaier printf(h->not ? " !" : " "); 1076126353Smlaier print_addr(&h->addr, h->af, 0); 1077126353Smlaier } 1078126353Smlaier nti = SIMPLEQ_NEXT(ti, entries); 1079126353Smlaier if (nti != NULL && nti->file == NULL) 1080126353Smlaier ti = nti; /* merge lists */ 1081126353Smlaier else 1082126353Smlaier break; 1083126353Smlaier } 1084126353Smlaier printf(" }"); 1085126353Smlaier } 1086126353Smlaier if (addrs && SIMPLEQ_EMPTY(nodes)) 1087126353Smlaier printf(" { }"); 1088126353Smlaier printf("\n"); 1089126353Smlaier} 1090126353Smlaier 1091126353Smlaierint 1092126353Smlaierparse_flags(char *s) 1093126353Smlaier{ 1094126353Smlaier char *p, *q; 1095126353Smlaier u_int8_t f = 0; 1096126353Smlaier 1097126353Smlaier for (p = s; *p; p++) { 1098126353Smlaier if ((q = strchr(tcpflags, *p)) == NULL) 1099126353Smlaier return -1; 1100126353Smlaier else 1101126353Smlaier f |= 1 << (q - tcpflags); 1102126353Smlaier } 1103126353Smlaier return (f ? f : PF_TH_ALL); 1104126353Smlaier} 1105126353Smlaier 1106126353Smlaiervoid 1107126353Smlaierset_ipmask(struct node_host *h, u_int8_t b) 1108126353Smlaier{ 1109126353Smlaier struct pf_addr *m, *n; 1110126353Smlaier int i, j = 0; 1111126353Smlaier 1112126353Smlaier m = &h->addr.v.a.mask; 1113145840Smlaier memset(m, 0, sizeof(*m)); 1114126353Smlaier 1115126353Smlaier while (b >= 32) { 1116126353Smlaier m->addr32[j++] = 0xffffffff; 1117126353Smlaier b -= 32; 1118126353Smlaier } 1119126353Smlaier for (i = 31; i > 31-b; --i) 1120126353Smlaier m->addr32[j] |= (1 << i); 1121126353Smlaier if (b) 1122126353Smlaier m->addr32[j] = htonl(m->addr32[j]); 1123126353Smlaier 1124126353Smlaier /* Mask off bits of the address that will never be used. */ 1125126353Smlaier n = &h->addr.v.a.addr; 1126126353Smlaier if (h->addr.type == PF_ADDR_ADDRMASK) 1127126353Smlaier for (i = 0; i < 4; i++) 1128126353Smlaier n->addr32[i] = n->addr32[i] & m->addr32[i]; 1129126353Smlaier} 1130126353Smlaier 1131126353Smlaierint 1132126353Smlaiercheck_netmask(struct node_host *h, sa_family_t af) 1133126353Smlaier{ 1134126353Smlaier struct node_host *n = NULL; 1135126353Smlaier struct pf_addr *m; 1136126353Smlaier 1137126353Smlaier for (n = h; n != NULL; n = n->next) { 1138126353Smlaier if (h->addr.type == PF_ADDR_TABLE) 1139126353Smlaier continue; 1140126353Smlaier m = &h->addr.v.a.mask; 1141126353Smlaier /* fix up netmask for dynaddr */ 1142126353Smlaier if (af == AF_INET && h->addr.type == PF_ADDR_DYNIFTL && 1143126353Smlaier unmask(m, AF_INET6) > 32) 1144126353Smlaier set_ipmask(n, 32); 1145126353Smlaier /* netmasks > 32 bit are invalid on v4 */ 1146126353Smlaier if (af == AF_INET && 1147126353Smlaier (m->addr32[1] || m->addr32[2] || m->addr32[3])) { 1148126353Smlaier fprintf(stderr, "netmask %u invalid for IPv4 address\n", 1149126353Smlaier unmask(m, AF_INET6)); 1150126353Smlaier return (1); 1151126353Smlaier } 1152126353Smlaier } 1153126353Smlaier return (0); 1154126353Smlaier} 1155126353Smlaier 1156126353Smlaier/* interface lookup routines */ 1157126353Smlaier 1158126353Smlaierstruct node_host *iftab; 1159126353Smlaier 1160126353Smlaiervoid 1161126353Smlaierifa_load(void) 1162126353Smlaier{ 1163126353Smlaier struct ifaddrs *ifap, *ifa; 1164126353Smlaier struct node_host *n = NULL, *h = NULL; 1165126353Smlaier 1166126353Smlaier if (getifaddrs(&ifap) < 0) 1167126353Smlaier err(1, "getifaddrs"); 1168126353Smlaier 1169126353Smlaier for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1170126353Smlaier if (!(ifa->ifa_addr->sa_family == AF_INET || 1171126353Smlaier ifa->ifa_addr->sa_family == AF_INET6 || 1172126353Smlaier ifa->ifa_addr->sa_family == AF_LINK)) 1173126353Smlaier continue; 1174126353Smlaier n = calloc(1, sizeof(struct node_host)); 1175126353Smlaier if (n == NULL) 1176126353Smlaier err(1, "address: calloc"); 1177126353Smlaier n->af = ifa->ifa_addr->sa_family; 1178126353Smlaier n->ifa_flags = ifa->ifa_flags; 1179126353Smlaier#ifdef __KAME__ 1180126353Smlaier if (n->af == AF_INET6 && 1181126353Smlaier IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) 1182126353Smlaier ifa->ifa_addr)->sin6_addr) && 1183130617Smlaier ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 1184130617Smlaier 0) { 1185126353Smlaier struct sockaddr_in6 *sin6; 1186126353Smlaier 1187126353Smlaier sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 1188126353Smlaier sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | 1189126353Smlaier sin6->sin6_addr.s6_addr[3]; 1190126353Smlaier sin6->sin6_addr.s6_addr[2] = 0; 1191126353Smlaier sin6->sin6_addr.s6_addr[3] = 0; 1192126353Smlaier } 1193126353Smlaier#endif 1194126353Smlaier n->ifindex = 0; 1195126353Smlaier if (n->af == AF_INET) { 1196126353Smlaier memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) 1197126353Smlaier ifa->ifa_addr)->sin_addr.s_addr, 1198126353Smlaier sizeof(struct in_addr)); 1199126353Smlaier memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) 1200126353Smlaier ifa->ifa_netmask)->sin_addr.s_addr, 1201126353Smlaier sizeof(struct in_addr)); 1202126353Smlaier if (ifa->ifa_broadaddr != NULL) 1203126353Smlaier memcpy(&n->bcast, &((struct sockaddr_in *) 1204126353Smlaier ifa->ifa_broadaddr)->sin_addr.s_addr, 1205126353Smlaier sizeof(struct in_addr)); 1206130617Smlaier if (ifa->ifa_dstaddr != NULL) 1207130617Smlaier memcpy(&n->peer, &((struct sockaddr_in *) 1208130617Smlaier ifa->ifa_dstaddr)->sin_addr.s_addr, 1209130617Smlaier sizeof(struct in_addr)); 1210126353Smlaier } else if (n->af == AF_INET6) { 1211126353Smlaier memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) 1212126353Smlaier ifa->ifa_addr)->sin6_addr.s6_addr, 1213126353Smlaier sizeof(struct in6_addr)); 1214126353Smlaier memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) 1215126353Smlaier ifa->ifa_netmask)->sin6_addr.s6_addr, 1216126353Smlaier sizeof(struct in6_addr)); 1217126353Smlaier if (ifa->ifa_broadaddr != NULL) 1218126353Smlaier memcpy(&n->bcast, &((struct sockaddr_in6 *) 1219126353Smlaier ifa->ifa_broadaddr)->sin6_addr.s6_addr, 1220126353Smlaier sizeof(struct in6_addr)); 1221130617Smlaier if (ifa->ifa_dstaddr != NULL) 1222130617Smlaier memcpy(&n->peer, &((struct sockaddr_in6 *) 1223130617Smlaier ifa->ifa_dstaddr)->sin6_addr.s6_addr, 1224130617Smlaier sizeof(struct in6_addr)); 1225126353Smlaier n->ifindex = ((struct sockaddr_in6 *) 1226126353Smlaier ifa->ifa_addr)->sin6_scope_id; 1227126353Smlaier } 1228126353Smlaier if ((n->ifname = strdup(ifa->ifa_name)) == NULL) 1229126353Smlaier err(1, "ifa_load: strdup"); 1230126353Smlaier n->next = NULL; 1231126353Smlaier n->tail = n; 1232126353Smlaier if (h == NULL) 1233126353Smlaier h = n; 1234126353Smlaier else { 1235126353Smlaier h->tail->next = n; 1236126353Smlaier h->tail = n; 1237126353Smlaier } 1238126353Smlaier } 1239130617Smlaier 1240126353Smlaier iftab = h; 1241126353Smlaier freeifaddrs(ifap); 1242126353Smlaier} 1243126353Smlaier 1244259916Sbzint 1245259916Sbzget_socket_domain(void) 1246259916Sbz{ 1247259916Sbz int sdom; 1248259916Sbz 1249259916Sbz sdom = AF_UNSPEC; 1250259916Sbz#ifdef WITH_INET6 1251259916Sbz if (sdom == AF_UNSPEC && feature_present("inet6")) 1252259916Sbz sdom = AF_INET6; 1253259916Sbz#endif 1254259916Sbz#ifdef WITH_INET 1255259916Sbz if (sdom == AF_UNSPEC && feature_present("inet")) 1256259916Sbz sdom = AF_INET; 1257259916Sbz#endif 1258259916Sbz if (sdom == AF_UNSPEC) 1259259916Sbz sdom = AF_LINK; 1260259916Sbz 1261259916Sbz return (sdom); 1262259916Sbz} 1263259916Sbz 1264126353Smlaierstruct node_host * 1265171172Smlaierifa_exists(const char *ifa_name) 1266126353Smlaier{ 1267126353Smlaier struct node_host *n; 1268171172Smlaier struct ifgroupreq ifgr; 1269171172Smlaier int s; 1270126353Smlaier 1271126353Smlaier if (iftab == NULL) 1272126353Smlaier ifa_load(); 1273126353Smlaier 1274171172Smlaier /* check wether this is a group */ 1275259916Sbz if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) 1276171172Smlaier err(1, "socket"); 1277171172Smlaier bzero(&ifgr, sizeof(ifgr)); 1278171172Smlaier strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); 1279171172Smlaier if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == 0) { 1280171172Smlaier /* fake a node_host */ 1281171172Smlaier if ((n = calloc(1, sizeof(*n))) == NULL) 1282171172Smlaier err(1, "calloc"); 1283171172Smlaier if ((n->ifname = strdup(ifa_name)) == NULL) 1284171172Smlaier err(1, "strdup"); 1285171172Smlaier close(s); 1286171172Smlaier return (n); 1287171172Smlaier } 1288171172Smlaier close(s); 1289171172Smlaier 1290126353Smlaier for (n = iftab; n; n = n->next) { 1291126353Smlaier if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) 1292126353Smlaier return (n); 1293126353Smlaier } 1294145840Smlaier 1295126353Smlaier return (NULL); 1296126353Smlaier} 1297126353Smlaier 1298126353Smlaierstruct node_host * 1299171172Smlaierifa_grouplookup(const char *ifa_name, int flags) 1300171172Smlaier{ 1301171172Smlaier struct ifg_req *ifg; 1302171172Smlaier struct ifgroupreq ifgr; 1303171172Smlaier int s, len; 1304171172Smlaier struct node_host *n, *h = NULL; 1305171172Smlaier 1306259916Sbz if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) 1307171172Smlaier err(1, "socket"); 1308171172Smlaier bzero(&ifgr, sizeof(ifgr)); 1309171172Smlaier strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); 1310171172Smlaier if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) { 1311171172Smlaier close(s); 1312171172Smlaier return (NULL); 1313171172Smlaier } 1314171172Smlaier 1315171172Smlaier len = ifgr.ifgr_len; 1316171172Smlaier if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 1317171172Smlaier err(1, "calloc"); 1318171172Smlaier if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 1319171172Smlaier err(1, "SIOCGIFGMEMB"); 1320171172Smlaier 1321171172Smlaier for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req); 1322171172Smlaier ifg++) { 1323171172Smlaier len -= sizeof(struct ifg_req); 1324171172Smlaier if ((n = ifa_lookup(ifg->ifgrq_member, flags)) == NULL) 1325171172Smlaier continue; 1326171172Smlaier if (h == NULL) 1327171172Smlaier h = n; 1328171172Smlaier else { 1329171172Smlaier h->tail->next = n; 1330171172Smlaier h->tail = n->tail; 1331171172Smlaier } 1332171172Smlaier } 1333171172Smlaier free(ifgr.ifgr_groups); 1334171172Smlaier close(s); 1335171172Smlaier 1336171172Smlaier return (h); 1337171172Smlaier} 1338171172Smlaier 1339171172Smlaierstruct node_host * 1340130617Smlaierifa_lookup(const char *ifa_name, int flags) 1341126353Smlaier{ 1342126353Smlaier struct node_host *p = NULL, *h = NULL, *n = NULL; 1343145840Smlaier int got4 = 0, got6 = 0; 1344130617Smlaier const char *last_if = NULL; 1345126353Smlaier 1346171172Smlaier if ((h = ifa_grouplookup(ifa_name, flags)) != NULL) 1347171172Smlaier return (h); 1348171172Smlaier 1349126353Smlaier if (!strncmp(ifa_name, "self", IFNAMSIZ)) 1350145840Smlaier ifa_name = NULL; 1351126353Smlaier 1352126353Smlaier if (iftab == NULL) 1353126353Smlaier ifa_load(); 1354126353Smlaier 1355126353Smlaier for (p = iftab; p; p = p->next) { 1356145840Smlaier if (ifa_skip_if(ifa_name, p)) 1357126353Smlaier continue; 1358130617Smlaier if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET) 1359126353Smlaier continue; 1360130617Smlaier if ((flags & PFI_AFLAG_BROADCAST) && 1361130617Smlaier !(p->ifa_flags & IFF_BROADCAST)) 1362126353Smlaier continue; 1363130617Smlaier if ((flags & PFI_AFLAG_PEER) && 1364130617Smlaier !(p->ifa_flags & IFF_POINTOPOINT)) 1365130617Smlaier continue; 1366130617Smlaier if ((flags & PFI_AFLAG_NETWORK) && p->ifindex > 0) 1367130617Smlaier continue; 1368130617Smlaier if (last_if == NULL || strcmp(last_if, p->ifname)) 1369130617Smlaier got4 = got6 = 0; 1370130617Smlaier last_if = p->ifname; 1371130617Smlaier if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET && got4) 1372130617Smlaier continue; 1373130617Smlaier if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && got6) 1374130617Smlaier continue; 1375130617Smlaier if (p->af == AF_INET) 1376130617Smlaier got4 = 1; 1377130617Smlaier else 1378130617Smlaier got6 = 1; 1379126353Smlaier n = calloc(1, sizeof(struct node_host)); 1380126353Smlaier if (n == NULL) 1381126353Smlaier err(1, "address: calloc"); 1382126353Smlaier n->af = p->af; 1383130617Smlaier if (flags & PFI_AFLAG_BROADCAST) 1384126353Smlaier memcpy(&n->addr.v.a.addr, &p->bcast, 1385126353Smlaier sizeof(struct pf_addr)); 1386130617Smlaier else if (flags & PFI_AFLAG_PEER) 1387130617Smlaier memcpy(&n->addr.v.a.addr, &p->peer, 1388130617Smlaier sizeof(struct pf_addr)); 1389126353Smlaier else 1390126353Smlaier memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, 1391126353Smlaier sizeof(struct pf_addr)); 1392130617Smlaier if (flags & PFI_AFLAG_NETWORK) 1393126353Smlaier set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); 1394126353Smlaier else { 1395126353Smlaier if (n->af == AF_INET) { 1396126353Smlaier if (p->ifa_flags & IFF_LOOPBACK && 1397126353Smlaier p->ifa_flags & IFF_LINK1) 1398126353Smlaier memcpy(&n->addr.v.a.mask, 1399126353Smlaier &p->addr.v.a.mask, 1400126353Smlaier sizeof(struct pf_addr)); 1401126353Smlaier else 1402126353Smlaier set_ipmask(n, 32); 1403126353Smlaier } else 1404126353Smlaier set_ipmask(n, 128); 1405126353Smlaier } 1406126353Smlaier n->ifindex = p->ifindex; 1407340779Skp n->ifname = strdup(p->ifname); 1408126353Smlaier 1409126353Smlaier n->next = NULL; 1410126353Smlaier n->tail = n; 1411126353Smlaier if (h == NULL) 1412126353Smlaier h = n; 1413126353Smlaier else { 1414126353Smlaier h->tail->next = n; 1415126353Smlaier h->tail = n; 1416126353Smlaier } 1417126353Smlaier } 1418126353Smlaier return (h); 1419126353Smlaier} 1420126353Smlaier 1421145840Smlaierint 1422145840Smlaierifa_skip_if(const char *filter, struct node_host *p) 1423145840Smlaier{ 1424145840Smlaier int n; 1425145840Smlaier 1426145840Smlaier if (p->af != AF_INET && p->af != AF_INET6) 1427145840Smlaier return (1); 1428145840Smlaier if (filter == NULL || !*filter) 1429145840Smlaier return (0); 1430145840Smlaier if (!strcmp(p->ifname, filter)) 1431145840Smlaier return (0); /* exact match */ 1432145840Smlaier n = strlen(filter); 1433145840Smlaier if (n < 1 || n >= IFNAMSIZ) 1434145840Smlaier return (1); /* sanity check */ 1435145840Smlaier if (filter[n-1] >= '0' && filter[n-1] <= '9') 1436145840Smlaier return (1); /* only do exact match in that case */ 1437145840Smlaier if (strncmp(p->ifname, filter, n)) 1438145840Smlaier return (1); /* prefix doesn't match */ 1439145840Smlaier return (p->ifname[n] < '0' || p->ifname[n] > '9'); 1440145840Smlaier} 1441145840Smlaier 1442145840Smlaier 1443126353Smlaierstruct node_host * 1444126353Smlaierhost(const char *s) 1445126353Smlaier{ 1446126353Smlaier struct node_host *h = NULL; 1447126353Smlaier int mask, v4mask, v6mask, cont = 1; 1448126353Smlaier char *p, *q, *ps; 1449126353Smlaier 1450126353Smlaier if ((p = strrchr(s, '/')) != NULL) { 1451126353Smlaier mask = strtol(p+1, &q, 0); 1452126353Smlaier if (!q || *q || mask > 128 || q == (p+1)) { 1453145840Smlaier fprintf(stderr, "invalid netmask '%s'\n", p); 1454126353Smlaier return (NULL); 1455126353Smlaier } 1456126353Smlaier if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 1457126353Smlaier err(1, "host: malloc"); 1458126353Smlaier strlcpy(ps, s, strlen(s) - strlen(p) + 1); 1459126353Smlaier v4mask = v6mask = mask; 1460126353Smlaier } else { 1461126353Smlaier if ((ps = strdup(s)) == NULL) 1462126353Smlaier err(1, "host: strdup"); 1463126353Smlaier v4mask = 32; 1464126353Smlaier v6mask = 128; 1465126353Smlaier mask = -1; 1466126353Smlaier } 1467126353Smlaier 1468126353Smlaier /* IPv4 address? */ 1469126353Smlaier if (cont && (h = host_v4(s, mask)) != NULL) 1470126353Smlaier cont = 0; 1471126353Smlaier 1472126353Smlaier /* IPv6 address? */ 1473126353Smlaier if (cont && (h = host_v6(ps, v6mask)) != NULL) 1474126353Smlaier cont = 0; 1475126353Smlaier 1476359573Skp /* interface with this name exists? */ 1477359573Skp /* expensive with thousands of interfaces - prioritze IPv4/6 check */ 1478359573Skp if (cont && (h = host_if(ps, mask)) != NULL) 1479359573Skp cont = 0; 1480359573Skp 1481126353Smlaier /* dns lookup */ 1482126353Smlaier if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL) 1483126353Smlaier cont = 0; 1484126353Smlaier free(ps); 1485126353Smlaier 1486126353Smlaier if (h == NULL || cont == 1) { 1487126353Smlaier fprintf(stderr, "no IP address found for %s\n", s); 1488126353Smlaier return (NULL); 1489126353Smlaier } 1490126353Smlaier return (h); 1491126353Smlaier} 1492126353Smlaier 1493126353Smlaierstruct node_host * 1494126353Smlaierhost_if(const char *s, int mask) 1495126353Smlaier{ 1496126353Smlaier struct node_host *n, *h = NULL; 1497126353Smlaier char *p, *ps; 1498130617Smlaier int flags = 0; 1499126353Smlaier 1500130617Smlaier if ((ps = strdup(s)) == NULL) 1501130617Smlaier err(1, "host_if: strdup"); 1502130617Smlaier while ((p = strrchr(ps, ':')) != NULL) { 1503126353Smlaier if (!strcmp(p+1, "network")) 1504130617Smlaier flags |= PFI_AFLAG_NETWORK; 1505130617Smlaier else if (!strcmp(p+1, "broadcast")) 1506130617Smlaier flags |= PFI_AFLAG_BROADCAST; 1507130617Smlaier else if (!strcmp(p+1, "peer")) 1508130617Smlaier flags |= PFI_AFLAG_PEER; 1509130617Smlaier else if (!strcmp(p+1, "0")) 1510130617Smlaier flags |= PFI_AFLAG_NOALIAS; 1511130617Smlaier else { 1512130617Smlaier free(ps); 1513126353Smlaier return (NULL); 1514126353Smlaier } 1515130617Smlaier *p = '\0'; 1516130617Smlaier } 1517130617Smlaier if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */ 1518130617Smlaier fprintf(stderr, "illegal combination of interface modifiers\n"); 1519130617Smlaier free(ps); 1520130617Smlaier return (NULL); 1521130617Smlaier } 1522130617Smlaier if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) { 1523130617Smlaier fprintf(stderr, "network or broadcast lookup, but " 1524130617Smlaier "extra netmask given\n"); 1525130617Smlaier free(ps); 1526130617Smlaier return (NULL); 1527130617Smlaier } 1528171172Smlaier if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) { 1529126353Smlaier /* interface with this name exists */ 1530130617Smlaier h = ifa_lookup(ps, flags); 1531126353Smlaier for (n = h; n != NULL && mask > -1; n = n->next) 1532126353Smlaier set_ipmask(n, mask); 1533126353Smlaier } 1534126353Smlaier 1535126353Smlaier free(ps); 1536126353Smlaier return (h); 1537126353Smlaier} 1538126353Smlaier 1539126353Smlaierstruct node_host * 1540126353Smlaierhost_v4(const char *s, int mask) 1541126353Smlaier{ 1542126353Smlaier struct node_host *h = NULL; 1543126353Smlaier struct in_addr ina; 1544130617Smlaier int bits = 32; 1545126353Smlaier 1546126353Smlaier memset(&ina, 0, sizeof(struct in_addr)); 1547130617Smlaier if (strrchr(s, '/') != NULL) { 1548130617Smlaier if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 1549130617Smlaier return (NULL); 1550130617Smlaier } else { 1551130617Smlaier if (inet_pton(AF_INET, s, &ina) != 1) 1552130617Smlaier return (NULL); 1553126353Smlaier } 1554126353Smlaier 1555130617Smlaier h = calloc(1, sizeof(struct node_host)); 1556130617Smlaier if (h == NULL) 1557130617Smlaier err(1, "address: calloc"); 1558130617Smlaier h->ifname = NULL; 1559130617Smlaier h->af = AF_INET; 1560130617Smlaier h->addr.v.a.addr.addr32[0] = ina.s_addr; 1561130617Smlaier set_ipmask(h, bits); 1562130617Smlaier h->next = NULL; 1563130617Smlaier h->tail = h; 1564130617Smlaier 1565126353Smlaier return (h); 1566126353Smlaier} 1567126353Smlaier 1568126353Smlaierstruct node_host * 1569126353Smlaierhost_v6(const char *s, int mask) 1570126353Smlaier{ 1571126353Smlaier struct addrinfo hints, *res; 1572126353Smlaier struct node_host *h = NULL; 1573126353Smlaier 1574126353Smlaier memset(&hints, 0, sizeof(hints)); 1575126353Smlaier hints.ai_family = AF_INET6; 1576126353Smlaier hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 1577126353Smlaier hints.ai_flags = AI_NUMERICHOST; 1578126353Smlaier if (getaddrinfo(s, "0", &hints, &res) == 0) { 1579126353Smlaier h = calloc(1, sizeof(struct node_host)); 1580126353Smlaier if (h == NULL) 1581126353Smlaier err(1, "address: calloc"); 1582126353Smlaier h->ifname = NULL; 1583126353Smlaier h->af = AF_INET6; 1584126353Smlaier memcpy(&h->addr.v.a.addr, 1585126353Smlaier &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 1586126353Smlaier sizeof(h->addr.v.a.addr)); 1587126353Smlaier h->ifindex = 1588126353Smlaier ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 1589126353Smlaier set_ipmask(h, mask); 1590126353Smlaier freeaddrinfo(res); 1591126353Smlaier h->next = NULL; 1592126353Smlaier h->tail = h; 1593126353Smlaier } 1594126353Smlaier 1595126353Smlaier return (h); 1596126353Smlaier} 1597126353Smlaier 1598126353Smlaierstruct node_host * 1599126353Smlaierhost_dns(const char *s, int v4mask, int v6mask) 1600126353Smlaier{ 1601126353Smlaier struct addrinfo hints, *res0, *res; 1602126353Smlaier struct node_host *n, *h = NULL; 1603130617Smlaier int error, noalias = 0; 1604130617Smlaier int got4 = 0, got6 = 0; 1605130617Smlaier char *p, *ps; 1606126353Smlaier 1607130617Smlaier if ((ps = strdup(s)) == NULL) 1608145840Smlaier err(1, "host_dns: strdup"); 1609130617Smlaier if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) { 1610130617Smlaier noalias = 1; 1611130617Smlaier *p = '\0'; 1612130617Smlaier } 1613126353Smlaier memset(&hints, 0, sizeof(hints)); 1614126353Smlaier hints.ai_family = PF_UNSPEC; 1615126353Smlaier hints.ai_socktype = SOCK_STREAM; /* DUMMY */ 1616130617Smlaier error = getaddrinfo(ps, NULL, &hints, &res0); 1617145840Smlaier if (error) { 1618145840Smlaier free(ps); 1619126353Smlaier return (h); 1620145840Smlaier } 1621126353Smlaier 1622126353Smlaier for (res = res0; res; res = res->ai_next) { 1623126353Smlaier if (res->ai_family != AF_INET && 1624126353Smlaier res->ai_family != AF_INET6) 1625126353Smlaier continue; 1626130617Smlaier if (noalias) { 1627130617Smlaier if (res->ai_family == AF_INET) { 1628130617Smlaier if (got4) 1629130617Smlaier continue; 1630130617Smlaier got4 = 1; 1631130617Smlaier } else { 1632130617Smlaier if (got6) 1633130617Smlaier continue; 1634130617Smlaier got6 = 1; 1635130617Smlaier } 1636130617Smlaier } 1637126353Smlaier n = calloc(1, sizeof(struct node_host)); 1638126353Smlaier if (n == NULL) 1639126353Smlaier err(1, "host_dns: calloc"); 1640126353Smlaier n->ifname = NULL; 1641126353Smlaier n->af = res->ai_family; 1642126353Smlaier if (res->ai_family == AF_INET) { 1643126353Smlaier memcpy(&n->addr.v.a.addr, 1644126353Smlaier &((struct sockaddr_in *) 1645126353Smlaier res->ai_addr)->sin_addr.s_addr, 1646126353Smlaier sizeof(struct in_addr)); 1647126353Smlaier set_ipmask(n, v4mask); 1648126353Smlaier } else { 1649126353Smlaier memcpy(&n->addr.v.a.addr, 1650126353Smlaier &((struct sockaddr_in6 *) 1651126353Smlaier res->ai_addr)->sin6_addr.s6_addr, 1652126353Smlaier sizeof(struct in6_addr)); 1653126353Smlaier n->ifindex = 1654126353Smlaier ((struct sockaddr_in6 *) 1655126353Smlaier res->ai_addr)->sin6_scope_id; 1656126353Smlaier set_ipmask(n, v6mask); 1657126353Smlaier } 1658126353Smlaier n->next = NULL; 1659126353Smlaier n->tail = n; 1660126353Smlaier if (h == NULL) 1661126353Smlaier h = n; 1662126353Smlaier else { 1663126353Smlaier h->tail->next = n; 1664126353Smlaier h->tail = n; 1665126353Smlaier } 1666126353Smlaier } 1667126353Smlaier freeaddrinfo(res0); 1668130617Smlaier free(ps); 1669126353Smlaier 1670126353Smlaier return (h); 1671126353Smlaier} 1672126353Smlaier 1673126353Smlaier/* 1674126353Smlaier * convert a hostname to a list of addresses and put them in the given buffer. 1675126353Smlaier * test: 1676126353Smlaier * if set to 1, only simple addresses are accepted (no netblock, no "!"). 1677126353Smlaier */ 1678126353Smlaierint 1679126353Smlaierappend_addr(struct pfr_buffer *b, char *s, int test) 1680126353Smlaier{ 1681126353Smlaier char *r; 1682126353Smlaier struct node_host *h, *n; 1683126353Smlaier int rv, not = 0; 1684126353Smlaier 1685126353Smlaier for (r = s; *r == '!'; r++) 1686126353Smlaier not = !not; 1687126353Smlaier if ((n = host(r)) == NULL) { 1688126353Smlaier errno = 0; 1689126353Smlaier return (-1); 1690126353Smlaier } 1691126353Smlaier rv = append_addr_host(b, n, test, not); 1692126353Smlaier do { 1693126353Smlaier h = n; 1694126353Smlaier n = n->next; 1695126353Smlaier free(h); 1696126353Smlaier } while (n != NULL); 1697126353Smlaier return (rv); 1698126353Smlaier} 1699126353Smlaier 1700126353Smlaier/* 1701126353Smlaier * same as previous function, but with a pre-parsed input and the ability 1702126353Smlaier * to "negate" the result. Does not free the node_host list. 1703126353Smlaier * not: 1704126353Smlaier * setting it to 1 is equivalent to adding "!" in front of parameter s. 1705126353Smlaier */ 1706126353Smlaierint 1707126353Smlaierappend_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not) 1708126353Smlaier{ 1709126353Smlaier int bits; 1710126353Smlaier struct pfr_addr addr; 1711126353Smlaier 1712126353Smlaier do { 1713126353Smlaier bzero(&addr, sizeof(addr)); 1714126353Smlaier addr.pfra_not = n->not ^ not; 1715126353Smlaier addr.pfra_af = n->af; 1716126353Smlaier addr.pfra_net = unmask(&n->addr.v.a.mask, n->af); 1717126353Smlaier switch (n->af) { 1718126353Smlaier case AF_INET: 1719126353Smlaier addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0]; 1720126353Smlaier bits = 32; 1721126353Smlaier break; 1722126353Smlaier case AF_INET6: 1723126353Smlaier memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6, 1724126353Smlaier sizeof(struct in6_addr)); 1725126353Smlaier bits = 128; 1726126353Smlaier break; 1727126353Smlaier default: 1728126353Smlaier errno = EINVAL; 1729126353Smlaier return (-1); 1730126353Smlaier } 1731126353Smlaier if ((test && (not || addr.pfra_net != bits)) || 1732126353Smlaier addr.pfra_net > bits) { 1733126353Smlaier errno = EINVAL; 1734126353Smlaier return (-1); 1735126353Smlaier } 1736126353Smlaier if (pfr_buf_add(b, &addr)) 1737126353Smlaier return (-1); 1738126353Smlaier } while ((n = n->next) != NULL); 1739126353Smlaier 1740126353Smlaier return (0); 1741126353Smlaier} 1742130617Smlaier 1743130617Smlaierint 1744145840Smlaierpfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor) 1745130617Smlaier{ 1746130617Smlaier struct pfioc_trans_e trans; 1747130617Smlaier 1748130617Smlaier bzero(&trans, sizeof(trans)); 1749130617Smlaier trans.rs_num = rs_num; 1750130617Smlaier if (strlcpy(trans.anchor, anchor, 1751145840Smlaier sizeof(trans.anchor)) >= sizeof(trans.anchor)) 1752130617Smlaier errx(1, "pfctl_add_trans: strlcpy"); 1753130617Smlaier 1754130617Smlaier return pfr_buf_add(buf, &trans); 1755130617Smlaier} 1756130617Smlaier 1757130617Smlaieru_int32_t 1758145840Smlaierpfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor) 1759130617Smlaier{ 1760130617Smlaier struct pfioc_trans_e *p; 1761130617Smlaier 1762130617Smlaier PFRB_FOREACH(p, buf) 1763145840Smlaier if (rs_num == p->rs_num && !strcmp(anchor, p->anchor)) 1764130617Smlaier return (p->ticket); 1765145840Smlaier errx(1, "pfctl_get_ticket: assertion failed"); 1766130617Smlaier} 1767130617Smlaier 1768130617Smlaierint 1769130617Smlaierpfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from) 1770130617Smlaier{ 1771130617Smlaier struct pfioc_trans trans; 1772130617Smlaier 1773130617Smlaier bzero(&trans, sizeof(trans)); 1774130617Smlaier trans.size = buf->pfrb_size - from; 1775130617Smlaier trans.esize = sizeof(struct pfioc_trans_e); 1776130617Smlaier trans.array = ((struct pfioc_trans_e *)buf->pfrb_caddr) + from; 1777130617Smlaier return ioctl(dev, cmd, &trans); 1778130617Smlaier} 1779