1*f48d62b3Sdhartmei /* $OpenBSD: pfctl_parser.c,v 1.52 2001/10/15 16:22:22 dhartmei Exp $ */ 214a9b182Skjell 314a9b182Skjell /* 4fd3c3a0cSderaadt * Copyright (c) 2001 Daniel Hartmeier 514a9b182Skjell * All rights reserved. 614a9b182Skjell * 714a9b182Skjell * Redistribution and use in source and binary forms, with or without 814a9b182Skjell * modification, are permitted provided that the following conditions 914a9b182Skjell * are met: 1014a9b182Skjell * 1114a9b182Skjell * - Redistributions of source code must retain the above copyright 1214a9b182Skjell * notice, this list of conditions and the following disclaimer. 1314a9b182Skjell * - Redistributions in binary form must reproduce the above 1414a9b182Skjell * copyright notice, this list of conditions and the following 1514a9b182Skjell * disclaimer in the documentation and/or other materials provided 1614a9b182Skjell * with the distribution. 1714a9b182Skjell * 1814a9b182Skjell * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1914a9b182Skjell * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2014a9b182Skjell * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2114a9b182Skjell * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 225974bd37Sdhartmei * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2314a9b182Skjell * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 2414a9b182Skjell * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2514a9b182Skjell * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 2614a9b182Skjell * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2714a9b182Skjell * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 2814a9b182Skjell * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2914a9b182Skjell * POSSIBILITY OF SUCH DAMAGE. 3014a9b182Skjell * 3114a9b182Skjell */ 3214a9b182Skjell 33252d784aSderaadt #include <sys/types.h> 34252d784aSderaadt #include <sys/socket.h> 35252d784aSderaadt #include <net/if.h> 36252d784aSderaadt #include <netinet/in.h> 376329fa59Sderaadt #include <netinet/in_systm.h> 386329fa59Sderaadt #include <netinet/ip.h> 396329fa59Sderaadt #include <netinet/ip_icmp.h> 4030620b12Sfrantzen #include <netinet/icmp6.h> 4155507ad0Sfrantzen #define TCPSTATES 4255507ad0Sfrantzen #include <netinet/tcp_fsm.h> 43252d784aSderaadt #include <net/pfvar.h> 449f13c6caSmillert #include <arpa/inet.h> 45252d784aSderaadt 4614a9b182Skjell #include <stdio.h> 4714a9b182Skjell #include <stdlib.h> 4814a9b182Skjell #include <string.h> 4914a9b182Skjell #include <ctype.h> 5014a9b182Skjell #include <netdb.h> 516329fa59Sderaadt #include <stdarg.h> 526329fa59Sderaadt #include <errno.h> 53ff352a37Smarkus #include <err.h> 5414a9b182Skjell 5514a9b182Skjell #include "pfctl_parser.h" 5614a9b182Skjell 5730620b12Sfrantzen int unmask (struct pf_addr *, int); 5830620b12Sfrantzen void print_addr (struct pf_addr *, struct pf_addr *, int); 5930620b12Sfrantzen void print_host (struct pf_state_host *, int); 606d5ce0fbSderaadt void print_seq (struct pf_state_peer *); 6181a15e5dSderaadt void print_port (u_int8_t, u_int16_t, u_int16_t, char *); 6281a15e5dSderaadt void print_flags (u_int8_t); 6314a9b182Skjell 6481a15e5dSderaadt char *tcpflags = "FSRPAU"; 6514a9b182Skjell 66082ebc44Swilfried struct icmptypeent icmp_type[] = { 67082ebc44Swilfried { "echoreq", ICMP_ECHO }, 68082ebc44Swilfried { "echorep", ICMP_ECHOREPLY }, 69082ebc44Swilfried { "unreach", ICMP_UNREACH }, 70082ebc44Swilfried { "squench", ICMP_SOURCEQUENCH }, 71082ebc44Swilfried { "redir", ICMP_REDIRECT }, 72082ebc44Swilfried { "althost", ICMP_ALTHOSTADDR }, 73082ebc44Swilfried { "routeradv", ICMP_ROUTERADVERT }, 74082ebc44Swilfried { "routersol", ICMP_ROUTERSOLICIT }, 75082ebc44Swilfried { "timex", ICMP_TIMXCEED }, 76082ebc44Swilfried { "paramprob", ICMP_PARAMPROB }, 77082ebc44Swilfried { "timereq", ICMP_TSTAMP }, 78082ebc44Swilfried { "timerep", ICMP_TSTAMPREPLY }, 79082ebc44Swilfried { "inforeq", ICMP_IREQ }, 80082ebc44Swilfried { "inforep", ICMP_IREQREPLY }, 81082ebc44Swilfried { "maskreq", ICMP_MASKREQ }, 8202cbcc9eSwilfried { "maskrep", ICMP_MASKREPLY }, 8302cbcc9eSwilfried { "trace", ICMP_TRACEROUTE }, 8402cbcc9eSwilfried { "dataconv", ICMP_DATACONVERR }, 8502cbcc9eSwilfried { "mobredir", ICMP_MOBILE_REDIRECT }, 8602cbcc9eSwilfried { "ipv6-where", ICMP_IPV6_WHEREAREYOU }, 8702cbcc9eSwilfried { "ipv6-here", ICMP_IPV6_IAMHERE }, 8802cbcc9eSwilfried { "mobregreq", ICMP_MOBILE_REGREQUEST }, 8902cbcc9eSwilfried { "mobregrep", ICMP_MOBILE_REGREPLY }, 9002cbcc9eSwilfried { "skip", ICMP_SKIP }, 9102cbcc9eSwilfried { "photuris", ICMP_PHOTURIS } 9202cbcc9eSwilfried 93082ebc44Swilfried }; 94082ebc44Swilfried 9530620b12Sfrantzen struct icmptypeent icmp6_type[] = { 9630620b12Sfrantzen { "unreach", ICMP6_DST_UNREACH }, 9730620b12Sfrantzen { "toobig", ICMP6_PACKET_TOO_BIG }, 9830620b12Sfrantzen { "timex", ICMP6_TIME_EXCEEDED }, 9930620b12Sfrantzen { "paramprob", ICMP6_PARAM_PROB }, 10030620b12Sfrantzen { "echoreq", ICMP6_ECHO_REQUEST }, 10130620b12Sfrantzen { "echorep", ICMP6_ECHO_REPLY }, 10230620b12Sfrantzen { "groupqry", ICMP6_MEMBERSHIP_QUERY }, 10330620b12Sfrantzen { "listqry", MLD6_LISTENER_QUERY }, 10430620b12Sfrantzen { "grouprep", ICMP6_MEMBERSHIP_REPORT }, 10530620b12Sfrantzen { "listenrep", MLD6_LISTENER_REPORT }, 10630620b12Sfrantzen { "groupterm", ICMP6_MEMBERSHIP_REDUCTION }, 10730620b12Sfrantzen { "listendone", MLD6_LISTENER_DONE }, 10830620b12Sfrantzen { "routersol", ND_ROUTER_SOLICIT }, 10930620b12Sfrantzen { "routeradv", ND_ROUTER_ADVERT }, 11030620b12Sfrantzen { "neighbrsol", ND_NEIGHBOR_SOLICIT }, 11130620b12Sfrantzen { "neighbradv", ND_NEIGHBOR_ADVERT }, 11230620b12Sfrantzen { "redir", ND_REDIRECT }, 11330620b12Sfrantzen { "routrrenum", ICMP6_ROUTER_RENUMBERING }, 11430620b12Sfrantzen { "wrureq", ICMP6_WRUREQUEST }, 11530620b12Sfrantzen { "wrurep", ICMP6_WRUREPLY }, 11630620b12Sfrantzen { "fqdnreq", ICMP6_FQDN_QUERY }, 11730620b12Sfrantzen { "fqdnrep", ICMP6_FQDN_REPLY }, 11830620b12Sfrantzen { "niqry", ICMP6_NI_QUERY }, 11930620b12Sfrantzen { "nirep", ICMP6_NI_REPLY }, 12030620b12Sfrantzen { "mtraceresp", MLD6_MTRACE_RESP }, 12130620b12Sfrantzen { "mtrace", MLD6_MTRACE } 12230620b12Sfrantzen }; 12330620b12Sfrantzen 124082ebc44Swilfried struct icmpcodeent icmp_code[] = { 125082ebc44Swilfried { "net-unr", ICMP_UNREACH, ICMP_UNREACH_NET }, 126082ebc44Swilfried { "host-unr", ICMP_UNREACH, ICMP_UNREACH_HOST }, 127082ebc44Swilfried { "proto-unr", ICMP_UNREACH, ICMP_UNREACH_PROTOCOL }, 128082ebc44Swilfried { "port-unr", ICMP_UNREACH, ICMP_UNREACH_PORT }, 129082ebc44Swilfried { "needfrag", ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG }, 130082ebc44Swilfried { "srcfail", ICMP_UNREACH, ICMP_UNREACH_SRCFAIL }, 131082ebc44Swilfried { "net-unk", ICMP_UNREACH, ICMP_UNREACH_NET_UNKNOWN }, 132082ebc44Swilfried { "host-unk", ICMP_UNREACH, ICMP_UNREACH_HOST_UNKNOWN }, 133082ebc44Swilfried { "isolate", ICMP_UNREACH, ICMP_UNREACH_ISOLATED }, 134082ebc44Swilfried { "net-prohib", ICMP_UNREACH, ICMP_UNREACH_NET_PROHIB }, 135082ebc44Swilfried { "host-prohib", ICMP_UNREACH, ICMP_UNREACH_HOST_PROHIB }, 136082ebc44Swilfried { "net-tos", ICMP_UNREACH, ICMP_UNREACH_TOSNET }, 137082ebc44Swilfried { "host-tos", ICMP_UNREACH, ICMP_UNREACH_TOSHOST }, 138082ebc44Swilfried { "filter-prohib", ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB }, 139082ebc44Swilfried { "host-preced", ICMP_UNREACH, ICMP_UNREACH_HOST_PRECEDENCE }, 140082ebc44Swilfried { "cutoff-preced", ICMP_UNREACH, ICMP_UNREACH_PRECEDENCE_CUTOFF }, 141082ebc44Swilfried { "redir-net", ICMP_REDIRECT, ICMP_REDIRECT_NET }, 142082ebc44Swilfried { "redir-host", ICMP_REDIRECT, ICMP_REDIRECT_HOST }, 143082ebc44Swilfried { "redir-tos-net", ICMP_REDIRECT, ICMP_REDIRECT_TOSNET }, 144082ebc44Swilfried { "redir-tos-host", ICMP_REDIRECT, ICMP_REDIRECT_TOSHOST }, 14502cbcc9eSwilfried { "normal-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL }, 14602cbcc9eSwilfried { "common-adv", ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON }, 147082ebc44Swilfried { "transit", ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS }, 148082ebc44Swilfried { "reassemb", ICMP_TIMXCEED, ICMP_TIMXCEED_REASS }, 149082ebc44Swilfried { "badhead", ICMP_PARAMPROB, ICMP_PARAMPROB_ERRATPTR }, 150082ebc44Swilfried { "optmiss", ICMP_PARAMPROB, ICMP_PARAMPROB_OPTABSENT }, 15102cbcc9eSwilfried { "badlen", ICMP_PARAMPROB, ICMP_PARAMPROB_LENGTH }, 15202cbcc9eSwilfried { "unknown-ind", ICMP_PHOTURIS, ICMP_PHOTURIS_UNKNOWN_INDEX }, 15302cbcc9eSwilfried { "auth-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_AUTH_FAILED }, 15402cbcc9eSwilfried { "decrypt-fail", ICMP_PHOTURIS, ICMP_PHOTURIS_DECRYPT_FAILED } 155082ebc44Swilfried }; 156082ebc44Swilfried 15730620b12Sfrantzen struct icmpcodeent icmp6_code[] = { 1581d32ee3bSdhartmei { "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN }, 1591d32ee3bSdhartmei { "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE }, 16030620b12Sfrantzen { "notnbr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR }, 16130620b12Sfrantzen { "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE }, 16230620b12Sfrantzen { "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR }, 16330620b12Sfrantzen { "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT }, 16430620b12Sfrantzen { "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT }, 16530620b12Sfrantzen { "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY }, 16630620b12Sfrantzen { "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER }, 16730620b12Sfrantzen { "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER }, 16830620b12Sfrantzen { "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK }, 16930620b12Sfrantzen { "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER } 17030620b12Sfrantzen }; 17130620b12Sfrantzen 17230620b12Sfrantzen 173082ebc44Swilfried struct icmptypeent * 174d14c53d7Swilfried geticmptypebynumber(u_int8_t type, u_int8_t af) 175082ebc44Swilfried { 176d77ee430Sdhartmei unsigned i; 177082ebc44Swilfried 178d14c53d7Swilfried if (af != AF_INET6) { 179082ebc44Swilfried for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) { 180082ebc44Swilfried if(type == icmp_type[i].type) 181082ebc44Swilfried return (&icmp_type[i]); 182082ebc44Swilfried } 18330620b12Sfrantzen } else { 18430620b12Sfrantzen for(i=0; i < (sizeof (icmp6_type) / 18530620b12Sfrantzen sizeof(icmp6_type[0])); i++) { 18630620b12Sfrantzen if(type == icmp6_type[i].type) 18730620b12Sfrantzen return (&icmp6_type[i]); 18830620b12Sfrantzen } 18930620b12Sfrantzen } 19030620b12Sfrantzen return (NULL); 191082ebc44Swilfried } 192082ebc44Swilfried 193082ebc44Swilfried struct icmptypeent * 194d14c53d7Swilfried geticmptypebyname(char *w, u_int8_t af) 195082ebc44Swilfried { 196d77ee430Sdhartmei unsigned i; 197082ebc44Swilfried 198d14c53d7Swilfried if (af != AF_INET6) { 199082ebc44Swilfried for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) { 200082ebc44Swilfried if(!strcmp(w, icmp_type[i].name)) 201082ebc44Swilfried return (&icmp_type[i]); 202082ebc44Swilfried } 20330620b12Sfrantzen } else { 20430620b12Sfrantzen for(i=0; i < (sizeof (icmp6_type) / 20530620b12Sfrantzen sizeof(icmp6_type[0])); i++) { 20630620b12Sfrantzen if(!strcmp(w, icmp6_type[i].name)) 20730620b12Sfrantzen return (&icmp6_type[i]); 20830620b12Sfrantzen } 20930620b12Sfrantzen } 21030620b12Sfrantzen return (NULL); 211082ebc44Swilfried } 212082ebc44Swilfried 213082ebc44Swilfried struct icmpcodeent * 214d14c53d7Swilfried geticmpcodebynumber(u_int8_t type, u_int8_t code, u_int8_t af) 215082ebc44Swilfried { 216d77ee430Sdhartmei unsigned i; 217082ebc44Swilfried 218d14c53d7Swilfried if (af != AF_INET6) { 219082ebc44Swilfried for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) { 22030620b12Sfrantzen if (type == icmp_code[i].type && 22130620b12Sfrantzen code == icmp_code[i].code) 222082ebc44Swilfried return (&icmp_code[i]); 223082ebc44Swilfried } 22430620b12Sfrantzen } else { 22530620b12Sfrantzen for(i=0; i < (sizeof (icmp6_code) / 22630620b12Sfrantzen sizeof(icmp6_code[0])); i++) { 22730620b12Sfrantzen if (type == icmp6_code[i].type && 22830620b12Sfrantzen code == icmp6_code[i].code) 22930620b12Sfrantzen return (&icmp6_code[i]); 23030620b12Sfrantzen } 23130620b12Sfrantzen } 23230620b12Sfrantzen return (NULL); 233082ebc44Swilfried } 234082ebc44Swilfried 235082ebc44Swilfried struct icmpcodeent * 236d14c53d7Swilfried geticmpcodebyname(u_long type, char *w, u_int8_t af) 237082ebc44Swilfried { 238d77ee430Sdhartmei unsigned i; 239082ebc44Swilfried 240d14c53d7Swilfried if (af != AF_INET6) { 241082ebc44Swilfried for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) { 24230620b12Sfrantzen if (type == icmp_code[i].type && 24330620b12Sfrantzen !strcmp(w, icmp_code[i].name)) 244082ebc44Swilfried return (&icmp_code[i]); 245082ebc44Swilfried } 24630620b12Sfrantzen } else { 24730620b12Sfrantzen for(i=0; i < (sizeof (icmp6_code) / 24830620b12Sfrantzen sizeof(icmp6_code[0])); i++) { 24930620b12Sfrantzen if (type == icmp6_code[i].type && 25030620b12Sfrantzen !strcmp(w, icmp6_code[i].name)) 25130620b12Sfrantzen return (&icmp6_code[i]); 25230620b12Sfrantzen } 25330620b12Sfrantzen } 25430620b12Sfrantzen return (NULL); 25530620b12Sfrantzen } 25630620b12Sfrantzen 25730620b12Sfrantzen int 25830620b12Sfrantzen unmask(struct pf_addr *m, int af) 25930620b12Sfrantzen { 26030620b12Sfrantzen int i = 31, j = 0, b = 0, msize; 26130620b12Sfrantzen u_int32_t tmp; 26230620b12Sfrantzen 26330620b12Sfrantzen if (af == AF_INET) 26430620b12Sfrantzen msize = 1; 26530620b12Sfrantzen else 26630620b12Sfrantzen msize = 4; 26730620b12Sfrantzen while (j < msize && m->addr32[j] == 0xffffffff) { 26830620b12Sfrantzen b += 32; 26930620b12Sfrantzen j++; 27030620b12Sfrantzen } 27130620b12Sfrantzen if (j < msize) { 27230620b12Sfrantzen tmp = ntohl(m->addr32[j]); 27330620b12Sfrantzen for (i = 31; tmp & (1 << i); --i) 27430620b12Sfrantzen b++; 27530620b12Sfrantzen } 27630620b12Sfrantzen return (b); 277082ebc44Swilfried } 278082ebc44Swilfried 27981a15e5dSderaadt void 28030620b12Sfrantzen print_addr(struct pf_addr *addr, struct pf_addr *mask, int af) 28114a9b182Skjell { 28230620b12Sfrantzen char buf[48]; 28330620b12Sfrantzen const char *bf; 28430620b12Sfrantzen 28530620b12Sfrantzen bf = inet_ntop(af, addr, buf, sizeof(buf)); 28630620b12Sfrantzen printf("%s", bf); 28730620b12Sfrantzen if (mask != NULL) { 28830620b12Sfrantzen if (!PF_AZERO(mask, af)) 28930620b12Sfrantzen printf("/%u", unmask(mask, af)); 29030620b12Sfrantzen } 29114a9b182Skjell } 29214a9b182Skjell 29381a15e5dSderaadt void 29430620b12Sfrantzen print_host(struct pf_state_host *h, int af) 29514a9b182Skjell { 29614a9b182Skjell u_int16_t p = ntohs(h->port); 29781a15e5dSderaadt 29830620b12Sfrantzen print_addr(&h->addr, NULL, af); 29930620b12Sfrantzen if (af == AF_INET) 30030620b12Sfrantzen printf(":%u", p); 30130620b12Sfrantzen else 30230620b12Sfrantzen printf("[%u]", p); 30314a9b182Skjell } 30414a9b182Skjell 30530620b12Sfrantzen 30681a15e5dSderaadt void 3076d5ce0fbSderaadt print_seq(struct pf_state_peer *p) 30814a9b182Skjell { 309b96c47abSfrantzen if (p->seqdiff) 310b96c47abSfrantzen printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo, 311b96c47abSfrantzen p->seqdiff); 312b96c47abSfrantzen else 31314a9b182Skjell printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo); 31414a9b182Skjell } 31514a9b182Skjell 31681a15e5dSderaadt void 31714a9b182Skjell print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto) 31814a9b182Skjell { 31914a9b182Skjell struct servent *s = getservbyport(p1, proto); 32081a15e5dSderaadt 32114a9b182Skjell p1 = ntohs(p1); 32214a9b182Skjell p2 = ntohs(p2); 32314a9b182Skjell printf("port "); 3243b08c811Skrw if (op == PF_OP_IRG) 32514a9b182Skjell printf("%u >< %u ", p1, p2); 3263b08c811Skrw else if (op == PF_OP_XRG) 3273b08c811Skrw printf("%u <> %u ", p1, p2); 328e2baa6deSdugsong else if (op == PF_OP_EQ) { 32914a9b182Skjell if (s != NULL) 33014a9b182Skjell printf("= %s ", s->s_name); 33114a9b182Skjell else 33214a9b182Skjell printf("= %u ", p1); 333e2baa6deSdugsong } else if (op == PF_OP_NE) { 33414a9b182Skjell if (s != NULL) 33514a9b182Skjell printf("!= %s ", s->s_name); 33614a9b182Skjell else 33714a9b182Skjell printf("!= %u ", p1); 338e2baa6deSdugsong } else if (op == PF_OP_LT) 33914a9b182Skjell printf("< %u ", p1); 340e2baa6deSdugsong else if (op == PF_OP_LE) 34114a9b182Skjell printf("<= %u ", p1); 342e2baa6deSdugsong else if (op == PF_OP_GT) 34314a9b182Skjell printf("> %u ", p1); 344e2baa6deSdugsong else if (op == PF_OP_GE) 34514a9b182Skjell printf(">= %u ", p1); 34614a9b182Skjell } 34714a9b182Skjell 34881a15e5dSderaadt void 34914a9b182Skjell print_flags(u_int8_t f) 35014a9b182Skjell { 35114a9b182Skjell int i; 35281a15e5dSderaadt 35314a9b182Skjell for (i = 0; i < 6; ++i) 35414a9b182Skjell if (f & (1 << i)) 35514a9b182Skjell printf("%c", tcpflags[i]); 35614a9b182Skjell } 35714a9b182Skjell 35814a9b182Skjell void 35981a15e5dSderaadt print_nat(struct pf_nat *n) 36014a9b182Skjell { 36153a96278Sderaadt printf("@nat "); 36228964e80Sdhartmei if (n->ifname[0]) { 36328964e80Sdhartmei printf("on "); 364870b51d7Schris if (n->ifnot) 365870b51d7Schris printf("! "); 366870b51d7Schris printf("%s ", n->ifname); 36728964e80Sdhartmei } 36828964e80Sdhartmei printf("from "); 36930620b12Sfrantzen if (!PF_AZERO(&n->saddr, n->af) || !PF_AZERO(&n->smask, n->af)) { 37028964e80Sdhartmei if (n->snot) 37114a9b182Skjell printf("! "); 37230620b12Sfrantzen print_addr(&n->saddr, &n->smask, n->af); 37328964e80Sdhartmei printf(" "); 37428964e80Sdhartmei } else 37528964e80Sdhartmei printf("any "); 37628964e80Sdhartmei printf("to "); 37730620b12Sfrantzen if (!PF_AZERO(&n->daddr, n->af) || !PF_AZERO(&n->dmask, n->af)) { 37830620b12Sfrantzen if (n->snot) 37928964e80Sdhartmei printf("! "); 38030620b12Sfrantzen print_addr(&n->daddr, &n->dmask, n->af); 38128964e80Sdhartmei printf(" "); 38228964e80Sdhartmei } else 38328964e80Sdhartmei printf("any "); 38428964e80Sdhartmei printf("-> "); 38530620b12Sfrantzen print_addr(&n->raddr, NULL, n->af); 38628964e80Sdhartmei printf(" "); 38714a9b182Skjell switch (n->proto) { 38814a9b182Skjell case IPPROTO_TCP: 38914a9b182Skjell printf("proto tcp"); 39014a9b182Skjell break; 39114a9b182Skjell case IPPROTO_UDP: 39214a9b182Skjell printf("proto udp"); 39314a9b182Skjell break; 39414a9b182Skjell case IPPROTO_ICMP: 39514a9b182Skjell printf("proto icmp"); 39614a9b182Skjell break; 39714a9b182Skjell } 39814a9b182Skjell printf("\n"); 39914a9b182Skjell } 40014a9b182Skjell 40114a9b182Skjell void 402a3e657d0Sjasoni print_binat(struct pf_binat *b) 403a3e657d0Sjasoni { 404a3e657d0Sjasoni printf("@binat "); 405a3e657d0Sjasoni if (b->ifname[0]) { 406a3e657d0Sjasoni printf("on "); 407a3e657d0Sjasoni printf("%s ", b->ifname); 408a3e657d0Sjasoni } 409a3e657d0Sjasoni switch (b->proto) { 410a3e657d0Sjasoni case IPPROTO_TCP: 411a3e657d0Sjasoni printf("proto tcp "); 412a3e657d0Sjasoni break; 413a3e657d0Sjasoni case IPPROTO_UDP: 414a3e657d0Sjasoni printf("proto udp "); 415a3e657d0Sjasoni break; 416a3e657d0Sjasoni case IPPROTO_ICMP: 417a3e657d0Sjasoni printf("proto icmp "); 418a3e657d0Sjasoni break; 419a3e657d0Sjasoni } 420a3e657d0Sjasoni printf("from "); 42130620b12Sfrantzen print_addr(&b->saddr, NULL, b->af); 422a3e657d0Sjasoni printf(" "); 423a3e657d0Sjasoni printf("to "); 42430620b12Sfrantzen if (!PF_AZERO(&b->daddr, b->af) || !PF_AZERO(&b->dmask, b->af)) { 425a3e657d0Sjasoni if (b->dnot) 426a3e657d0Sjasoni printf("! "); 42730620b12Sfrantzen print_addr(&b->daddr, &b->dmask, b->af); 428a3e657d0Sjasoni printf(" "); 429a3e657d0Sjasoni } else 430a3e657d0Sjasoni printf("any "); 431a3e657d0Sjasoni printf("-> "); 43230620b12Sfrantzen print_addr(&b->raddr, NULL, b->af); 433a3e657d0Sjasoni printf("\n"); 434a3e657d0Sjasoni } 435a3e657d0Sjasoni 436a3e657d0Sjasoni void 43781a15e5dSderaadt print_rdr(struct pf_rdr *r) 43814a9b182Skjell { 43953a96278Sderaadt printf("@rdr "); 44028964e80Sdhartmei if (r->ifname[0]) { 44128964e80Sdhartmei printf("on "); 442870b51d7Schris if (r->ifnot) 443870b51d7Schris printf("! "); 444870b51d7Schris printf("%s ", r->ifname); 44528964e80Sdhartmei } 446e3d52469Smillert switch (r->proto) { 447e3d52469Smillert case IPPROTO_TCP: 448e3d52469Smillert printf("proto tcp "); 449e3d52469Smillert break; 450e3d52469Smillert case IPPROTO_UDP: 451e3d52469Smillert printf("proto udp "); 452e3d52469Smillert break; 453e3d52469Smillert } 45428964e80Sdhartmei printf("from "); 45530620b12Sfrantzen if (!PF_AZERO(&r->saddr, r->af) || !PF_AZERO(&r->smask, r->af)) { 45628964e80Sdhartmei if (r->snot) 45728964e80Sdhartmei printf("! "); 45830620b12Sfrantzen print_addr(&r->saddr, &r->smask, r->af); 45928964e80Sdhartmei printf(" "); 46028964e80Sdhartmei } else 46128964e80Sdhartmei printf("any "); 46228964e80Sdhartmei printf("to "); 46330620b12Sfrantzen if (!PF_AZERO(&r->daddr, r->af) || !PF_AZERO(&r->dmask, r->af)) { 46430620b12Sfrantzen if (r->snot) 46514a9b182Skjell printf("! "); 46630620b12Sfrantzen print_addr(&r->daddr, &r->dmask, r->af); 46728964e80Sdhartmei printf(" "); 46828964e80Sdhartmei } else 46928964e80Sdhartmei printf("any "); 470cb07131dSkjell printf("port %u", ntohs(r->dport)); 471cb07131dSkjell if (r->opts & PF_DPORT_RANGE) 472cb07131dSkjell printf(":%u", ntohs(r->dport2)); 473cb07131dSkjell printf(" -> "); 47430620b12Sfrantzen print_addr(&r->raddr, NULL, r->af); 47528964e80Sdhartmei printf(" "); 47614a9b182Skjell printf("port %u", ntohs(r->rport)); 477cb07131dSkjell if (r->opts & PF_RPORT_RANGE) 478cb07131dSkjell printf(":*"); 47914a9b182Skjell printf("\n"); 48014a9b182Skjell } 48114a9b182Skjell 482bca2bf17Sdhartmei char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES; 483bca2bf17Sdhartmei char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES; 48499a73934Sderaadt 48514a9b182Skjell void 48681a15e5dSderaadt print_status(struct pf_status *s) 48714a9b182Skjell { 48881a15e5dSderaadt 48999a73934Sderaadt time_t t = time(NULL); 49099a73934Sderaadt int i; 49199a73934Sderaadt 492ae58c8acSdhartmei printf("Status: %s Time: %u Since: %u Debug: ", 4937f08579dSkjell s->running ? "Enabled" : "Disabled", 4947f08579dSkjell t, s->since); 495ae58c8acSdhartmei switch (s->debug) { 496ae58c8acSdhartmei case 0: 497ae58c8acSdhartmei printf("None"); 498ae58c8acSdhartmei break; 499ae58c8acSdhartmei case 1: 500ae58c8acSdhartmei printf("Urgent"); 501ae58c8acSdhartmei break; 502ae58c8acSdhartmei case 2: 503ae58c8acSdhartmei printf("Misc"); 504ae58c8acSdhartmei break; 505ae58c8acSdhartmei } 50630620b12Sfrantzen printf("\nBytes In IPv4: %-10llu Bytes Out: %-10llu\n", 50730620b12Sfrantzen s->bcounters[0][PF_IN], s->bcounters[0][PF_OUT]); 50830620b12Sfrantzen printf(" IPv6: %-10llu Bytes Out: %-10llu\n", 50930620b12Sfrantzen s->bcounters[1][PF_IN], s->bcounters[1][PF_OUT]); 51030620b12Sfrantzen printf("Inbound Packets IPv4: Passed: %-10llu Dropped: %-10llu\n", 51130620b12Sfrantzen s->pcounters[0][PF_IN][PF_PASS], 51230620b12Sfrantzen s->pcounters[0][PF_IN][PF_DROP]); 51330620b12Sfrantzen printf(" IPv6: Passed: %-10llu Dropped: %-10llu\n", 51430620b12Sfrantzen s->pcounters[1][PF_IN][PF_PASS], 51530620b12Sfrantzen s->pcounters[1][PF_IN][PF_DROP]); 51630620b12Sfrantzen printf("Outbound Packets IPv4: Passed: %-10llu Dropped: %-10llu\n", 51730620b12Sfrantzen s->pcounters[0][PF_OUT][PF_PASS], 51830620b12Sfrantzen s->pcounters[0][PF_OUT][PF_DROP]); 51930620b12Sfrantzen printf(" IPv6: Passed: %-10llu Dropped: %-10llu\n", 52030620b12Sfrantzen s->pcounters[1][PF_OUT][PF_PASS], 52130620b12Sfrantzen s->pcounters[1][PF_OUT][PF_DROP]); 52284976600Sderaadt printf("States: %u\n", s->states); 52384976600Sderaadt printf("pf Counters\n"); 524bca2bf17Sdhartmei for (i = 0; i < FCNT_MAX; i++) 525184bf464Sderaadt printf("%-25s %-8lld\n", pf_fcounters[i], 52684976600Sderaadt s->fcounters[i]); 52799a73934Sderaadt printf("Counters\n"); 52899a73934Sderaadt for (i = 0; i < PFRES_MAX; i++) 529184bf464Sderaadt printf("%-25s %-8lld\n", pf_reasons[i], 53099a73934Sderaadt s->counters[i]); 53114a9b182Skjell } 53214a9b182Skjell 53314a9b182Skjell void 534fdd4db37Sdhartmei print_state(struct pf_state *s, int opts) 53514a9b182Skjell { 5366d5ce0fbSderaadt struct pf_state_peer *src, *dst; 53714a9b182Skjell u_int8_t hrs, min, sec; 538252d784aSderaadt 53914a9b182Skjell if (s->direction == PF_OUT) { 54014a9b182Skjell src = &s->src; 54114a9b182Skjell dst = &s->dst; 54214a9b182Skjell } else { 54314a9b182Skjell src = &s->dst; 54414a9b182Skjell dst = &s->src; 54514a9b182Skjell } 54614a9b182Skjell switch (s->proto) { 54714a9b182Skjell case IPPROTO_TCP: 54814a9b182Skjell printf("TCP "); 54914a9b182Skjell break; 55014a9b182Skjell case IPPROTO_UDP: 55114a9b182Skjell printf("UDP "); 55214a9b182Skjell break; 55330620b12Sfrantzen case IPPROTO_ICMPV6: 55414a9b182Skjell case IPPROTO_ICMP: 55514a9b182Skjell printf("ICMP "); 55614a9b182Skjell break; 55714a9b182Skjell default: 55814a9b182Skjell printf("???? "); 55914a9b182Skjell break; 56014a9b182Skjell } 56130620b12Sfrantzen if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) || 56230620b12Sfrantzen (s->lan.port != s->gwy.port)) { 56330620b12Sfrantzen print_host(&s->lan, s->af); 56414a9b182Skjell if (s->direction == PF_OUT) 56514a9b182Skjell printf(" -> "); 56614a9b182Skjell else 56714a9b182Skjell printf(" <- "); 56814a9b182Skjell } 56930620b12Sfrantzen print_host(&s->gwy, s->af); 57014a9b182Skjell if (s->direction == PF_OUT) 57114a9b182Skjell printf(" -> "); 57214a9b182Skjell else 57314a9b182Skjell printf(" <- "); 57430620b12Sfrantzen print_host(&s->ext, s->af); 57514a9b182Skjell 576b96c47abSfrantzen printf(" "); 57714a9b182Skjell if (s->proto == IPPROTO_TCP) { 578b96c47abSfrantzen if (src->state <= TCPS_TIME_WAIT && 579b96c47abSfrantzen dst->state <= TCPS_TIME_WAIT) { 580b96c47abSfrantzen printf(" %s:%s\n", tcpstates[src->state], 58155507ad0Sfrantzen tcpstates[dst->state]); 582b96c47abSfrantzen } else { 583b96c47abSfrantzen printf(" <BAD STATE LEVELS>\n"); 584b96c47abSfrantzen } 585fdd4db37Sdhartmei if (opts & PF_OPT_VERBOSE) { 586b96c47abSfrantzen printf(" "); 58714a9b182Skjell print_seq(src); 58814a9b182Skjell printf(" "); 58914a9b182Skjell print_seq(dst); 59014a9b182Skjell printf("\n"); 591fdd4db37Sdhartmei } 59255507ad0Sfrantzen } else { 593b96c47abSfrantzen printf(" %u:%u\n", src->state, dst->state); 59414a9b182Skjell } 59514a9b182Skjell 596fdd4db37Sdhartmei if (opts & PF_OPT_VERBOSE) { 59714a9b182Skjell sec = s->creation % 60; 59814a9b182Skjell s->creation /= 60; 59914a9b182Skjell min = s->creation % 60; 60014a9b182Skjell s->creation /= 60; 60114a9b182Skjell hrs = s->creation; 60255507ad0Sfrantzen printf(" age %.2u:%.2u:%.2u", hrs, min, sec); 60314a9b182Skjell sec = s->expire % 60; 60414a9b182Skjell s->expire /= 60; 60514a9b182Skjell min = s->expire % 60; 60614a9b182Skjell s->expire /= 60; 60714a9b182Skjell hrs = s->expire; 60814a9b182Skjell printf(", expires in %.2u:%.2u:%.2u", hrs, min, sec); 60914a9b182Skjell printf(", %u pkts, %u bytes\n", s->packets, s->bytes); 61014a9b182Skjell } 611fdd4db37Sdhartmei } 61214a9b182Skjell 61314a9b182Skjell void 61481a15e5dSderaadt print_rule(struct pf_rule *r) 61514a9b182Skjell { 61678baf774Sdhartmei printf("@%d ", r->nr); 6178418a02fSprovos if (r->action == PF_PASS) 61814a9b182Skjell printf("pass "); 619b996d042Sdhartmei else if (r->action == PF_DROP) { 62014a9b182Skjell printf("block "); 62167d2a440Sprovos if (r->rule_flag & PFRULE_RETURNRST) 62214a9b182Skjell printf("return-rst "); 623b996d042Sdhartmei else if (r->return_icmp) { 624b996d042Sdhartmei struct icmpcodeent *ic; 625b996d042Sdhartmei 626d14c53d7Swilfried if (r->af != AF_INET6) 627b996d042Sdhartmei printf("return-icmp"); 628d14c53d7Swilfried else 629d14c53d7Swilfried printf("return-icmp6"); 630b996d042Sdhartmei ic = geticmpcodebynumber(r->return_icmp >> 8, 631d14c53d7Swilfried r->return_icmp & 255, r->af); 632d14c53d7Swilfried 633d14c53d7Swilfried if (ic == NULL) 634d14c53d7Swilfried printf("(%u) ", r->return_icmp & 255); 635d14c53d7Swilfried else if ((r->af != AF_INET6 && ic->code != ICMP_UNREACH_PORT) || 636d14c53d7Swilfried (r->af == AF_INET6 && ic->code != ICMP6_DST_UNREACH_NOPORT)) 637b996d042Sdhartmei printf("(%s) ", ic->name); 638b996d042Sdhartmei else 639b996d042Sdhartmei printf(" "); 640b996d042Sdhartmei } 641b996d042Sdhartmei } else 642b996d042Sdhartmei printf("scrub "); 64314a9b182Skjell if (r->direction == 0) 64414a9b182Skjell printf("in "); 64514a9b182Skjell else 64614a9b182Skjell printf("out "); 6477242ce7aSdhartmei if (r->log == 1) 64814a9b182Skjell printf("log "); 6497242ce7aSdhartmei else if (r->log == 2) 6507242ce7aSdhartmei printf("log-all "); 65114a9b182Skjell if (r->quick) 65214a9b182Skjell printf("quick "); 65314a9b182Skjell if (r->ifname[0]) 65414a9b182Skjell printf("on %s ", r->ifname); 65530620b12Sfrantzen if (r->af) { 65630620b12Sfrantzen if (r->af == AF_INET) 65730620b12Sfrantzen printf("inet "); 65830620b12Sfrantzen else 65930620b12Sfrantzen printf("inet6 "); 66030620b12Sfrantzen } 66114a9b182Skjell if (r->proto) { 66214a9b182Skjell struct protoent *p = getprotobynumber(r->proto); 66314a9b182Skjell if (p != NULL) 66414a9b182Skjell printf("proto %s ", p->p_name); 66514a9b182Skjell else 66614a9b182Skjell printf("proto %u ", r->proto); 66714a9b182Skjell } 66830620b12Sfrantzen if (PF_AZERO(&r->src.addr, AF_INET6) && 66930620b12Sfrantzen PF_AZERO(&r->src.mask, AF_INET6) && 67030620b12Sfrantzen !r->src.port_op && PF_AZERO(&r->dst.addr, AF_INET6) && 67130620b12Sfrantzen PF_AZERO(&r->dst.mask, AF_INET6) && !r->dst.port_op) 67214a9b182Skjell printf("all "); 67314a9b182Skjell else { 67414a9b182Skjell printf("from "); 67530620b12Sfrantzen if (PF_AZERO(&r->src.addr, AF_INET6) && 67630620b12Sfrantzen PF_AZERO(&r->src.mask, AF_INET6)) 67714a9b182Skjell printf("any "); 67814a9b182Skjell else { 67914a9b182Skjell if (r->src.not) 68014a9b182Skjell printf("! "); 68130620b12Sfrantzen print_addr(&r->src.addr, &r->src.mask, r->af); 68214a9b182Skjell printf(" "); 68314a9b182Skjell } 68414a9b182Skjell if (r->src.port_op) 68514a9b182Skjell print_port(r->src.port_op, r->src.port[0], 6865df8e51cSsmart r->src.port[1], 6875df8e51cSsmart r->proto == IPPROTO_TCP ? "tcp" : "udp"); 68814a9b182Skjell 68914a9b182Skjell printf("to "); 69030620b12Sfrantzen if (PF_AZERO(&r->dst.addr, AF_INET6) && 69130620b12Sfrantzen PF_AZERO(&r->dst.mask, AF_INET6)) 69214a9b182Skjell printf("any "); 69314a9b182Skjell else { 69414a9b182Skjell if (r->dst.not) 69514a9b182Skjell printf("! "); 69630620b12Sfrantzen print_addr(&r->dst.addr, &r->dst.mask, r->af); 69714a9b182Skjell printf(" "); 69814a9b182Skjell } 69914a9b182Skjell if (r->dst.port_op) 70014a9b182Skjell print_port(r->dst.port_op, r->dst.port[0], 7015df8e51cSsmart r->dst.port[1], 7025df8e51cSsmart r->proto == IPPROTO_TCP ? "tcp" : "udp"); 70314a9b182Skjell } 70414a9b182Skjell if (r->flags || r->flagset) { 70514a9b182Skjell printf("flags "); 70614a9b182Skjell print_flags(r->flags); 70714a9b182Skjell printf("/"); 70814a9b182Skjell print_flags(r->flagset); 70914a9b182Skjell printf(" "); 71014a9b182Skjell } 711082ebc44Swilfried if (r->type) { 712082ebc44Swilfried struct icmptypeent *p; 713082ebc44Swilfried 714d14c53d7Swilfried p = geticmptypebynumber(r->type-1, r->af); 715d14c53d7Swilfried if (r->af != AF_INET6) 716d14c53d7Swilfried printf("icmp-type"); 717082ebc44Swilfried else 718d14c53d7Swilfried printf("ipv6-icmp-type"); 719d14c53d7Swilfried if (p != NULL) 720d14c53d7Swilfried printf(" %s ", p->name); 721d14c53d7Swilfried else 722d14c53d7Swilfried printf(" %u ", r->type-1); 723082ebc44Swilfried if (r->code) { 724082ebc44Swilfried struct icmpcodeent *p; 725082ebc44Swilfried 726d14c53d7Swilfried p = geticmpcodebynumber(r->type-1, r->code-1, r->af); 727082ebc44Swilfried if (p != NULL) 728082ebc44Swilfried printf("code %s ", p->name); 729082ebc44Swilfried else 73014a9b182Skjell printf("code %u ", r->code-1); 731082ebc44Swilfried } 732082ebc44Swilfried } 733b96c47abSfrantzen if (r->keep_state == PF_STATE_NORMAL) 73414a9b182Skjell printf("keep state "); 735b96c47abSfrantzen else if (r->keep_state == PF_STATE_MODULATE) 736b96c47abSfrantzen printf("modulate state "); 73767d2a440Sprovos if (r->rule_flag & PFRULE_NODF) 73867d2a440Sprovos printf("no-df "); 739e258bfd4Sprovos if (r->min_ttl) 74034c76dcbSprovos printf("min-ttl %d ", r->min_ttl); 741*f48d62b3Sdhartmei if (r->allow_opts) 742*f48d62b3Sdhartmei printf("allow-opts "); 74367d2a440Sprovos 74414a9b182Skjell printf("\n"); 74514a9b182Skjell } 74614a9b182Skjell 7471f8f21bdSmillert int 748ff352a37Smarkus parse_flags(char *s) 74914a9b182Skjell { 750ff352a37Smarkus char *p, *q; 75114a9b182Skjell u_int8_t f = 0; 75281a15e5dSderaadt 753ff352a37Smarkus for (p = s; *p; p++) { 754ff352a37Smarkus if ((q = strchr(tcpflags, *p)) == NULL) 755ff352a37Smarkus return -1; 756ff352a37Smarkus else 757ff352a37Smarkus f |= 1 << (q - tcpflags); 75814a9b182Skjell } 759dbfb98deSprovos return (f ? f : 63); 76014a9b182Skjell } 761