1223637Sbz/* $OpenBSD: pfctl_parser.c,v 1.240 2008/06/10 20:55:02 mcbride Exp $ */ 2126353Smlaier 3126353Smlaier/* 4126353Smlaier * Copyright (c) 2001 Daniel Hartmeier 5130617Smlaier * Copyright (c) 2002,2003 Henning Brauer 6126353Smlaier * All rights reserved. 7126353Smlaier * 8126353Smlaier * Redistribution and use in source and binary forms, with or without 9126353Smlaier * modification, are permitted provided that the following conditions 10126353Smlaier * are met: 11126353Smlaier * 12126353Smlaier * - Redistributions of source code must retain the above copyright 13126353Smlaier * notice, this list of conditions and the following disclaimer. 14126353Smlaier * - Redistributions in binary form must reproduce the above 15126353Smlaier * copyright notice, this list of conditions and the following 16126353Smlaier * disclaimer in the documentation and/or other materials provided 17126353Smlaier * with the distribution. 18126353Smlaier * 19126353Smlaier * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20126353Smlaier * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21126353Smlaier * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22126353Smlaier * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23126353Smlaier * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24126353Smlaier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25126353Smlaier * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26126353Smlaier * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27126353Smlaier * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28126353Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 29126353Smlaier * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30126353Smlaier * POSSIBILITY OF SUCH DAMAGE. 31126353Smlaier * 32126353Smlaier */ 33126353Smlaier 34127082Sobrien#include <sys/cdefs.h> 35127082Sobrien__FBSDID("$FreeBSD$"); 36127082Sobrien 37126353Smlaier#include <sys/types.h> 38130617Smlaier#include <sys/ioctl.h> 39126353Smlaier#include <sys/socket.h> 40145840Smlaier#include <sys/param.h> 41145840Smlaier#include <sys/proc.h> 42126353Smlaier#include <net/if.h> 43126353Smlaier#include <netinet/in.h> 44126353Smlaier#include <netinet/in_systm.h> 45126353Smlaier#include <netinet/ip.h> 46126353Smlaier#include <netinet/ip_icmp.h> 47126353Smlaier#include <netinet/icmp6.h> 48126353Smlaier#include <net/pfvar.h> 49126353Smlaier#include <arpa/inet.h> 50126353Smlaier 51126353Smlaier#include <stdio.h> 52126353Smlaier#include <stdlib.h> 53126353Smlaier#include <string.h> 54126353Smlaier#include <ctype.h> 55126353Smlaier#include <netdb.h> 56126353Smlaier#include <stdarg.h> 57126353Smlaier#include <errno.h> 58126353Smlaier#include <err.h> 59126353Smlaier#include <ifaddrs.h> 60171172Smlaier#include <unistd.h> 61126353Smlaier 62126353Smlaier#include "pfctl_parser.h" 63126353Smlaier#include "pfctl.h" 64126353Smlaier 65126353Smlaiervoid print_op (u_int8_t, const char *, const char *); 66223057Sbzvoid print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int); 67126353Smlaiervoid print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned); 68126353Smlaiervoid print_flags (u_int8_t); 69126353Smlaiervoid print_fromto(struct pf_rule_addr *, pf_osfp_t, 70223057Sbz struct pf_rule_addr *, u_int8_t, u_int8_t, int, int); 71145840Smlaierint ifa_skip_if(const char *filter, struct node_host *p); 72126353Smlaier 73171172Smlaierstruct node_host *ifa_grouplookup(const char *, int); 74126353Smlaierstruct node_host *host_if(const char *, int); 75126353Smlaierstruct node_host *host_v4(const char *, int); 76126353Smlaierstruct node_host *host_v6(const char *, int); 77126353Smlaierstruct node_host *host_dns(const char *, int, int); 78126353Smlaier 79126353Smlaierconst char *tcpflags = "FSRPAUEW"; 80126353Smlaier 81126353Smlaierstatic const struct icmptypeent icmp_type[] = { 82126353Smlaier { "echoreq", ICMP_ECHO }, 83126353Smlaier { "echorep", ICMP_ECHOREPLY }, 84126353Smlaier { "unreach", ICMP_UNREACH }, 85126353Smlaier { "squench", ICMP_SOURCEQUENCH }, 86126353Smlaier { "redir", ICMP_REDIRECT }, 87126353Smlaier { "althost", ICMP_ALTHOSTADDR }, 88126353Smlaier { "routeradv", ICMP_ROUTERADVERT }, 89126353Smlaier { "routersol", ICMP_ROUTERSOLICIT }, 90126353Smlaier { "timex", ICMP_TIMXCEED }, 91126353Smlaier { "paramprob", ICMP_PARAMPROB }, 92126353Smlaier { "timereq", ICMP_TSTAMP }, 93126353Smlaier { "timerep", ICMP_TSTAMPREPLY }, 94126353Smlaier { "inforeq", ICMP_IREQ }, 95126353Smlaier { "inforep", ICMP_IREQREPLY }, 96126353Smlaier { "maskreq", ICMP_MASKREQ }, 97126353Smlaier { "maskrep", ICMP_MASKREPLY }, 98126353Smlaier { "trace", ICMP_TRACEROUTE }, 99126353Smlaier { "dataconv", ICMP_DATACONVERR }, 100126353Smlaier { "mobredir", ICMP_MOBILE_REDIRECT }, 101126353Smlaier { "ipv6-where", ICMP_IPV6_WHEREAREYOU }, 102126353Smlaier { "ipv6-here", ICMP_IPV6_IAMHERE }, 103126353Smlaier { "mobregreq", ICMP_MOBILE_REGREQUEST }, 104126353Smlaier { "mobregrep", ICMP_MOBILE_REGREPLY }, 105126353Smlaier { "skip", ICMP_SKIP }, 106126353Smlaier { "photuris", ICMP_PHOTURIS } 107126353Smlaier}; 108126353Smlaier 109126353Smlaierstatic const struct icmptypeent icmp6_type[] = { 110126353Smlaier { "unreach", ICMP6_DST_UNREACH }, 111126353Smlaier { "toobig", ICMP6_PACKET_TOO_BIG }, 112126353Smlaier { "timex", ICMP6_TIME_EXCEEDED }, 113126353Smlaier { "paramprob", ICMP6_PARAM_PROB }, 114126353Smlaier { "echoreq", ICMP6_ECHO_REQUEST }, 115126353Smlaier { "echorep", ICMP6_ECHO_REPLY }, 116126353Smlaier { "groupqry", ICMP6_MEMBERSHIP_QUERY }, 117126353Smlaier { "listqry", MLD_LISTENER_QUERY }, 118126353Smlaier { "grouprep", ICMP6_MEMBERSHIP_REPORT }, 119126353Smlaier { "listenrep", MLD_LISTENER_REPORT }, 120126353Smlaier { "groupterm", ICMP6_MEMBERSHIP_REDUCTION }, 121126353Smlaier { "listendone", MLD_LISTENER_DONE }, 122126353Smlaier { "routersol", ND_ROUTER_SOLICIT }, 123126353Smlaier { "routeradv", ND_ROUTER_ADVERT }, 124126353Smlaier { "neighbrsol", ND_NEIGHBOR_SOLICIT }, 125126353Smlaier { "neighbradv", ND_NEIGHBOR_ADVERT }, 126126353Smlaier { "redir", ND_REDIRECT }, 127126353Smlaier { "routrrenum", ICMP6_ROUTER_RENUMBERING }, 128126353Smlaier { "wrureq", ICMP6_WRUREQUEST }, 129126353Smlaier { "wrurep", ICMP6_WRUREPLY }, 130126353Smlaier { "fqdnreq", ICMP6_FQDN_QUERY }, 131126353Smlaier { "fqdnrep", ICMP6_FQDN_REPLY }, 132126353Smlaier { "niqry", ICMP6_NI_QUERY }, 133126353Smlaier { "nirep", ICMP6_NI_REPLY }, 134126353Smlaier { "mtraceresp", MLD_MTRACE_RESP }, 135126353Smlaier { "mtrace", MLD_MTRACE } 136126353Smlaier}; 137126353Smlaier 138126353Smlaierstatic const struct icmpcodeent icmp_code[] = { 139126353Smlaier { "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET }, 140126353Smlaier { "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST }, 141126353Smlaier { "proto-unr", ICMP_UNREACH, ICMP_UNREACH_PROTOCOL }, 142126353Smlaier { "port-unr", ICMP_UNREACH, ICMP_UNREACH_PORT }, 143126353Smlaier { "needfrag", ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG }, 144126353Smlaier { "srcfail", ICMP_UNREACH, ICMP_UNREACH_SRCFAIL }, 145126353Smlaier { "net-unk", ICMP_UNREACH, ICMP_UNREACH_NET_UNKNOWN }, 146126353Smlaier { "host-unk", ICMP_UNREACH, ICMP_UNREACH_HOST_UNKNOWN }, 147126353Smlaier { "isolate", ICMP_UNREACH, ICMP_UNREACH_ISOLATED }, 148126353Smlaier { "net-prohib", ICMP_UNREACH, ICMP_UNREACH_NET_PROHIB }, 149126353Smlaier { "host-prohib", ICMP_UNREACH, ICMP_UNREACH_HOST_PROHIB }, 150126353Smlaier { "net-tos", ICMP_UNREACH, ICMP_UNREACH_TOSNET }, 151126353Smlaier { "host-tos", ICMP_UNREACH, ICMP_UNREACH_TOSHOST }, 152126353Smlaier { "filter-prohib", ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB }, 153126353Smlaier { "host-preced", ICMP_UNREACH, ICMP_UNREACH_HOST_PRECEDENCE }, 154126353Smlaier { "cutoff-preced", ICMP_UNREACH, ICMP_UNREACH_PRECEDENCE_CUTOFF }, 155126353Smlaier { "redir-net", ICMP_REDIRECT, ICMP_REDIRECT_NET }, 156126353Smlaier { "redir-host", ICMP_REDIRECT, ICMP_REDIRECT_HOST }, 157126353Smlaier { "redir-tos-net", ICMP_REDIRECT, ICMP_REDIRECT_TOSNET }, 158126353Smlaier { "redir-tos-host", ICMP_REDIRECT, ICMP_REDIRECT_TOSHOST }, 159126353Smlaier { "normal-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL }, 160126353Smlaier { "common-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON }, 161126353Smlaier { "transit", ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS }, 162126353Smlaier { "reassemb", ICMP_TIMXCEED, ICMP_TIMXCEED_REASS }, 163126353Smlaier { "badhead", ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR }, 164126353Smlaier { "optmiss", ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT }, 165126353Smlaier { "badlen", ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH }, 166126353Smlaier { "unknown-ind", ICMP_PHOTURIS, ICMP_PHOTURIS_UNKNOWN_INDEX }, 167126353Smlaier { "auth-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_AUTH_FAILED }, 168126353Smlaier { "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED } 169126353Smlaier}; 170126353Smlaier 171126353Smlaierstatic const struct icmpcodeent icmp6_code[] = { 172126353Smlaier { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN }, 173126353Smlaier { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE }, 174126353Smlaier { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR }, 175126353Smlaier { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE }, 176126353Smlaier { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR }, 177126353Smlaier { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT }, 178126353Smlaier { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT }, 179126353Smlaier { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY }, 180126353Smlaier { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER }, 181126353Smlaier { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER }, 182126353Smlaier { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK }, 183126353Smlaier { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER } 184126353Smlaier}; 185126353Smlaier 186126353Smlaierconst struct pf_timeout pf_timeouts[] = { 187126353Smlaier { "tcp.first", PFTM_TCP_FIRST_PACKET }, 188126353Smlaier { "tcp.opening", PFTM_TCP_OPENING }, 189126353Smlaier { "tcp.established", PFTM_TCP_ESTABLISHED }, 190126353Smlaier { "tcp.closing", PFTM_TCP_CLOSING }, 191126353Smlaier { "tcp.finwait", PFTM_TCP_FIN_WAIT }, 192126353Smlaier { "tcp.closed", PFTM_TCP_CLOSED }, 193145840Smlaier { "tcp.tsdiff", PFTM_TS_DIFF }, 194126353Smlaier { "udp.first", PFTM_UDP_FIRST_PACKET }, 195126353Smlaier { "udp.single", PFTM_UDP_SINGLE }, 196126353Smlaier { "udp.multiple", PFTM_UDP_MULTIPLE }, 197126353Smlaier { "icmp.first", PFTM_ICMP_FIRST_PACKET }, 198126353Smlaier { "icmp.error", PFTM_ICMP_ERROR_REPLY }, 199126353Smlaier { "other.first", PFTM_OTHER_FIRST_PACKET }, 200126353Smlaier { "other.single", PFTM_OTHER_SINGLE }, 201126353Smlaier { "other.multiple", PFTM_OTHER_MULTIPLE }, 202126353Smlaier { "frag", PFTM_FRAG }, 203126353Smlaier { "interval", PFTM_INTERVAL }, 204126353Smlaier { "adaptive.start", PFTM_ADAPTIVE_START }, 205126353Smlaier { "adaptive.end", PFTM_ADAPTIVE_END }, 206130617Smlaier { "src.track", PFTM_SRC_NODE }, 207126353Smlaier { NULL, 0 } 208126353Smlaier}; 209126353Smlaier 210126353Smlaierconst struct icmptypeent * 211126353Smlaiergeticmptypebynumber(u_int8_t type, sa_family_t af) 212126353Smlaier{ 213126353Smlaier unsigned int i; 214126353Smlaier 215126353Smlaier if (af != AF_INET6) { 216126353Smlaier for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); 217126353Smlaier i++) { 218126353Smlaier if (type == icmp_type[i].type) 219126353Smlaier return (&icmp_type[i]); 220126353Smlaier } 221126353Smlaier } else { 222126353Smlaier for (i=0; i < (sizeof (icmp6_type) / 223126353Smlaier sizeof(icmp6_type[0])); 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) { 237126353Smlaier for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); 238126353Smlaier i++) { 239126353Smlaier if (!strcmp(w, icmp_type[i].name)) 240126353Smlaier return (&icmp_type[i]); 241126353Smlaier } 242126353Smlaier } else { 243126353Smlaier for (i=0; i < (sizeof (icmp6_type) / 244126353Smlaier sizeof(icmp6_type[0])); i++) { 245126353Smlaier if (!strcmp(w, icmp6_type[i].name)) 246126353Smlaier return (&icmp6_type[i]); 247126353Smlaier } 248126353Smlaier } 249126353Smlaier return (NULL); 250126353Smlaier} 251126353Smlaier 252126353Smlaierconst struct icmpcodeent * 253126353Smlaiergeticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af) 254126353Smlaier{ 255126353Smlaier unsigned int i; 256126353Smlaier 257126353Smlaier if (af != AF_INET6) { 258126353Smlaier for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); 259126353Smlaier i++) { 260126353Smlaier if (type == icmp_code[i].type && 261126353Smlaier code == icmp_code[i].code) 262126353Smlaier return (&icmp_code[i]); 263126353Smlaier } 264126353Smlaier } else { 265126353Smlaier for (i=0; i < (sizeof (icmp6_code) / 266130617Smlaier sizeof(icmp6_code[0])); i++) { 267126353Smlaier if (type == icmp6_code[i].type && 268126353Smlaier code == icmp6_code[i].code) 269126353Smlaier return (&icmp6_code[i]); 270126353Smlaier } 271126353Smlaier } 272126353Smlaier return (NULL); 273126353Smlaier} 274126353Smlaier 275126353Smlaierconst struct icmpcodeent * 276126353Smlaiergeticmpcodebyname(u_long type, char *w, sa_family_t af) 277126353Smlaier{ 278126353Smlaier unsigned int i; 279126353Smlaier 280126353Smlaier if (af != AF_INET6) { 281126353Smlaier for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); 282126353Smlaier i++) { 283126353Smlaier if (type == icmp_code[i].type && 284126353Smlaier !strcmp(w, icmp_code[i].name)) 285126353Smlaier return (&icmp_code[i]); 286126353Smlaier } 287126353Smlaier } else { 288126353Smlaier for (i=0; i < (sizeof (icmp6_code) / 289126353Smlaier sizeof(icmp6_code[0])); i++) { 290126353Smlaier if (type == icmp6_code[i].type && 291126353Smlaier !strcmp(w, icmp6_code[i].name)) 292126353Smlaier return (&icmp6_code[i]); 293126353Smlaier } 294126353Smlaier } 295126353Smlaier return (NULL); 296126353Smlaier} 297126353Smlaier 298126353Smlaiervoid 299126353Smlaierprint_op(u_int8_t op, const char *a1, const char *a2) 300126353Smlaier{ 301126353Smlaier if (op == PF_OP_IRG) 302126353Smlaier printf(" %s >< %s", a1, a2); 303126353Smlaier else if (op == PF_OP_XRG) 304126353Smlaier printf(" %s <> %s", a1, a2); 305126353Smlaier else if (op == PF_OP_EQ) 306126353Smlaier printf(" = %s", a1); 307126353Smlaier else if (op == PF_OP_NE) 308126353Smlaier printf(" != %s", a1); 309126353Smlaier else if (op == PF_OP_LT) 310126353Smlaier printf(" < %s", a1); 311126353Smlaier else if (op == PF_OP_LE) 312126353Smlaier printf(" <= %s", a1); 313126353Smlaier else if (op == PF_OP_GT) 314126353Smlaier printf(" > %s", a1); 315126353Smlaier else if (op == PF_OP_GE) 316126353Smlaier printf(" >= %s", a1); 317126353Smlaier else if (op == PF_OP_RRG) 318126353Smlaier printf(" %s:%s", a1, a2); 319126353Smlaier} 320126353Smlaier 321126353Smlaiervoid 322223057Sbzprint_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int numeric) 323126353Smlaier{ 324126353Smlaier char a1[6], a2[6]; 325126353Smlaier struct servent *s; 326126353Smlaier 327223057Sbz if (!numeric) 328223057Sbz s = getservbyport(p1, proto); 329223057Sbz else 330223057Sbz s = NULL; 331126353Smlaier p1 = ntohs(p1); 332126353Smlaier p2 = ntohs(p2); 333126353Smlaier snprintf(a1, sizeof(a1), "%u", p1); 334126353Smlaier snprintf(a2, sizeof(a2), "%u", p2); 335126353Smlaier printf(" port"); 336126353Smlaier if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE)) 337126353Smlaier print_op(op, s->s_name, a2); 338126353Smlaier else 339126353Smlaier print_op(op, a1, a2); 340126353Smlaier} 341126353Smlaier 342126353Smlaiervoid 343126353Smlaierprint_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax) 344126353Smlaier{ 345126353Smlaier char a1[11], a2[11]; 346126353Smlaier 347126353Smlaier snprintf(a1, sizeof(a1), "%u", u1); 348126353Smlaier snprintf(a2, sizeof(a2), "%u", u2); 349126353Smlaier printf(" %s", t); 350126353Smlaier if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE)) 351126353Smlaier print_op(op, "unknown", a2); 352126353Smlaier else 353126353Smlaier print_op(op, a1, a2); 354126353Smlaier} 355126353Smlaier 356126353Smlaiervoid 357126353Smlaierprint_flags(u_int8_t f) 358126353Smlaier{ 359126353Smlaier int i; 360126353Smlaier 361126353Smlaier for (i = 0; tcpflags[i]; ++i) 362126353Smlaier if (f & (1 << i)) 363126353Smlaier printf("%c", tcpflags[i]); 364126353Smlaier} 365126353Smlaier 366126353Smlaiervoid 367126353Smlaierprint_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, 368223057Sbz sa_family_t af, u_int8_t proto, int verbose, int numeric) 369126353Smlaier{ 370126353Smlaier char buf[PF_OSFP_LEN*3]; 371126353Smlaier if (src->addr.type == PF_ADDR_ADDRMASK && 372126353Smlaier dst->addr.type == PF_ADDR_ADDRMASK && 373126353Smlaier PF_AZERO(&src->addr.v.a.addr, AF_INET6) && 374126353Smlaier PF_AZERO(&src->addr.v.a.mask, AF_INET6) && 375126353Smlaier PF_AZERO(&dst->addr.v.a.addr, AF_INET6) && 376126353Smlaier PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && 377145840Smlaier !src->neg && !dst->neg && 378126353Smlaier !src->port_op && !dst->port_op && 379126353Smlaier osfp == PF_OSFP_ANY) 380126353Smlaier printf(" all"); 381126353Smlaier else { 382126353Smlaier printf(" from "); 383145840Smlaier if (src->neg) 384126353Smlaier printf("! "); 385126353Smlaier print_addr(&src->addr, af, verbose); 386126353Smlaier if (src->port_op) 387126353Smlaier print_port(src->port_op, src->port[0], 388126353Smlaier src->port[1], 389223057Sbz proto == IPPROTO_TCP ? "tcp" : "udp", 390223057Sbz numeric); 391126353Smlaier if (osfp != PF_OSFP_ANY) 392126353Smlaier printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf, 393126353Smlaier sizeof(buf))); 394126353Smlaier 395126353Smlaier printf(" to "); 396145840Smlaier if (dst->neg) 397126353Smlaier printf("! "); 398126353Smlaier print_addr(&dst->addr, af, verbose); 399126353Smlaier if (dst->port_op) 400126353Smlaier print_port(dst->port_op, dst->port[0], 401126353Smlaier dst->port[1], 402223057Sbz proto == IPPROTO_TCP ? "tcp" : "udp", 403223057Sbz numeric); 404126353Smlaier } 405126353Smlaier} 406126353Smlaier 407126353Smlaiervoid 408126353Smlaierprint_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2, 409126353Smlaier sa_family_t af, int id) 410126353Smlaier{ 411126353Smlaier struct pf_pooladdr *pooladdr; 412126353Smlaier 413126353Smlaier if ((TAILQ_FIRST(&pool->list) != NULL) && 414126353Smlaier TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 415126353Smlaier printf("{ "); 416126353Smlaier TAILQ_FOREACH(pooladdr, &pool->list, entries){ 417126353Smlaier switch (id) { 418126353Smlaier case PF_NAT: 419126353Smlaier case PF_RDR: 420126353Smlaier case PF_BINAT: 421126353Smlaier print_addr(&pooladdr->addr, af, 0); 422126353Smlaier break; 423126353Smlaier case PF_PASS: 424126353Smlaier if (PF_AZERO(&pooladdr->addr.v.a.addr, af)) 425126353Smlaier printf("%s", pooladdr->ifname); 426126353Smlaier else { 427126353Smlaier printf("(%s ", pooladdr->ifname); 428126353Smlaier print_addr(&pooladdr->addr, af, 0); 429126353Smlaier printf(")"); 430126353Smlaier } 431126353Smlaier break; 432126353Smlaier default: 433126353Smlaier break; 434126353Smlaier } 435126353Smlaier if (TAILQ_NEXT(pooladdr, entries) != NULL) 436126353Smlaier printf(", "); 437126353Smlaier else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL) 438126353Smlaier printf(" }"); 439126353Smlaier } 440126353Smlaier switch (id) { 441126353Smlaier case PF_NAT: 442126353Smlaier if ((p1 != PF_NAT_PROXY_PORT_LOW || 443126353Smlaier p2 != PF_NAT_PROXY_PORT_HIGH) && (p1 != 0 || p2 != 0)) { 444126353Smlaier if (p1 == p2) 445126353Smlaier printf(" port %u", p1); 446126353Smlaier else 447126353Smlaier printf(" port %u:%u", p1, p2); 448126353Smlaier } 449126353Smlaier break; 450126353Smlaier case PF_RDR: 451126353Smlaier if (p1) { 452126353Smlaier printf(" port %u", p1); 453126353Smlaier if (p2 && (p2 != p1)) 454126353Smlaier printf(":%u", p2); 455126353Smlaier } 456126353Smlaier break; 457126353Smlaier default: 458126353Smlaier break; 459126353Smlaier } 460126353Smlaier switch (pool->opts & PF_POOL_TYPEMASK) { 461126353Smlaier case PF_POOL_NONE: 462126353Smlaier break; 463126353Smlaier case PF_POOL_BITMASK: 464126353Smlaier printf(" bitmask"); 465126353Smlaier break; 466126353Smlaier case PF_POOL_RANDOM: 467126353Smlaier printf(" random"); 468126353Smlaier break; 469126353Smlaier case PF_POOL_SRCHASH: 470126353Smlaier printf(" source-hash 0x%08x%08x%08x%08x", 471126353Smlaier pool->key.key32[0], pool->key.key32[1], 472126353Smlaier pool->key.key32[2], pool->key.key32[3]); 473126353Smlaier break; 474126353Smlaier case PF_POOL_ROUNDROBIN: 475126353Smlaier printf(" round-robin"); 476126353Smlaier break; 477126353Smlaier } 478130617Smlaier if (pool->opts & PF_POOL_STICKYADDR) 479130617Smlaier printf(" sticky-address"); 480126353Smlaier if (id == PF_NAT && p1 == 0 && p2 == 0) 481126353Smlaier printf(" static-port"); 482126353Smlaier} 483126353Smlaier 484126353Smlaierconst char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 485145840Smlaierconst char *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES; 486126353Smlaierconst char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 487130617Smlaierconst char *pf_scounters[FCNT_MAX+1] = FCNT_NAMES; 488126353Smlaier 489126353Smlaiervoid 490130617Smlaierprint_status(struct pf_status *s, int opts) 491126353Smlaier{ 492171172Smlaier char statline[80], *running; 493171172Smlaier time_t runtime; 494171172Smlaier int i; 495171172Smlaier char buf[PF_MD5_DIGEST_LENGTH * 2 + 1]; 496171172Smlaier static const char hex[] = "0123456789abcdef"; 497126353Smlaier 498126353Smlaier runtime = time(NULL) - s->since; 499130617Smlaier running = s->running ? "Enabled" : "Disabled"; 500126353Smlaier 501130617Smlaier if (s->since) { 502223637Sbz unsigned int sec, min, hrs, day = runtime; 503126353Smlaier 504126353Smlaier sec = day % 60; 505126353Smlaier day /= 60; 506126353Smlaier min = day % 60; 507126353Smlaier day /= 60; 508126353Smlaier hrs = day % 24; 509126353Smlaier day /= 24; 510126353Smlaier snprintf(statline, sizeof(statline), 511130617Smlaier "Status: %s for %u days %.2u:%.2u:%.2u", 512130617Smlaier running, day, hrs, min, sec); 513126353Smlaier } else 514130617Smlaier snprintf(statline, sizeof(statline), "Status: %s", running); 515126353Smlaier printf("%-44s", statline); 516126353Smlaier switch (s->debug) { 517130617Smlaier case PF_DEBUG_NONE: 518126353Smlaier printf("%15s\n\n", "Debug: None"); 519126353Smlaier break; 520130617Smlaier case PF_DEBUG_URGENT: 521126353Smlaier printf("%15s\n\n", "Debug: Urgent"); 522126353Smlaier break; 523130617Smlaier case PF_DEBUG_MISC: 524126353Smlaier printf("%15s\n\n", "Debug: Misc"); 525126353Smlaier break; 526130617Smlaier case PF_DEBUG_NOISY: 527130617Smlaier printf("%15s\n\n", "Debug: Loud"); 528130617Smlaier break; 529126353Smlaier } 530171172Smlaier 531171172Smlaier if (opts & PF_OPT_VERBOSE) { 532171172Smlaier printf("Hostid: 0x%08x\n", ntohl(s->hostid)); 533171172Smlaier 534171172Smlaier for (i = 0; i < PF_MD5_DIGEST_LENGTH; i++) { 535171172Smlaier buf[i + i] = hex[s->pf_chksum[i] >> 4]; 536171172Smlaier buf[i + i + 1] = hex[s->pf_chksum[i] & 0x0f]; 537171172Smlaier } 538171172Smlaier buf[i + i] = '\0'; 539171172Smlaier printf("Checksum: 0x%s\n\n", buf); 540171172Smlaier } 541171172Smlaier 542126353Smlaier if (s->ifname[0] != 0) { 543126353Smlaier printf("Interface Stats for %-16s %5s %16s\n", 544126353Smlaier s->ifname, "IPv4", "IPv6"); 545127024Smlaier printf(" %-25s %14llu %16llu\n", "Bytes In", 546127024Smlaier (unsigned long long)s->bcounters[0][0], 547127024Smlaier (unsigned long long)s->bcounters[1][0]); 548127024Smlaier printf(" %-25s %14llu %16llu\n", "Bytes Out", 549127024Smlaier (unsigned long long)s->bcounters[0][1], 550127024Smlaier (unsigned long long)s->bcounters[1][1]); 551126353Smlaier printf(" Packets In\n"); 552127024Smlaier printf(" %-23s %14llu %16llu\n", "Passed", 553127024Smlaier (unsigned long long)s->pcounters[0][0][PF_PASS], 554127024Smlaier (unsigned long long)s->pcounters[1][0][PF_PASS]); 555127024Smlaier printf(" %-23s %14llu %16llu\n", "Blocked", 556127024Smlaier (unsigned long long)s->pcounters[0][0][PF_DROP], 557127024Smlaier (unsigned long long)s->pcounters[1][0][PF_DROP]); 558126353Smlaier printf(" Packets Out\n"); 559127024Smlaier printf(" %-23s %14llu %16llu\n", "Passed", 560127024Smlaier (unsigned long long)s->pcounters[0][1][PF_PASS], 561127024Smlaier (unsigned long long)s->pcounters[1][1][PF_PASS]); 562127024Smlaier printf(" %-23s %14llu %16llu\n\n", "Blocked", 563127024Smlaier (unsigned long long)s->pcounters[0][1][PF_DROP], 564127024Smlaier (unsigned long long)s->pcounters[1][1][PF_DROP]); 565126353Smlaier } 566126353Smlaier printf("%-27s %14s %16s\n", "State Table", "Total", "Rate"); 567126353Smlaier printf(" %-25s %14u %14s\n", "current entries", s->states, ""); 568126353Smlaier for (i = 0; i < FCNT_MAX; i++) { 569127024Smlaier printf(" %-25s %14llu ", pf_fcounters[i], 570127024Smlaier (unsigned long long)s->fcounters[i]); 571126353Smlaier if (runtime > 0) 572126353Smlaier printf("%14.1f/s\n", 573126353Smlaier (double)s->fcounters[i] / (double)runtime); 574126353Smlaier else 575126353Smlaier printf("%14s\n", ""); 576126353Smlaier } 577130617Smlaier if (opts & PF_OPT_VERBOSE) { 578130617Smlaier printf("Source Tracking Table\n"); 579130617Smlaier printf(" %-25s %14u %14s\n", "current entries", 580130617Smlaier s->src_nodes, ""); 581130617Smlaier for (i = 0; i < SCNT_MAX; i++) { 582130617Smlaier printf(" %-25s %14lld ", pf_scounters[i], 583223637Sbz#ifdef __FreeBSD__ 584223637Sbz (long long)s->scounters[i]); 585223637Sbz#else 586223637Sbz s->scounters[i]); 587223637Sbz#endif 588130617Smlaier if (runtime > 0) 589130617Smlaier printf("%14.1f/s\n", 590130617Smlaier (double)s->scounters[i] / (double)runtime); 591130617Smlaier else 592130617Smlaier printf("%14s\n", ""); 593130617Smlaier } 594130617Smlaier } 595126353Smlaier printf("Counters\n"); 596126353Smlaier for (i = 0; i < PFRES_MAX; i++) { 597127024Smlaier printf(" %-25s %14llu ", pf_reasons[i], 598127024Smlaier (unsigned long long)s->counters[i]); 599126353Smlaier if (runtime > 0) 600126353Smlaier printf("%14.1f/s\n", 601126353Smlaier (double)s->counters[i] / (double)runtime); 602126353Smlaier else 603126353Smlaier printf("%14s\n", ""); 604126353Smlaier } 605145840Smlaier if (opts & PF_OPT_VERBOSE) { 606145840Smlaier printf("Limit Counters\n"); 607145840Smlaier for (i = 0; i < LCNT_MAX; i++) { 608145840Smlaier printf(" %-25s %14lld ", pf_lcounters[i], 609145840Smlaier#ifdef __FreeBSD__ 610145840Smlaier (unsigned long long)s->lcounters[i]); 611145840Smlaier#else 612145840Smlaier s->lcounters[i]); 613145840Smlaier#endif 614145840Smlaier if (runtime > 0) 615145840Smlaier printf("%14.1f/s\n", 616145840Smlaier (double)s->lcounters[i] / (double)runtime); 617145840Smlaier else 618145840Smlaier printf("%14s\n", ""); 619145840Smlaier } 620145840Smlaier } 621126353Smlaier} 622126353Smlaier 623126353Smlaiervoid 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); 852171172Smlaier if (!r->keep_state && r->action == PF_PASS && !anchor_call[0]) 853171172Smlaier printf(" no state"); 854171172Smlaier else if (r->keep_state == PF_STATE_NORMAL) 855126353Smlaier printf(" keep state"); 856126353Smlaier else if (r->keep_state == PF_STATE_MODULATE) 857126353Smlaier printf(" modulate state"); 858126353Smlaier else if (r->keep_state == PF_STATE_SYNPROXY) 859126353Smlaier printf(" synproxy state"); 860145840Smlaier if (r->prob) { 861145840Smlaier char buf[20]; 862145840Smlaier 863145840Smlaier snprintf(buf, sizeof(buf), "%f", r->prob*100.0/(UINT_MAX+1.0)); 864145840Smlaier for (i = strlen(buf)-1; i > 0; i--) { 865145840Smlaier if (buf[i] == '0') 866145840Smlaier buf[i] = '\0'; 867145840Smlaier else { 868145840Smlaier if (buf[i] == '.') 869145840Smlaier buf[i] = '\0'; 870145840Smlaier break; 871145840Smlaier } 872145840Smlaier } 873145840Smlaier printf(" probability %s%%", buf); 874145840Smlaier } 875126353Smlaier opts = 0; 876130617Smlaier if (r->max_states || r->max_src_nodes || r->max_src_states) 877126353Smlaier opts = 1; 878130617Smlaier if (r->rule_flag & PFRULE_NOSYNC) 879130617Smlaier opts = 1; 880130617Smlaier if (r->rule_flag & PFRULE_SRCTRACK) 881130617Smlaier opts = 1; 882171172Smlaier if (r->rule_flag & PFRULE_IFBOUND) 883130617Smlaier opts = 1; 884200930Sdelphij if (r->rule_flag & PFRULE_STATESLOPPY) 885200930Sdelphij opts = 1; 886126353Smlaier for (i = 0; !opts && i < PFTM_MAX; ++i) 887126353Smlaier if (r->timeout[i]) 888126353Smlaier opts = 1; 889126353Smlaier if (opts) { 890126353Smlaier printf(" ("); 891126353Smlaier if (r->max_states) { 892126353Smlaier printf("max %u", r->max_states); 893126353Smlaier opts = 0; 894126353Smlaier } 895130617Smlaier if (r->rule_flag & PFRULE_NOSYNC) { 896130617Smlaier if (!opts) 897130617Smlaier printf(", "); 898130617Smlaier printf("no-sync"); 899130617Smlaier opts = 0; 900130617Smlaier } 901130617Smlaier if (r->rule_flag & PFRULE_SRCTRACK) { 902130617Smlaier if (!opts) 903130617Smlaier printf(", "); 904130617Smlaier printf("source-track"); 905130617Smlaier if (r->rule_flag & PFRULE_RULESRCTRACK) 906130617Smlaier printf(" rule"); 907130617Smlaier else 908130617Smlaier printf(" global"); 909130617Smlaier opts = 0; 910130617Smlaier } 911130617Smlaier if (r->max_src_states) { 912130617Smlaier if (!opts) 913130617Smlaier printf(", "); 914130617Smlaier printf("max-src-states %u", r->max_src_states); 915130617Smlaier opts = 0; 916130617Smlaier } 917145840Smlaier if (r->max_src_conn) { 918145840Smlaier if (!opts) 919145840Smlaier printf(", "); 920145840Smlaier printf("max-src-conn %u", r->max_src_conn); 921145840Smlaier opts = 0; 922145840Smlaier } 923145840Smlaier if (r->max_src_conn_rate.limit) { 924145840Smlaier if (!opts) 925145840Smlaier printf(", "); 926145840Smlaier printf("max-src-conn-rate %u/%u", 927145840Smlaier r->max_src_conn_rate.limit, 928145840Smlaier r->max_src_conn_rate.seconds); 929145840Smlaier opts = 0; 930145840Smlaier } 931130617Smlaier if (r->max_src_nodes) { 932130617Smlaier if (!opts) 933130617Smlaier printf(", "); 934130617Smlaier printf("max-src-nodes %u", r->max_src_nodes); 935130617Smlaier opts = 0; 936130617Smlaier } 937145840Smlaier if (r->overload_tblname[0]) { 938145840Smlaier if (!opts) 939145840Smlaier printf(", "); 940145840Smlaier printf("overload <%s>", r->overload_tblname); 941145840Smlaier if (r->flush) 942145840Smlaier printf(" flush"); 943145840Smlaier if (r->flush & PF_FLUSH_GLOBAL) 944145840Smlaier printf(" global"); 945145840Smlaier } 946130617Smlaier if (r->rule_flag & PFRULE_IFBOUND) { 947130617Smlaier if (!opts) 948130617Smlaier printf(", "); 949130617Smlaier printf("if-bound"); 950130617Smlaier opts = 0; 951130617Smlaier } 952200930Sdelphij if (r->rule_flag & PFRULE_STATESLOPPY) { 953200930Sdelphij if (!opts) 954200930Sdelphij printf(", "); 955200930Sdelphij printf("sloppy"); 956200930Sdelphij opts = 0; 957200930Sdelphij } 958126353Smlaier for (i = 0; i < PFTM_MAX; ++i) 959126353Smlaier if (r->timeout[i]) { 960145840Smlaier int j; 961145840Smlaier 962126353Smlaier if (!opts) 963126353Smlaier printf(", "); 964126353Smlaier opts = 0; 965171172Smlaier for (j = 0; pf_timeouts[j].name != NULL; 966171172Smlaier ++j) 967145840Smlaier if (pf_timeouts[j].timeout == i) 968145840Smlaier break; 969171172Smlaier printf("%s %u", pf_timeouts[j].name == NULL ? 970171172Smlaier "inv.timeout" : pf_timeouts[j].name, 971171172Smlaier r->timeout[i]); 972126353Smlaier } 973126353Smlaier printf(")"); 974126353Smlaier } 975126353Smlaier if (r->rule_flag & PFRULE_FRAGMENT) 976126353Smlaier printf(" fragment"); 977126353Smlaier if (r->rule_flag & PFRULE_NODF) 978126353Smlaier printf(" no-df"); 979126353Smlaier if (r->rule_flag & PFRULE_RANDOMID) 980126353Smlaier printf(" random-id"); 981126353Smlaier if (r->min_ttl) 982126353Smlaier printf(" min-ttl %d", r->min_ttl); 983126353Smlaier if (r->max_mss) 984126353Smlaier printf(" max-mss %d", r->max_mss); 985223637Sbz if (r->rule_flag & PFRULE_SET_TOS) 986223637Sbz printf(" set-tos 0x%2.2x", r->set_tos); 987126353Smlaier if (r->allow_opts) 988126353Smlaier printf(" allow-opts"); 989126353Smlaier if (r->action == PF_SCRUB) { 990126353Smlaier if (r->rule_flag & PFRULE_REASSEMBLE_TCP) 991126353Smlaier printf(" reassemble tcp"); 992126353Smlaier 993126353Smlaier if (r->rule_flag & PFRULE_FRAGDROP) 994126353Smlaier printf(" fragment drop-ovl"); 995126353Smlaier else if (r->rule_flag & PFRULE_FRAGCROP) 996126353Smlaier printf(" fragment crop"); 997126353Smlaier else 998126353Smlaier printf(" fragment reassemble"); 999126353Smlaier } 1000126353Smlaier if (r->label[0]) 1001126353Smlaier printf(" label \"%s\"", r->label); 1002126353Smlaier if (r->qname[0] && r->pqname[0]) 1003126353Smlaier printf(" queue(%s, %s)", r->qname, r->pqname); 1004126353Smlaier else if (r->qname[0]) 1005126353Smlaier printf(" queue %s", r->qname); 1006126353Smlaier if (r->tagname[0]) 1007126353Smlaier printf(" tag %s", r->tagname); 1008126353Smlaier if (r->match_tagname[0]) { 1009126353Smlaier if (r->match_tag_not) 1010126353Smlaier printf(" !"); 1011126353Smlaier printf(" tagged %s", r->match_tagname); 1012126353Smlaier } 1013171172Smlaier if (r->rtableid != -1) 1014171172Smlaier printf(" rtable %u", r->rtableid); 1015223637Sbz if (r->divert.port) { 1016223637Sbz#ifdef __FreeBSD__ 1017223637Sbz printf(" divert-to %u", ntohs(r->divert.port)); 1018223637Sbz#else 1019223637Sbz if (PF_AZERO(&r->divert.addr, r->af)) { 1020223637Sbz printf(" divert-reply"); 1021223637Sbz } else { 1022223637Sbz /* XXX cut&paste from print_addr */ 1023223637Sbz char buf[48]; 1024223637Sbz 1025223637Sbz printf(" divert-to "); 1026223637Sbz if (inet_ntop(r->af, &r->divert.addr, buf, 1027223637Sbz sizeof(buf)) == NULL) 1028223637Sbz printf("?"); 1029223637Sbz else 1030223637Sbz printf("%s", buf); 1031223637Sbz printf(" port %u", ntohs(r->divert.port)); 1032223637Sbz } 1033223637Sbz#endif 1034223637Sbz } 1035145840Smlaier if (!anchor_call[0] && (r->action == PF_NAT || 1036126353Smlaier r->action == PF_BINAT || r->action == PF_RDR)) { 1037126353Smlaier printf(" -> "); 1038126353Smlaier print_pool(&r->rpool, r->rpool.proxy_port[0], 1039126353Smlaier r->rpool.proxy_port[1], r->af, r->action); 1040126353Smlaier } 1041126353Smlaier} 1042126353Smlaier 1043126353Smlaiervoid 1044126353Smlaierprint_tabledef(const char *name, int flags, int addrs, 1045126353Smlaier struct node_tinithead *nodes) 1046126353Smlaier{ 1047126353Smlaier struct node_tinit *ti, *nti; 1048126353Smlaier struct node_host *h; 1049126353Smlaier 1050126353Smlaier printf("table <%s>", name); 1051126353Smlaier if (flags & PFR_TFLAG_CONST) 1052126353Smlaier printf(" const"); 1053126353Smlaier if (flags & PFR_TFLAG_PERSIST) 1054126353Smlaier printf(" persist"); 1055223637Sbz if (flags & PFR_TFLAG_COUNTERS) 1056223637Sbz printf(" counters"); 1057126353Smlaier SIMPLEQ_FOREACH(ti, nodes, entries) { 1058126353Smlaier if (ti->file) { 1059126353Smlaier printf(" file \"%s\"", ti->file); 1060126353Smlaier continue; 1061126353Smlaier } 1062126353Smlaier printf(" {"); 1063126353Smlaier for (;;) { 1064126353Smlaier for (h = ti->host; h != NULL; h = h->next) { 1065126353Smlaier printf(h->not ? " !" : " "); 1066126353Smlaier print_addr(&h->addr, h->af, 0); 1067126353Smlaier } 1068126353Smlaier nti = SIMPLEQ_NEXT(ti, entries); 1069126353Smlaier if (nti != NULL && nti->file == NULL) 1070126353Smlaier ti = nti; /* merge lists */ 1071126353Smlaier else 1072126353Smlaier break; 1073126353Smlaier } 1074126353Smlaier printf(" }"); 1075126353Smlaier } 1076126353Smlaier if (addrs && SIMPLEQ_EMPTY(nodes)) 1077126353Smlaier printf(" { }"); 1078126353Smlaier printf("\n"); 1079126353Smlaier} 1080126353Smlaier 1081126353Smlaierint 1082126353Smlaierparse_flags(char *s) 1083126353Smlaier{ 1084126353Smlaier char *p, *q; 1085126353Smlaier u_int8_t f = 0; 1086126353Smlaier 1087126353Smlaier for (p = s; *p; p++) { 1088126353Smlaier if ((q = strchr(tcpflags, *p)) == NULL) 1089126353Smlaier return -1; 1090126353Smlaier else 1091126353Smlaier f |= 1 << (q - tcpflags); 1092126353Smlaier } 1093126353Smlaier return (f ? f : PF_TH_ALL); 1094126353Smlaier} 1095126353Smlaier 1096126353Smlaiervoid 1097126353Smlaierset_ipmask(struct node_host *h, u_int8_t b) 1098126353Smlaier{ 1099126353Smlaier struct pf_addr *m, *n; 1100126353Smlaier int i, j = 0; 1101126353Smlaier 1102126353Smlaier m = &h->addr.v.a.mask; 1103145840Smlaier memset(m, 0, sizeof(*m)); 1104126353Smlaier 1105126353Smlaier while (b >= 32) { 1106126353Smlaier m->addr32[j++] = 0xffffffff; 1107126353Smlaier b -= 32; 1108126353Smlaier } 1109126353Smlaier for (i = 31; i > 31-b; --i) 1110126353Smlaier m->addr32[j] |= (1 << i); 1111126353Smlaier if (b) 1112126353Smlaier m->addr32[j] = htonl(m->addr32[j]); 1113126353Smlaier 1114126353Smlaier /* Mask off bits of the address that will never be used. */ 1115126353Smlaier n = &h->addr.v.a.addr; 1116126353Smlaier if (h->addr.type == PF_ADDR_ADDRMASK) 1117126353Smlaier for (i = 0; i < 4; i++) 1118126353Smlaier n->addr32[i] = n->addr32[i] & m->addr32[i]; 1119126353Smlaier} 1120126353Smlaier 1121126353Smlaierint 1122126353Smlaiercheck_netmask(struct node_host *h, sa_family_t af) 1123126353Smlaier{ 1124126353Smlaier struct node_host *n = NULL; 1125126353Smlaier struct pf_addr *m; 1126126353Smlaier 1127126353Smlaier for (n = h; n != NULL; n = n->next) { 1128126353Smlaier if (h->addr.type == PF_ADDR_TABLE) 1129126353Smlaier continue; 1130126353Smlaier m = &h->addr.v.a.mask; 1131126353Smlaier /* fix up netmask for dynaddr */ 1132126353Smlaier if (af == AF_INET && h->addr.type == PF_ADDR_DYNIFTL && 1133126353Smlaier unmask(m, AF_INET6) > 32) 1134126353Smlaier set_ipmask(n, 32); 1135126353Smlaier /* netmasks > 32 bit are invalid on v4 */ 1136126353Smlaier if (af == AF_INET && 1137126353Smlaier (m->addr32[1] || m->addr32[2] || m->addr32[3])) { 1138126353Smlaier fprintf(stderr, "netmask %u invalid for IPv4 address\n", 1139126353Smlaier unmask(m, AF_INET6)); 1140126353Smlaier return (1); 1141126353Smlaier } 1142126353Smlaier } 1143126353Smlaier return (0); 1144126353Smlaier} 1145126353Smlaier 1146126353Smlaier/* interface lookup routines */ 1147126353Smlaier 1148126353Smlaierstruct node_host *iftab; 1149126353Smlaier 1150126353Smlaiervoid 1151126353Smlaierifa_load(void) 1152126353Smlaier{ 1153126353Smlaier struct ifaddrs *ifap, *ifa; 1154126353Smlaier struct node_host *n = NULL, *h = NULL; 1155126353Smlaier 1156126353Smlaier if (getifaddrs(&ifap) < 0) 1157126353Smlaier err(1, "getifaddrs"); 1158126353Smlaier 1159126353Smlaier for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 1160126353Smlaier if (!(ifa->ifa_addr->sa_family == AF_INET || 1161126353Smlaier ifa->ifa_addr->sa_family == AF_INET6 || 1162126353Smlaier ifa->ifa_addr->sa_family == AF_LINK)) 1163126353Smlaier continue; 1164126353Smlaier n = calloc(1, sizeof(struct node_host)); 1165126353Smlaier if (n == NULL) 1166126353Smlaier err(1, "address: calloc"); 1167126353Smlaier n->af = ifa->ifa_addr->sa_family; 1168126353Smlaier n->ifa_flags = ifa->ifa_flags; 1169126353Smlaier#ifdef __KAME__ 1170126353Smlaier if (n->af == AF_INET6 && 1171126353Smlaier IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) 1172126353Smlaier ifa->ifa_addr)->sin6_addr) && 1173130617Smlaier ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 1174130617Smlaier 0) { 1175126353Smlaier struct sockaddr_in6 *sin6; 1176126353Smlaier 1177126353Smlaier sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 1178126353Smlaier sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 | 1179126353Smlaier sin6->sin6_addr.s6_addr[3]; 1180126353Smlaier sin6->sin6_addr.s6_addr[2] = 0; 1181126353Smlaier sin6->sin6_addr.s6_addr[3] = 0; 1182126353Smlaier } 1183126353Smlaier#endif 1184126353Smlaier n->ifindex = 0; 1185126353Smlaier if (n->af == AF_INET) { 1186126353Smlaier memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *) 1187126353Smlaier ifa->ifa_addr)->sin_addr.s_addr, 1188126353Smlaier sizeof(struct in_addr)); 1189126353Smlaier memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *) 1190126353Smlaier ifa->ifa_netmask)->sin_addr.s_addr, 1191126353Smlaier sizeof(struct in_addr)); 1192126353Smlaier if (ifa->ifa_broadaddr != NULL) 1193126353Smlaier memcpy(&n->bcast, &((struct sockaddr_in *) 1194126353Smlaier ifa->ifa_broadaddr)->sin_addr.s_addr, 1195126353Smlaier sizeof(struct in_addr)); 1196130617Smlaier if (ifa->ifa_dstaddr != NULL) 1197130617Smlaier memcpy(&n->peer, &((struct sockaddr_in *) 1198130617Smlaier ifa->ifa_dstaddr)->sin_addr.s_addr, 1199130617Smlaier sizeof(struct in_addr)); 1200126353Smlaier } else if (n->af == AF_INET6) { 1201126353Smlaier memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *) 1202126353Smlaier ifa->ifa_addr)->sin6_addr.s6_addr, 1203126353Smlaier sizeof(struct in6_addr)); 1204126353Smlaier memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *) 1205126353Smlaier ifa->ifa_netmask)->sin6_addr.s6_addr, 1206126353Smlaier sizeof(struct in6_addr)); 1207126353Smlaier if (ifa->ifa_broadaddr != NULL) 1208126353Smlaier memcpy(&n->bcast, &((struct sockaddr_in6 *) 1209126353Smlaier ifa->ifa_broadaddr)->sin6_addr.s6_addr, 1210126353Smlaier sizeof(struct in6_addr)); 1211130617Smlaier if (ifa->ifa_dstaddr != NULL) 1212130617Smlaier memcpy(&n->peer, &((struct sockaddr_in6 *) 1213130617Smlaier ifa->ifa_dstaddr)->sin6_addr.s6_addr, 1214130617Smlaier sizeof(struct in6_addr)); 1215126353Smlaier n->ifindex = ((struct sockaddr_in6 *) 1216126353Smlaier ifa->ifa_addr)->sin6_scope_id; 1217126353Smlaier } 1218126353Smlaier if ((n->ifname = strdup(ifa->ifa_name)) == NULL) 1219126353Smlaier err(1, "ifa_load: strdup"); 1220126353Smlaier n->next = NULL; 1221126353Smlaier n->tail = n; 1222126353Smlaier if (h == NULL) 1223126353Smlaier h = n; 1224126353Smlaier else { 1225126353Smlaier h->tail->next = n; 1226126353Smlaier h->tail = n; 1227126353Smlaier } 1228126353Smlaier } 1229130617Smlaier 1230126353Smlaier iftab = h; 1231126353Smlaier freeifaddrs(ifap); 1232126353Smlaier} 1233126353Smlaier 1234270047Sbzint 1235270047Sbzget_socket_domain(void) 1236270047Sbz{ 1237270047Sbz int sdom; 1238270047Sbz 1239270047Sbz sdom = AF_UNSPEC; 1240270047Sbz#ifdef WITH_INET6 1241270047Sbz if (sdom == AF_UNSPEC && feature_present("inet6")) 1242270047Sbz sdom = AF_INET6; 1243270047Sbz#endif 1244270047Sbz#ifdef WITH_INET 1245270047Sbz if (sdom == AF_UNSPEC && feature_present("inet")) 1246270047Sbz sdom = AF_INET; 1247270047Sbz#endif 1248270047Sbz if (sdom == AF_UNSPEC) 1249270047Sbz sdom = AF_LINK; 1250270047Sbz 1251270047Sbz return (sdom); 1252270047Sbz} 1253270047Sbz 1254126353Smlaierstruct node_host * 1255171172Smlaierifa_exists(const char *ifa_name) 1256126353Smlaier{ 1257126353Smlaier struct node_host *n; 1258171172Smlaier struct ifgroupreq ifgr; 1259171172Smlaier int s; 1260126353Smlaier 1261126353Smlaier if (iftab == NULL) 1262126353Smlaier ifa_load(); 1263126353Smlaier 1264171172Smlaier /* check wether this is a group */ 1265270047Sbz if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) 1266171172Smlaier err(1, "socket"); 1267171172Smlaier bzero(&ifgr, sizeof(ifgr)); 1268171172Smlaier strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); 1269171172Smlaier if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == 0) { 1270171172Smlaier /* fake a node_host */ 1271171172Smlaier if ((n = calloc(1, sizeof(*n))) == NULL) 1272171172Smlaier err(1, "calloc"); 1273171172Smlaier if ((n->ifname = strdup(ifa_name)) == NULL) 1274171172Smlaier err(1, "strdup"); 1275171172Smlaier close(s); 1276171172Smlaier return (n); 1277171172Smlaier } 1278171172Smlaier close(s); 1279171172Smlaier 1280126353Smlaier for (n = iftab; n; n = n->next) { 1281126353Smlaier if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ)) 1282126353Smlaier return (n); 1283126353Smlaier } 1284145840Smlaier 1285126353Smlaier return (NULL); 1286126353Smlaier} 1287126353Smlaier 1288126353Smlaierstruct node_host * 1289171172Smlaierifa_grouplookup(const char *ifa_name, int flags) 1290171172Smlaier{ 1291171172Smlaier struct ifg_req *ifg; 1292171172Smlaier struct ifgroupreq ifgr; 1293171172Smlaier int s, len; 1294171172Smlaier struct node_host *n, *h = NULL; 1295171172Smlaier 1296270047Sbz if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1) 1297171172Smlaier err(1, "socket"); 1298171172Smlaier bzero(&ifgr, sizeof(ifgr)); 1299171172Smlaier strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name)); 1300171172Smlaier if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) { 1301171172Smlaier close(s); 1302171172Smlaier return (NULL); 1303171172Smlaier } 1304171172Smlaier 1305171172Smlaier len = ifgr.ifgr_len; 1306171172Smlaier if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 1307171172Smlaier err(1, "calloc"); 1308171172Smlaier if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 1309171172Smlaier err(1, "SIOCGIFGMEMB"); 1310171172Smlaier 1311171172Smlaier for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req); 1312171172Smlaier ifg++) { 1313171172Smlaier len -= sizeof(struct ifg_req); 1314171172Smlaier if ((n = ifa_lookup(ifg->ifgrq_member, flags)) == NULL) 1315171172Smlaier continue; 1316171172Smlaier if (h == NULL) 1317171172Smlaier h = n; 1318171172Smlaier else { 1319171172Smlaier h->tail->next = n; 1320171172Smlaier h->tail = n->tail; 1321171172Smlaier } 1322171172Smlaier } 1323171172Smlaier free(ifgr.ifgr_groups); 1324171172Smlaier close(s); 1325171172Smlaier 1326171172Smlaier return (h); 1327171172Smlaier} 1328171172Smlaier 1329171172Smlaierstruct node_host * 1330130617Smlaierifa_lookup(const char *ifa_name, int flags) 1331126353Smlaier{ 1332126353Smlaier struct node_host *p = NULL, *h = NULL, *n = NULL; 1333145840Smlaier int got4 = 0, got6 = 0; 1334130617Smlaier const char *last_if = NULL; 1335126353Smlaier 1336171172Smlaier if ((h = ifa_grouplookup(ifa_name, flags)) != NULL) 1337171172Smlaier return (h); 1338171172Smlaier 1339126353Smlaier if (!strncmp(ifa_name, "self", IFNAMSIZ)) 1340145840Smlaier ifa_name = NULL; 1341126353Smlaier 1342126353Smlaier if (iftab == NULL) 1343126353Smlaier ifa_load(); 1344126353Smlaier 1345126353Smlaier for (p = iftab; p; p = p->next) { 1346145840Smlaier if (ifa_skip_if(ifa_name, p)) 1347126353Smlaier continue; 1348130617Smlaier if ((flags & PFI_AFLAG_BROADCAST) && p->af != AF_INET) 1349126353Smlaier continue; 1350130617Smlaier if ((flags & PFI_AFLAG_BROADCAST) && 1351130617Smlaier !(p->ifa_flags & IFF_BROADCAST)) 1352126353Smlaier continue; 1353130617Smlaier if ((flags & PFI_AFLAG_PEER) && 1354130617Smlaier !(p->ifa_flags & IFF_POINTOPOINT)) 1355130617Smlaier continue; 1356130617Smlaier if ((flags & PFI_AFLAG_NETWORK) && p->ifindex > 0) 1357130617Smlaier continue; 1358130617Smlaier if (last_if == NULL || strcmp(last_if, p->ifname)) 1359130617Smlaier got4 = got6 = 0; 1360130617Smlaier last_if = p->ifname; 1361130617Smlaier if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET && got4) 1362130617Smlaier continue; 1363130617Smlaier if ((flags & PFI_AFLAG_NOALIAS) && p->af == AF_INET6 && got6) 1364130617Smlaier continue; 1365130617Smlaier if (p->af == AF_INET) 1366130617Smlaier got4 = 1; 1367130617Smlaier else 1368130617Smlaier got6 = 1; 1369126353Smlaier n = calloc(1, sizeof(struct node_host)); 1370126353Smlaier if (n == NULL) 1371126353Smlaier err(1, "address: calloc"); 1372126353Smlaier n->af = p->af; 1373130617Smlaier if (flags & PFI_AFLAG_BROADCAST) 1374126353Smlaier memcpy(&n->addr.v.a.addr, &p->bcast, 1375126353Smlaier sizeof(struct pf_addr)); 1376130617Smlaier else if (flags & PFI_AFLAG_PEER) 1377130617Smlaier memcpy(&n->addr.v.a.addr, &p->peer, 1378130617Smlaier sizeof(struct pf_addr)); 1379126353Smlaier else 1380126353Smlaier memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr, 1381126353Smlaier sizeof(struct pf_addr)); 1382130617Smlaier if (flags & PFI_AFLAG_NETWORK) 1383126353Smlaier set_ipmask(n, unmask(&p->addr.v.a.mask, n->af)); 1384126353Smlaier else { 1385126353Smlaier if (n->af == AF_INET) { 1386126353Smlaier if (p->ifa_flags & IFF_LOOPBACK && 1387126353Smlaier p->ifa_flags & IFF_LINK1) 1388126353Smlaier memcpy(&n->addr.v.a.mask, 1389126353Smlaier &p->addr.v.a.mask, 1390126353Smlaier sizeof(struct pf_addr)); 1391126353Smlaier else 1392126353Smlaier set_ipmask(n, 32); 1393126353Smlaier } else 1394126353Smlaier set_ipmask(n, 128); 1395126353Smlaier } 1396126353Smlaier n->ifindex = p->ifindex; 1397126353Smlaier 1398126353Smlaier n->next = NULL; 1399126353Smlaier n->tail = n; 1400126353Smlaier if (h == NULL) 1401126353Smlaier h = n; 1402126353Smlaier else { 1403126353Smlaier h->tail->next = n; 1404126353Smlaier h->tail = n; 1405126353Smlaier } 1406126353Smlaier } 1407126353Smlaier return (h); 1408126353Smlaier} 1409126353Smlaier 1410145840Smlaierint 1411145840Smlaierifa_skip_if(const char *filter, struct node_host *p) 1412145840Smlaier{ 1413145840Smlaier int n; 1414145840Smlaier 1415145840Smlaier if (p->af != AF_INET && p->af != AF_INET6) 1416145840Smlaier return (1); 1417145840Smlaier if (filter == NULL || !*filter) 1418145840Smlaier return (0); 1419145840Smlaier if (!strcmp(p->ifname, filter)) 1420145840Smlaier return (0); /* exact match */ 1421145840Smlaier n = strlen(filter); 1422145840Smlaier if (n < 1 || n >= IFNAMSIZ) 1423145840Smlaier return (1); /* sanity check */ 1424145840Smlaier if (filter[n-1] >= '0' && filter[n-1] <= '9') 1425145840Smlaier return (1); /* only do exact match in that case */ 1426145840Smlaier if (strncmp(p->ifname, filter, n)) 1427145840Smlaier return (1); /* prefix doesn't match */ 1428145840Smlaier return (p->ifname[n] < '0' || p->ifname[n] > '9'); 1429145840Smlaier} 1430145840Smlaier 1431145840Smlaier 1432126353Smlaierstruct node_host * 1433126353Smlaierhost(const char *s) 1434126353Smlaier{ 1435126353Smlaier struct node_host *h = NULL; 1436126353Smlaier int mask, v4mask, v6mask, cont = 1; 1437126353Smlaier char *p, *q, *ps; 1438126353Smlaier 1439126353Smlaier if ((p = strrchr(s, '/')) != NULL) { 1440126353Smlaier mask = strtol(p+1, &q, 0); 1441126353Smlaier if (!q || *q || mask > 128 || q == (p+1)) { 1442145840Smlaier fprintf(stderr, "invalid netmask '%s'\n", p); 1443126353Smlaier return (NULL); 1444126353Smlaier } 1445126353Smlaier if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 1446126353Smlaier err(1, "host: malloc"); 1447126353Smlaier strlcpy(ps, s, strlen(s) - strlen(p) + 1); 1448126353Smlaier v4mask = v6mask = mask; 1449126353Smlaier } else { 1450126353Smlaier if ((ps = strdup(s)) == NULL) 1451126353Smlaier err(1, "host: strdup"); 1452126353Smlaier v4mask = 32; 1453126353Smlaier v6mask = 128; 1454126353Smlaier mask = -1; 1455126353Smlaier } 1456126353Smlaier 1457126353Smlaier /* interface with this name exists? */ 1458126353Smlaier if (cont && (h = host_if(ps, mask)) != NULL) 1459126353Smlaier cont = 0; 1460126353Smlaier 1461126353Smlaier /* IPv4 address? */ 1462126353Smlaier if (cont && (h = host_v4(s, mask)) != NULL) 1463126353Smlaier cont = 0; 1464126353Smlaier 1465126353Smlaier /* IPv6 address? */ 1466126353Smlaier if (cont && (h = host_v6(ps, v6mask)) != NULL) 1467126353Smlaier cont = 0; 1468126353Smlaier 1469126353Smlaier /* dns lookup */ 1470126353Smlaier if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL) 1471126353Smlaier cont = 0; 1472126353Smlaier free(ps); 1473126353Smlaier 1474126353Smlaier if (h == NULL || cont == 1) { 1475126353Smlaier fprintf(stderr, "no IP address found for %s\n", s); 1476126353Smlaier return (NULL); 1477126353Smlaier } 1478126353Smlaier return (h); 1479126353Smlaier} 1480126353Smlaier 1481126353Smlaierstruct node_host * 1482126353Smlaierhost_if(const char *s, int mask) 1483126353Smlaier{ 1484126353Smlaier struct node_host *n, *h = NULL; 1485126353Smlaier char *p, *ps; 1486130617Smlaier int flags = 0; 1487126353Smlaier 1488130617Smlaier if ((ps = strdup(s)) == NULL) 1489130617Smlaier err(1, "host_if: strdup"); 1490130617Smlaier while ((p = strrchr(ps, ':')) != NULL) { 1491126353Smlaier if (!strcmp(p+1, "network")) 1492130617Smlaier flags |= PFI_AFLAG_NETWORK; 1493130617Smlaier else if (!strcmp(p+1, "broadcast")) 1494130617Smlaier flags |= PFI_AFLAG_BROADCAST; 1495130617Smlaier else if (!strcmp(p+1, "peer")) 1496130617Smlaier flags |= PFI_AFLAG_PEER; 1497130617Smlaier else if (!strcmp(p+1, "0")) 1498130617Smlaier flags |= PFI_AFLAG_NOALIAS; 1499130617Smlaier else { 1500130617Smlaier free(ps); 1501126353Smlaier return (NULL); 1502126353Smlaier } 1503130617Smlaier *p = '\0'; 1504130617Smlaier } 1505130617Smlaier if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */ 1506130617Smlaier fprintf(stderr, "illegal combination of interface modifiers\n"); 1507130617Smlaier free(ps); 1508130617Smlaier return (NULL); 1509130617Smlaier } 1510130617Smlaier if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) { 1511130617Smlaier fprintf(stderr, "network or broadcast lookup, but " 1512130617Smlaier "extra netmask given\n"); 1513130617Smlaier free(ps); 1514130617Smlaier return (NULL); 1515130617Smlaier } 1516171172Smlaier if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) { 1517126353Smlaier /* interface with this name exists */ 1518130617Smlaier h = ifa_lookup(ps, flags); 1519126353Smlaier for (n = h; n != NULL && mask > -1; n = n->next) 1520126353Smlaier set_ipmask(n, mask); 1521126353Smlaier } 1522126353Smlaier 1523126353Smlaier free(ps); 1524126353Smlaier return (h); 1525126353Smlaier} 1526126353Smlaier 1527126353Smlaierstruct node_host * 1528126353Smlaierhost_v4(const char *s, int mask) 1529126353Smlaier{ 1530126353Smlaier struct node_host *h = NULL; 1531126353Smlaier struct in_addr ina; 1532130617Smlaier int bits = 32; 1533126353Smlaier 1534126353Smlaier memset(&ina, 0, sizeof(struct in_addr)); 1535130617Smlaier if (strrchr(s, '/') != NULL) { 1536130617Smlaier if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 1537130617Smlaier return (NULL); 1538130617Smlaier } else { 1539130617Smlaier if (inet_pton(AF_INET, s, &ina) != 1) 1540130617Smlaier return (NULL); 1541126353Smlaier } 1542126353Smlaier 1543130617Smlaier h = calloc(1, sizeof(struct node_host)); 1544130617Smlaier if (h == NULL) 1545130617Smlaier err(1, "address: calloc"); 1546130617Smlaier h->ifname = NULL; 1547130617Smlaier h->af = AF_INET; 1548130617Smlaier h->addr.v.a.addr.addr32[0] = ina.s_addr; 1549130617Smlaier set_ipmask(h, bits); 1550130617Smlaier h->next = NULL; 1551130617Smlaier h->tail = h; 1552130617Smlaier 1553126353Smlaier return (h); 1554126353Smlaier} 1555126353Smlaier 1556126353Smlaierstruct node_host * 1557126353Smlaierhost_v6(const char *s, int mask) 1558126353Smlaier{ 1559126353Smlaier struct addrinfo hints, *res; 1560126353Smlaier struct node_host *h = NULL; 1561126353Smlaier 1562126353Smlaier memset(&hints, 0, sizeof(hints)); 1563126353Smlaier hints.ai_family = AF_INET6; 1564126353Smlaier hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 1565126353Smlaier hints.ai_flags = AI_NUMERICHOST; 1566126353Smlaier if (getaddrinfo(s, "0", &hints, &res) == 0) { 1567126353Smlaier h = calloc(1, sizeof(struct node_host)); 1568126353Smlaier if (h == NULL) 1569126353Smlaier err(1, "address: calloc"); 1570126353Smlaier h->ifname = NULL; 1571126353Smlaier h->af = AF_INET6; 1572126353Smlaier memcpy(&h->addr.v.a.addr, 1573126353Smlaier &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 1574126353Smlaier sizeof(h->addr.v.a.addr)); 1575126353Smlaier h->ifindex = 1576126353Smlaier ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 1577126353Smlaier set_ipmask(h, mask); 1578126353Smlaier freeaddrinfo(res); 1579126353Smlaier h->next = NULL; 1580126353Smlaier h->tail = h; 1581126353Smlaier } 1582126353Smlaier 1583126353Smlaier return (h); 1584126353Smlaier} 1585126353Smlaier 1586126353Smlaierstruct node_host * 1587126353Smlaierhost_dns(const char *s, int v4mask, int v6mask) 1588126353Smlaier{ 1589126353Smlaier struct addrinfo hints, *res0, *res; 1590126353Smlaier struct node_host *n, *h = NULL; 1591130617Smlaier int error, noalias = 0; 1592130617Smlaier int got4 = 0, got6 = 0; 1593130617Smlaier char *p, *ps; 1594126353Smlaier 1595130617Smlaier if ((ps = strdup(s)) == NULL) 1596145840Smlaier err(1, "host_dns: strdup"); 1597130617Smlaier if ((p = strrchr(ps, ':')) != NULL && !strcmp(p, ":0")) { 1598130617Smlaier noalias = 1; 1599130617Smlaier *p = '\0'; 1600130617Smlaier } 1601126353Smlaier memset(&hints, 0, sizeof(hints)); 1602126353Smlaier hints.ai_family = PF_UNSPEC; 1603126353Smlaier hints.ai_socktype = SOCK_STREAM; /* DUMMY */ 1604130617Smlaier error = getaddrinfo(ps, NULL, &hints, &res0); 1605145840Smlaier if (error) { 1606145840Smlaier free(ps); 1607126353Smlaier return (h); 1608145840Smlaier } 1609126353Smlaier 1610126353Smlaier for (res = res0; res; res = res->ai_next) { 1611126353Smlaier if (res->ai_family != AF_INET && 1612126353Smlaier res->ai_family != AF_INET6) 1613126353Smlaier continue; 1614130617Smlaier if (noalias) { 1615130617Smlaier if (res->ai_family == AF_INET) { 1616130617Smlaier if (got4) 1617130617Smlaier continue; 1618130617Smlaier got4 = 1; 1619130617Smlaier } else { 1620130617Smlaier if (got6) 1621130617Smlaier continue; 1622130617Smlaier got6 = 1; 1623130617Smlaier } 1624130617Smlaier } 1625126353Smlaier n = calloc(1, sizeof(struct node_host)); 1626126353Smlaier if (n == NULL) 1627126353Smlaier err(1, "host_dns: calloc"); 1628126353Smlaier n->ifname = NULL; 1629126353Smlaier n->af = res->ai_family; 1630126353Smlaier if (res->ai_family == AF_INET) { 1631126353Smlaier memcpy(&n->addr.v.a.addr, 1632126353Smlaier &((struct sockaddr_in *) 1633126353Smlaier res->ai_addr)->sin_addr.s_addr, 1634126353Smlaier sizeof(struct in_addr)); 1635126353Smlaier set_ipmask(n, v4mask); 1636126353Smlaier } else { 1637126353Smlaier memcpy(&n->addr.v.a.addr, 1638126353Smlaier &((struct sockaddr_in6 *) 1639126353Smlaier res->ai_addr)->sin6_addr.s6_addr, 1640126353Smlaier sizeof(struct in6_addr)); 1641126353Smlaier n->ifindex = 1642126353Smlaier ((struct sockaddr_in6 *) 1643126353Smlaier res->ai_addr)->sin6_scope_id; 1644126353Smlaier set_ipmask(n, v6mask); 1645126353Smlaier } 1646126353Smlaier n->next = NULL; 1647126353Smlaier n->tail = n; 1648126353Smlaier if (h == NULL) 1649126353Smlaier h = n; 1650126353Smlaier else { 1651126353Smlaier h->tail->next = n; 1652126353Smlaier h->tail = n; 1653126353Smlaier } 1654126353Smlaier } 1655126353Smlaier freeaddrinfo(res0); 1656130617Smlaier free(ps); 1657126353Smlaier 1658126353Smlaier return (h); 1659126353Smlaier} 1660126353Smlaier 1661126353Smlaier/* 1662126353Smlaier * convert a hostname to a list of addresses and put them in the given buffer. 1663126353Smlaier * test: 1664126353Smlaier * if set to 1, only simple addresses are accepted (no netblock, no "!"). 1665126353Smlaier */ 1666126353Smlaierint 1667126353Smlaierappend_addr(struct pfr_buffer *b, char *s, int test) 1668126353Smlaier{ 1669126353Smlaier char *r; 1670126353Smlaier struct node_host *h, *n; 1671126353Smlaier int rv, not = 0; 1672126353Smlaier 1673126353Smlaier for (r = s; *r == '!'; r++) 1674126353Smlaier not = !not; 1675126353Smlaier if ((n = host(r)) == NULL) { 1676126353Smlaier errno = 0; 1677126353Smlaier return (-1); 1678126353Smlaier } 1679126353Smlaier rv = append_addr_host(b, n, test, not); 1680126353Smlaier do { 1681126353Smlaier h = n; 1682126353Smlaier n = n->next; 1683126353Smlaier free(h); 1684126353Smlaier } while (n != NULL); 1685126353Smlaier return (rv); 1686126353Smlaier} 1687126353Smlaier 1688126353Smlaier/* 1689126353Smlaier * same as previous function, but with a pre-parsed input and the ability 1690126353Smlaier * to "negate" the result. Does not free the node_host list. 1691126353Smlaier * not: 1692126353Smlaier * setting it to 1 is equivalent to adding "!" in front of parameter s. 1693126353Smlaier */ 1694126353Smlaierint 1695126353Smlaierappend_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not) 1696126353Smlaier{ 1697126353Smlaier int bits; 1698126353Smlaier struct pfr_addr addr; 1699126353Smlaier 1700126353Smlaier do { 1701126353Smlaier bzero(&addr, sizeof(addr)); 1702126353Smlaier addr.pfra_not = n->not ^ not; 1703126353Smlaier addr.pfra_af = n->af; 1704126353Smlaier addr.pfra_net = unmask(&n->addr.v.a.mask, n->af); 1705126353Smlaier switch (n->af) { 1706126353Smlaier case AF_INET: 1707126353Smlaier addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0]; 1708126353Smlaier bits = 32; 1709126353Smlaier break; 1710126353Smlaier case AF_INET6: 1711126353Smlaier memcpy(&addr.pfra_ip6addr, &n->addr.v.a.addr.v6, 1712126353Smlaier sizeof(struct in6_addr)); 1713126353Smlaier bits = 128; 1714126353Smlaier break; 1715126353Smlaier default: 1716126353Smlaier errno = EINVAL; 1717126353Smlaier return (-1); 1718126353Smlaier } 1719126353Smlaier if ((test && (not || addr.pfra_net != bits)) || 1720126353Smlaier addr.pfra_net > bits) { 1721126353Smlaier errno = EINVAL; 1722126353Smlaier return (-1); 1723126353Smlaier } 1724126353Smlaier if (pfr_buf_add(b, &addr)) 1725126353Smlaier return (-1); 1726126353Smlaier } while ((n = n->next) != NULL); 1727126353Smlaier 1728126353Smlaier return (0); 1729126353Smlaier} 1730130617Smlaier 1731130617Smlaierint 1732145840Smlaierpfctl_add_trans(struct pfr_buffer *buf, int rs_num, const char *anchor) 1733130617Smlaier{ 1734130617Smlaier struct pfioc_trans_e trans; 1735130617Smlaier 1736130617Smlaier bzero(&trans, sizeof(trans)); 1737130617Smlaier trans.rs_num = rs_num; 1738130617Smlaier if (strlcpy(trans.anchor, anchor, 1739145840Smlaier sizeof(trans.anchor)) >= sizeof(trans.anchor)) 1740130617Smlaier errx(1, "pfctl_add_trans: strlcpy"); 1741130617Smlaier 1742130617Smlaier return pfr_buf_add(buf, &trans); 1743130617Smlaier} 1744130617Smlaier 1745130617Smlaieru_int32_t 1746145840Smlaierpfctl_get_ticket(struct pfr_buffer *buf, int rs_num, const char *anchor) 1747130617Smlaier{ 1748130617Smlaier struct pfioc_trans_e *p; 1749130617Smlaier 1750130617Smlaier PFRB_FOREACH(p, buf) 1751145840Smlaier if (rs_num == p->rs_num && !strcmp(anchor, p->anchor)) 1752130617Smlaier return (p->ticket); 1753145840Smlaier errx(1, "pfctl_get_ticket: assertion failed"); 1754130617Smlaier} 1755130617Smlaier 1756130617Smlaierint 1757130617Smlaierpfctl_trans(int dev, struct pfr_buffer *buf, u_long cmd, int from) 1758130617Smlaier{ 1759130617Smlaier struct pfioc_trans trans; 1760130617Smlaier 1761130617Smlaier bzero(&trans, sizeof(trans)); 1762130617Smlaier trans.size = buf->pfrb_size - from; 1763130617Smlaier trans.esize = sizeof(struct pfioc_trans_e); 1764130617Smlaier trans.array = ((struct pfioc_trans_e *)buf->pfrb_caddr) + from; 1765130617Smlaier return ioctl(dev, cmd, &trans); 1766130617Smlaier} 1767