xref: /openbsd/sbin/pfctl/pfctl_parser.c (revision 5d9ac2dc)
1*5d9ac2dcSdhartmei /*	$OpenBSD: pfctl_parser.c,v 1.68 2002/05/09 19:58:42 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 
57ece4c078Smpech int		 unmask (struct pf_addr *, u_int8_t);
58032e40b7Sdhartmei void		 print_addr (struct pf_addr_wrap *, struct pf_addr *, u_int8_t);
590eed2997Sdhartmei void		 print_host (struct pf_state_host *, u_int8_t, int);
606d5ce0fbSderaadt void		 print_seq (struct pf_state_peer *);
61*5d9ac2dcSdhartmei void		 print_op (u_int8_t, const char *, const char *);
6281a15e5dSderaadt void		 print_port (u_int8_t, u_int16_t, u_int16_t, char *);
63*5d9ac2dcSdhartmei void		 print_uid (u_int8_t, uid_t, uid_t, const char *);
6481a15e5dSderaadt void		 print_flags (u_int8_t);
6514a9b182Skjell 
6681a15e5dSderaadt char *tcpflags = "FSRPAU";
6714a9b182Skjell 
68082ebc44Swilfried struct icmptypeent icmp_type[] = {
69082ebc44Swilfried 	{ "echoreq",	ICMP_ECHO },
70082ebc44Swilfried 	{ "echorep",	ICMP_ECHOREPLY },
71082ebc44Swilfried 	{ "unreach",	ICMP_UNREACH },
72082ebc44Swilfried 	{ "squench",	ICMP_SOURCEQUENCH },
73082ebc44Swilfried 	{ "redir",	ICMP_REDIRECT },
74082ebc44Swilfried 	{ "althost",	ICMP_ALTHOSTADDR },
75082ebc44Swilfried 	{ "routeradv",	ICMP_ROUTERADVERT },
76082ebc44Swilfried 	{ "routersol",	ICMP_ROUTERSOLICIT },
77082ebc44Swilfried 	{ "timex",	ICMP_TIMXCEED },
78082ebc44Swilfried 	{ "paramprob",	ICMP_PARAMPROB },
79082ebc44Swilfried 	{ "timereq",	ICMP_TSTAMP },
80082ebc44Swilfried 	{ "timerep",	ICMP_TSTAMPREPLY },
81082ebc44Swilfried 	{ "inforeq",	ICMP_IREQ },
82082ebc44Swilfried 	{ "inforep",	ICMP_IREQREPLY },
83082ebc44Swilfried 	{ "maskreq",	ICMP_MASKREQ },
8402cbcc9eSwilfried 	{ "maskrep",	ICMP_MASKREPLY },
8502cbcc9eSwilfried 	{ "trace",	ICMP_TRACEROUTE },
8602cbcc9eSwilfried 	{ "dataconv",	ICMP_DATACONVERR },
8702cbcc9eSwilfried 	{ "mobredir",	ICMP_MOBILE_REDIRECT },
8802cbcc9eSwilfried 	{ "ipv6-where",	ICMP_IPV6_WHEREAREYOU },
8902cbcc9eSwilfried 	{ "ipv6-here",	ICMP_IPV6_IAMHERE },
9002cbcc9eSwilfried 	{ "mobregreq",	ICMP_MOBILE_REGREQUEST },
9102cbcc9eSwilfried 	{ "mobregrep",	ICMP_MOBILE_REGREPLY },
9202cbcc9eSwilfried 	{ "skip",	ICMP_SKIP },
9302cbcc9eSwilfried 	{ "photuris",	ICMP_PHOTURIS }
9402cbcc9eSwilfried 
95082ebc44Swilfried };
96082ebc44Swilfried 
9730620b12Sfrantzen struct icmptypeent icmp6_type[] = {
9830620b12Sfrantzen 	{ "unreach",	ICMP6_DST_UNREACH },
9930620b12Sfrantzen 	{ "toobig",	ICMP6_PACKET_TOO_BIG },
10030620b12Sfrantzen 	{ "timex",	ICMP6_TIME_EXCEEDED },
10130620b12Sfrantzen 	{ "paramprob",	ICMP6_PARAM_PROB },
10230620b12Sfrantzen 	{ "echoreq",	ICMP6_ECHO_REQUEST },
10330620b12Sfrantzen 	{ "echorep",	ICMP6_ECHO_REPLY },
10430620b12Sfrantzen 	{ "groupqry",	ICMP6_MEMBERSHIP_QUERY },
10530620b12Sfrantzen 	{ "listqry",	MLD6_LISTENER_QUERY },
10630620b12Sfrantzen 	{ "grouprep",	ICMP6_MEMBERSHIP_REPORT },
10730620b12Sfrantzen 	{ "listenrep",	MLD6_LISTENER_REPORT },
10830620b12Sfrantzen 	{ "groupterm",	ICMP6_MEMBERSHIP_REDUCTION },
10930620b12Sfrantzen 	{ "listendone", MLD6_LISTENER_DONE },
11030620b12Sfrantzen 	{ "routersol",	ND_ROUTER_SOLICIT },
11130620b12Sfrantzen 	{ "routeradv",	ND_ROUTER_ADVERT },
11230620b12Sfrantzen 	{ "neighbrsol", ND_NEIGHBOR_SOLICIT },
11330620b12Sfrantzen 	{ "neighbradv", ND_NEIGHBOR_ADVERT },
11430620b12Sfrantzen 	{ "redir",	ND_REDIRECT },
11530620b12Sfrantzen 	{ "routrrenum", ICMP6_ROUTER_RENUMBERING },
11630620b12Sfrantzen 	{ "wrureq",	ICMP6_WRUREQUEST },
11730620b12Sfrantzen 	{ "wrurep",	ICMP6_WRUREPLY },
11830620b12Sfrantzen 	{ "fqdnreq",	ICMP6_FQDN_QUERY },
11930620b12Sfrantzen 	{ "fqdnrep",	ICMP6_FQDN_REPLY },
12030620b12Sfrantzen 	{ "niqry",	ICMP6_NI_QUERY },
12130620b12Sfrantzen 	{ "nirep",	ICMP6_NI_REPLY },
12230620b12Sfrantzen 	{ "mtraceresp",	MLD6_MTRACE_RESP },
12330620b12Sfrantzen 	{ "mtrace",	MLD6_MTRACE }
12430620b12Sfrantzen };
12530620b12Sfrantzen 
126082ebc44Swilfried struct icmpcodeent icmp_code[] = {
127082ebc44Swilfried 	{ "net-unr",		ICMP_UNREACH,	ICMP_UNREACH_NET },
128082ebc44Swilfried 	{ "host-unr",		ICMP_UNREACH,	ICMP_UNREACH_HOST },
129082ebc44Swilfried 	{ "proto-unr",		ICMP_UNREACH,	ICMP_UNREACH_PROTOCOL },
130082ebc44Swilfried 	{ "port-unr",		ICMP_UNREACH,	ICMP_UNREACH_PORT },
131082ebc44Swilfried 	{ "needfrag",		ICMP_UNREACH,	ICMP_UNREACH_NEEDFRAG },
132082ebc44Swilfried 	{ "srcfail",		ICMP_UNREACH,	ICMP_UNREACH_SRCFAIL },
133082ebc44Swilfried 	{ "net-unk",		ICMP_UNREACH,	ICMP_UNREACH_NET_UNKNOWN },
134082ebc44Swilfried 	{ "host-unk",		ICMP_UNREACH,	ICMP_UNREACH_HOST_UNKNOWN },
135082ebc44Swilfried 	{ "isolate",		ICMP_UNREACH,	ICMP_UNREACH_ISOLATED },
136082ebc44Swilfried 	{ "net-prohib",		ICMP_UNREACH,	ICMP_UNREACH_NET_PROHIB },
137082ebc44Swilfried 	{ "host-prohib",	ICMP_UNREACH,	ICMP_UNREACH_HOST_PROHIB },
138082ebc44Swilfried 	{ "net-tos",		ICMP_UNREACH,	ICMP_UNREACH_TOSNET },
139082ebc44Swilfried 	{ "host-tos",		ICMP_UNREACH,	ICMP_UNREACH_TOSHOST },
140082ebc44Swilfried 	{ "filter-prohib",	ICMP_UNREACH,	ICMP_UNREACH_FILTER_PROHIB },
141082ebc44Swilfried 	{ "host-preced",	ICMP_UNREACH,	ICMP_UNREACH_HOST_PRECEDENCE },
142082ebc44Swilfried 	{ "cutoff-preced",	ICMP_UNREACH,	ICMP_UNREACH_PRECEDENCE_CUTOFF },
143082ebc44Swilfried 	{ "redir-net",		ICMP_REDIRECT,	ICMP_REDIRECT_NET },
144082ebc44Swilfried 	{ "redir-host",		ICMP_REDIRECT,	ICMP_REDIRECT_HOST },
145082ebc44Swilfried 	{ "redir-tos-net",	ICMP_REDIRECT,	ICMP_REDIRECT_TOSNET },
146082ebc44Swilfried 	{ "redir-tos-host",	ICMP_REDIRECT,	ICMP_REDIRECT_TOSHOST },
14702cbcc9eSwilfried 	{ "normal-adv",		ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL },
14802cbcc9eSwilfried 	{ "common-adv",		ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON },
149082ebc44Swilfried 	{ "transit",		ICMP_TIMXCEED,	ICMP_TIMXCEED_INTRANS },
150082ebc44Swilfried 	{ "reassemb",		ICMP_TIMXCEED,	ICMP_TIMXCEED_REASS },
151082ebc44Swilfried 	{ "badhead",		ICMP_PARAMPROB,	ICMP_PARAMPROB_ERRATPTR },
152082ebc44Swilfried 	{ "optmiss",		ICMP_PARAMPROB,	ICMP_PARAMPROB_OPTABSENT },
15302cbcc9eSwilfried 	{ "badlen",		ICMP_PARAMPROB,	ICMP_PARAMPROB_LENGTH },
15402cbcc9eSwilfried 	{ "unknown-ind",	ICMP_PHOTURIS,	ICMP_PHOTURIS_UNKNOWN_INDEX },
15502cbcc9eSwilfried 	{ "auth-fail",		ICMP_PHOTURIS,	ICMP_PHOTURIS_AUTH_FAILED },
15602cbcc9eSwilfried 	{ "decrypt-fail",	ICMP_PHOTURIS,	ICMP_PHOTURIS_DECRYPT_FAILED }
157082ebc44Swilfried };
158082ebc44Swilfried 
15930620b12Sfrantzen struct icmpcodeent icmp6_code[] = {
1601d32ee3bSdhartmei 	{ "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN },
1611d32ee3bSdhartmei 	{ "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE },
16230620b12Sfrantzen 	{ "notnbr-unr",	ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR },
16330620b12Sfrantzen 	{ "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE },
16430620b12Sfrantzen 	{ "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR },
16530620b12Sfrantzen 	{ "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT },
16630620b12Sfrantzen 	{ "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT },
16730620b12Sfrantzen 	{ "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY },
16830620b12Sfrantzen 	{ "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER },
16930620b12Sfrantzen 	{ "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER },
17030620b12Sfrantzen 	{ "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK },
17130620b12Sfrantzen 	{ "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER }
17230620b12Sfrantzen };
17330620b12Sfrantzen 
17430620b12Sfrantzen 
175082ebc44Swilfried struct icmptypeent *
176d14c53d7Swilfried geticmptypebynumber(u_int8_t type, u_int8_t af)
177082ebc44Swilfried {
178d77ee430Sdhartmei 	unsigned i;
179082ebc44Swilfried 
180d14c53d7Swilfried 	if (af != AF_INET6) {
181082ebc44Swilfried 		for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) {
182082ebc44Swilfried 			if(type == icmp_type[i].type)
183082ebc44Swilfried 				return (&icmp_type[i]);
184082ebc44Swilfried 		}
18530620b12Sfrantzen 	} else {
18630620b12Sfrantzen 		for(i=0; i < (sizeof (icmp6_type) /
18730620b12Sfrantzen 		    sizeof(icmp6_type[0])); i++) {
18830620b12Sfrantzen 			if(type == icmp6_type[i].type)
18930620b12Sfrantzen 				 return (&icmp6_type[i]);
19030620b12Sfrantzen 		}
19130620b12Sfrantzen 	}
19230620b12Sfrantzen 	return (NULL);
193082ebc44Swilfried }
194082ebc44Swilfried 
195082ebc44Swilfried struct icmptypeent *
196d14c53d7Swilfried geticmptypebyname(char *w, u_int8_t af)
197082ebc44Swilfried {
198d77ee430Sdhartmei 	unsigned i;
199082ebc44Swilfried 
200d14c53d7Swilfried 	if (af != AF_INET6) {
201082ebc44Swilfried 		for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) {
202082ebc44Swilfried 			if(!strcmp(w, icmp_type[i].name))
203082ebc44Swilfried 				return (&icmp_type[i]);
204082ebc44Swilfried 		}
20530620b12Sfrantzen 	} else {
20630620b12Sfrantzen 		for(i=0; i < (sizeof (icmp6_type) /
20730620b12Sfrantzen 		    sizeof(icmp6_type[0])); i++) {
20830620b12Sfrantzen 			if(!strcmp(w, icmp6_type[i].name))
20930620b12Sfrantzen 				return (&icmp6_type[i]);
21030620b12Sfrantzen 		}
21130620b12Sfrantzen 	}
21230620b12Sfrantzen 	return (NULL);
213082ebc44Swilfried }
214082ebc44Swilfried 
215082ebc44Swilfried struct icmpcodeent *
216d14c53d7Swilfried geticmpcodebynumber(u_int8_t type, u_int8_t code, u_int8_t af)
217082ebc44Swilfried {
218d77ee430Sdhartmei 	unsigned i;
219082ebc44Swilfried 
220d14c53d7Swilfried 	if (af != AF_INET6) {
221082ebc44Swilfried 		for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) {
22230620b12Sfrantzen 			if (type == icmp_code[i].type &&
22330620b12Sfrantzen 			    code == icmp_code[i].code)
224082ebc44Swilfried 				return (&icmp_code[i]);
225082ebc44Swilfried 		}
22630620b12Sfrantzen 	} else {
22730620b12Sfrantzen 		for(i=0; i < (sizeof (icmp6_code) /
22830620b12Sfrantzen 		   sizeof(icmp6_code[0])); i++) {
22930620b12Sfrantzen 			if (type == icmp6_code[i].type &&
23030620b12Sfrantzen 			    code == icmp6_code[i].code)
23130620b12Sfrantzen 				return (&icmp6_code[i]);
23230620b12Sfrantzen 		}
23330620b12Sfrantzen 	}
23430620b12Sfrantzen 	return (NULL);
235082ebc44Swilfried }
236082ebc44Swilfried 
237082ebc44Swilfried struct icmpcodeent *
238d14c53d7Swilfried geticmpcodebyname(u_long type, char *w, u_int8_t af)
239082ebc44Swilfried {
240d77ee430Sdhartmei 	unsigned i;
241082ebc44Swilfried 
242d14c53d7Swilfried 	if (af != AF_INET6) {
243082ebc44Swilfried 		for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) {
24430620b12Sfrantzen 			if (type == icmp_code[i].type &&
24530620b12Sfrantzen 			    !strcmp(w, icmp_code[i].name))
246082ebc44Swilfried 				return (&icmp_code[i]);
247082ebc44Swilfried 		}
24830620b12Sfrantzen 	} else {
24930620b12Sfrantzen 		for(i=0; i < (sizeof (icmp6_code) /
25030620b12Sfrantzen 		    sizeof(icmp6_code[0])); i++) {
25130620b12Sfrantzen 			if (type == icmp6_code[i].type &&
25230620b12Sfrantzen 			    !strcmp(w, icmp6_code[i].name))
25330620b12Sfrantzen 				return (&icmp6_code[i]);
25430620b12Sfrantzen 		}
25530620b12Sfrantzen 	}
25630620b12Sfrantzen 	return (NULL);
25730620b12Sfrantzen }
25830620b12Sfrantzen 
25930620b12Sfrantzen int
260ece4c078Smpech unmask(struct pf_addr *m, u_int8_t af)
26130620b12Sfrantzen {
26230620b12Sfrantzen 	int i = 31, j = 0, b = 0, msize;
26330620b12Sfrantzen 	u_int32_t tmp;
26430620b12Sfrantzen 
26530620b12Sfrantzen 	if (af == AF_INET)
26630620b12Sfrantzen 		msize = 1;
26730620b12Sfrantzen 	else
26830620b12Sfrantzen 		msize = 4;
26930620b12Sfrantzen 	while (j < msize && m->addr32[j] == 0xffffffff) {
27030620b12Sfrantzen 			b += 32;
27130620b12Sfrantzen 			j++;
27230620b12Sfrantzen 	}
27330620b12Sfrantzen 	if (j < msize) {
27430620b12Sfrantzen 		tmp = ntohl(m->addr32[j]);
27530620b12Sfrantzen 		for (i = 31; tmp & (1 << i); --i)
27630620b12Sfrantzen 			b++;
27730620b12Sfrantzen 	}
27830620b12Sfrantzen 	return (b);
279082ebc44Swilfried }
280082ebc44Swilfried 
28181a15e5dSderaadt void
282032e40b7Sdhartmei print_addr(struct pf_addr_wrap *addr, struct pf_addr *mask, u_int8_t af)
28314a9b182Skjell {
28430620b12Sfrantzen 	char buf[48];
28530620b12Sfrantzen 
286032e40b7Sdhartmei 	if (addr->addr_dyn != NULL)
287032e40b7Sdhartmei 		printf("(%s)", addr->addr.pfa.ifname);
288032e40b7Sdhartmei 	else {
289032e40b7Sdhartmei 		if (inet_ntop(af, &addr->addr, buf, sizeof(buf)) == NULL)
290ded7153fSdhartmei 			printf("?");
291ded7153fSdhartmei 		else
292ded7153fSdhartmei 			printf("%s", buf);
293032e40b7Sdhartmei 	}
29430620b12Sfrantzen 	if (mask != NULL) {
295032e40b7Sdhartmei 		int bits = unmask(mask, af);
296032e40b7Sdhartmei 
297032e40b7Sdhartmei 		if (bits != (af == AF_INET ? 32 : 128))
298032e40b7Sdhartmei 			printf("/%u", bits);
29930620b12Sfrantzen 	}
30014a9b182Skjell }
30114a9b182Skjell 
30281a15e5dSderaadt void
3030eed2997Sdhartmei print_name(struct pf_addr *addr, struct pf_addr *mask, int af)
3040eed2997Sdhartmei {
3050eed2997Sdhartmei 	char buf[48];
3060eed2997Sdhartmei 	struct hostent *hp;
3070eed2997Sdhartmei 
308ded7153fSdhartmei 	if (inet_ntop(af, addr, buf, sizeof(buf)) == NULL)
309ded7153fSdhartmei 		printf("?");
310ded7153fSdhartmei 	else {
311ded7153fSdhartmei 		hp = getpfhostname(buf);
3120eed2997Sdhartmei 		printf("%s", hp->h_name);
313ded7153fSdhartmei 	}
3140eed2997Sdhartmei 	if (mask != NULL) {
315032e40b7Sdhartmei 
3160eed2997Sdhartmei 		if (!PF_AZERO(mask, af))
3170eed2997Sdhartmei 			printf("/%u", unmask(mask, af));
3180eed2997Sdhartmei 	}
3190eed2997Sdhartmei }
3200eed2997Sdhartmei 
3210eed2997Sdhartmei void
3220eed2997Sdhartmei print_host(struct pf_state_host *h, u_int8_t af, int opts)
32314a9b182Skjell {
32414a9b182Skjell 	u_int16_t p = ntohs(h->port);
32581a15e5dSderaadt 
3260eed2997Sdhartmei 	if (opts & PF_OPT_USEDNS)
3270eed2997Sdhartmei 		print_name(&h->addr, NULL, af);
328032e40b7Sdhartmei 	else {
329032e40b7Sdhartmei 		struct pf_addr_wrap aw;
330032e40b7Sdhartmei 
331032e40b7Sdhartmei 		aw.addr = h->addr;
332032e40b7Sdhartmei 		aw.addr_dyn = NULL;
333032e40b7Sdhartmei 		print_addr(&aw, NULL, af);
334032e40b7Sdhartmei 	}
3350eed2997Sdhartmei 
33680edb1f0Sdhartmei 	if (p) {
33730620b12Sfrantzen 		if (af == AF_INET)
33830620b12Sfrantzen 			printf(":%u", p);
33930620b12Sfrantzen 		else
34030620b12Sfrantzen 			printf("[%u]", p);
34114a9b182Skjell 	}
34280edb1f0Sdhartmei }
34314a9b182Skjell 
34430620b12Sfrantzen 
34581a15e5dSderaadt void
3466d5ce0fbSderaadt print_seq(struct pf_state_peer *p)
34714a9b182Skjell {
348b96c47abSfrantzen 	if (p->seqdiff)
349b96c47abSfrantzen 		printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo,
350b96c47abSfrantzen 		    p->seqdiff);
351b96c47abSfrantzen 	else
35214a9b182Skjell 		printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo);
35314a9b182Skjell }
35414a9b182Skjell 
35581a15e5dSderaadt void
356*5d9ac2dcSdhartmei print_op(u_int8_t op, const char *a1, const char *a2)
357*5d9ac2dcSdhartmei {
358*5d9ac2dcSdhartmei 	if (op == PF_OP_IRG)
359*5d9ac2dcSdhartmei 		printf("%s >< %s ", a1, a2);
360*5d9ac2dcSdhartmei 	else if (op == PF_OP_XRG)
361*5d9ac2dcSdhartmei 		printf("%s <> %s ", a1, a2);
362*5d9ac2dcSdhartmei 	else if (op == PF_OP_EQ) {
363*5d9ac2dcSdhartmei 		printf("= %s ", a1);
364*5d9ac2dcSdhartmei 	} else if (op == PF_OP_NE) {
365*5d9ac2dcSdhartmei 		printf("!= %s ", a1);
366*5d9ac2dcSdhartmei 	} else if (op == PF_OP_LT)
367*5d9ac2dcSdhartmei 		printf("< %s ", a1);
368*5d9ac2dcSdhartmei 	else if (op == PF_OP_LE)
369*5d9ac2dcSdhartmei 		printf("<= %s ", a1);
370*5d9ac2dcSdhartmei 	else if (op == PF_OP_GT)
371*5d9ac2dcSdhartmei 		printf("> %s ", a1);
372*5d9ac2dcSdhartmei 	else if (op == PF_OP_GE)
373*5d9ac2dcSdhartmei 		printf(">= %s ", a1);
374*5d9ac2dcSdhartmei }
375*5d9ac2dcSdhartmei 
376*5d9ac2dcSdhartmei void
37714a9b182Skjell print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto)
37814a9b182Skjell {
379*5d9ac2dcSdhartmei 	char a1[5], a2[5];
38014a9b182Skjell 	struct servent *s = getservbyport(p1, proto);
38181a15e5dSderaadt 
38214a9b182Skjell 	p1 = ntohs(p1);
38314a9b182Skjell 	p2 = ntohs(p2);
384*5d9ac2dcSdhartmei 	snprintf(a1, sizeof(a1), "%u", p1);
385*5d9ac2dcSdhartmei 	snprintf(a2, sizeof(a2), "%u", p2);
38614a9b182Skjell 	printf("port ");
387*5d9ac2dcSdhartmei 	if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE))
388*5d9ac2dcSdhartmei 		print_op(op, s->s_name, a2);
38914a9b182Skjell 	else
390*5d9ac2dcSdhartmei 		print_op(op, a1, a2);
391*5d9ac2dcSdhartmei }
392*5d9ac2dcSdhartmei 
393*5d9ac2dcSdhartmei void
394*5d9ac2dcSdhartmei print_uid(u_int8_t op, uid_t u1, uid_t u2, const char *t)
395*5d9ac2dcSdhartmei {
396*5d9ac2dcSdhartmei 	char a1[5], a2[5];
397*5d9ac2dcSdhartmei 
398*5d9ac2dcSdhartmei 	snprintf(a1, sizeof(a1), "%u", u1);
399*5d9ac2dcSdhartmei 	snprintf(a2, sizeof(a2), "%u", u2);
400*5d9ac2dcSdhartmei 	printf("%s ", t);
401*5d9ac2dcSdhartmei 	if (u1 == UID_MAX && (op == PF_OP_EQ || op == PF_OP_NE))
402*5d9ac2dcSdhartmei 		print_op(op, "unknown", a2);
40314a9b182Skjell 	else
404*5d9ac2dcSdhartmei 		print_op(op, a1, a2);
40514a9b182Skjell }
40614a9b182Skjell 
40781a15e5dSderaadt void
40814a9b182Skjell print_flags(u_int8_t f)
40914a9b182Skjell {
41014a9b182Skjell 	int i;
41181a15e5dSderaadt 
41214a9b182Skjell 	for (i = 0; i < 6; ++i)
41314a9b182Skjell 		if (f & (1 << i))
41414a9b182Skjell 			printf("%c", tcpflags[i]);
41514a9b182Skjell }
41614a9b182Skjell 
41714a9b182Skjell void
41881a15e5dSderaadt print_nat(struct pf_nat *n)
41914a9b182Skjell {
420f27db9bcSdhartmei 	if (n->no)
421f27db9bcSdhartmei 		printf("no ");
422f27db9bcSdhartmei 	printf("nat ");
42328964e80Sdhartmei 	if (n->ifname[0]) {
42428964e80Sdhartmei 		printf("on ");
425870b51d7Schris 		if (n->ifnot)
426870b51d7Schris 			printf("! ");
427870b51d7Schris 		printf("%s ", n->ifname);
42828964e80Sdhartmei 	}
429032e40b7Sdhartmei 	if (n->af) {
430032e40b7Sdhartmei 		if (n->af == AF_INET)
431032e40b7Sdhartmei 			printf("inet ");
432032e40b7Sdhartmei 		else
433032e40b7Sdhartmei 			printf("inet6 ");
434032e40b7Sdhartmei 	}
43580edb1f0Sdhartmei 	if (n->proto) {
43680edb1f0Sdhartmei 		struct protoent *p = getprotobynumber(n->proto);
437ab745e3bSmpech 		if (p != NULL)
43880edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
43980edb1f0Sdhartmei 		else
44080edb1f0Sdhartmei 			printf("proto %u ", n->proto);
44180edb1f0Sdhartmei 	}
44228964e80Sdhartmei 	printf("from ");
443032e40b7Sdhartmei 	if (!PF_AZERO(&n->saddr.addr, n->af) || !PF_AZERO(&n->smask, n->af)) {
44428964e80Sdhartmei 		if (n->snot)
44514a9b182Skjell 			printf("! ");
44630620b12Sfrantzen 		print_addr(&n->saddr, &n->smask, n->af);
44728964e80Sdhartmei 		printf(" ");
44828964e80Sdhartmei 	} else
44928964e80Sdhartmei 		printf("any ");
45028964e80Sdhartmei 	printf("to ");
451032e40b7Sdhartmei 	if (!PF_AZERO(&n->daddr.addr, n->af) || !PF_AZERO(&n->dmask, n->af)) {
45205885aacSfrantzen 		if (n->dnot)
45328964e80Sdhartmei 			printf("! ");
45430620b12Sfrantzen 		print_addr(&n->daddr, &n->dmask, n->af);
45528964e80Sdhartmei 		printf(" ");
45628964e80Sdhartmei 	} else
45728964e80Sdhartmei 		printf("any ");
458f27db9bcSdhartmei 	if (!n->no) {
45928964e80Sdhartmei 		printf("-> ");
46030620b12Sfrantzen 		print_addr(&n->raddr, NULL, n->af);
461f27db9bcSdhartmei 	}
46214a9b182Skjell 	printf("\n");
46314a9b182Skjell }
46414a9b182Skjell 
46514a9b182Skjell void
466a3e657d0Sjasoni print_binat(struct pf_binat *b)
467a3e657d0Sjasoni {
468f27db9bcSdhartmei 	if (b->no)
469f27db9bcSdhartmei 		printf("no ");
470f27db9bcSdhartmei 	printf("binat ");
471a3e657d0Sjasoni 	if (b->ifname[0]) {
472a3e657d0Sjasoni 		printf("on ");
473a3e657d0Sjasoni 		printf("%s ", b->ifname);
474a3e657d0Sjasoni 	}
475032e40b7Sdhartmei 	if (b->af) {
476032e40b7Sdhartmei 		if (b->af == AF_INET)
477032e40b7Sdhartmei 			printf("inet ");
478032e40b7Sdhartmei 		else
479032e40b7Sdhartmei 			printf("inet6 ");
480032e40b7Sdhartmei 	}
48180edb1f0Sdhartmei 	if (b->proto) {
48280edb1f0Sdhartmei 		struct protoent *p = getprotobynumber(b->proto);
48380edb1f0Sdhartmei 		if (p != NULL)
48480edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
48580edb1f0Sdhartmei 		else
48680edb1f0Sdhartmei 			printf("proto %u ", b->proto);
487a3e657d0Sjasoni 	}
488a3e657d0Sjasoni 	printf("from ");
48930620b12Sfrantzen 	print_addr(&b->saddr, NULL, b->af);
490a3e657d0Sjasoni 	printf(" ");
491a3e657d0Sjasoni 	printf("to ");
492032e40b7Sdhartmei 	if (!PF_AZERO(&b->daddr.addr, b->af) || !PF_AZERO(&b->dmask, b->af)) {
493a3e657d0Sjasoni 		if (b->dnot)
494a3e657d0Sjasoni 			printf("! ");
49530620b12Sfrantzen 		print_addr(&b->daddr, &b->dmask, b->af);
496a3e657d0Sjasoni 		printf(" ");
497a3e657d0Sjasoni 	} else
498a3e657d0Sjasoni 		printf("any ");
499f27db9bcSdhartmei 	if (!b->no) {
500a3e657d0Sjasoni 	 	printf("-> ");
50130620b12Sfrantzen 		print_addr(&b->raddr, NULL, b->af);
502f27db9bcSdhartmei 	}
503a3e657d0Sjasoni 	printf("\n");
504a3e657d0Sjasoni }
505a3e657d0Sjasoni 
506a3e657d0Sjasoni void
50781a15e5dSderaadt print_rdr(struct pf_rdr *r)
50814a9b182Skjell {
509f27db9bcSdhartmei 	if (r->no)
510f27db9bcSdhartmei 		printf("no ");
511f27db9bcSdhartmei 	printf("rdr ");
51228964e80Sdhartmei 	if (r->ifname[0]) {
51328964e80Sdhartmei 		printf("on ");
514870b51d7Schris 		if (r->ifnot)
515870b51d7Schris 			printf("! ");
516870b51d7Schris 		printf("%s ", r->ifname);
51728964e80Sdhartmei 	}
518032e40b7Sdhartmei 	if (r->af) {
519032e40b7Sdhartmei 		if (r->af == AF_INET)
520032e40b7Sdhartmei 			printf("inet ");
521032e40b7Sdhartmei 		else
522032e40b7Sdhartmei 			printf("inet6 ");
523032e40b7Sdhartmei 	}
52480edb1f0Sdhartmei 	if (r->proto) {
52580edb1f0Sdhartmei 		struct protoent *p = getprotobynumber(r->proto);
52680edb1f0Sdhartmei 		if (p != NULL)
52780edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
52880edb1f0Sdhartmei 		else
52980edb1f0Sdhartmei 			printf("proto %u ", r->proto);
530e3d52469Smillert 	}
53128964e80Sdhartmei 	printf("from ");
532032e40b7Sdhartmei 	if (!PF_AZERO(&r->saddr.addr, r->af) || !PF_AZERO(&r->smask, r->af)) {
53328964e80Sdhartmei 		if (r->snot)
53428964e80Sdhartmei 			printf("! ");
53530620b12Sfrantzen 		print_addr(&r->saddr, &r->smask, r->af);
53628964e80Sdhartmei 		printf(" ");
53728964e80Sdhartmei 	} else
53828964e80Sdhartmei 		printf("any ");
53928964e80Sdhartmei 	printf("to ");
540032e40b7Sdhartmei 	if (!PF_AZERO(&r->daddr.addr, r->af) || !PF_AZERO(&r->dmask, r->af)) {
541e7bd5eebSdhartmei 		if (r->dnot)
54214a9b182Skjell 			printf("! ");
54330620b12Sfrantzen 		print_addr(&r->daddr, &r->dmask, r->af);
54428964e80Sdhartmei 		printf(" ");
54528964e80Sdhartmei 	} else
54628964e80Sdhartmei 		printf("any ");
54780edb1f0Sdhartmei 	if (r->dport) {
548cb07131dSkjell 		printf("port %u", ntohs(r->dport));
549cb07131dSkjell 		if (r->opts & PF_DPORT_RANGE)
550cb07131dSkjell 			printf(":%u", ntohs(r->dport2));
55180edb1f0Sdhartmei 	}
552f27db9bcSdhartmei 	if (!r->no) {
553cb07131dSkjell 		printf(" -> ");
55430620b12Sfrantzen 		print_addr(&r->raddr, NULL, r->af);
55528964e80Sdhartmei 		printf(" ");
55680edb1f0Sdhartmei 		if (r->rport) {
55714a9b182Skjell 			printf("port %u", ntohs(r->rport));
558cb07131dSkjell 			if (r->opts & PF_RPORT_RANGE)
559cb07131dSkjell 				printf(":*");
56080edb1f0Sdhartmei 		}
561f27db9bcSdhartmei 	}
56214a9b182Skjell 	printf("\n");
56314a9b182Skjell }
56414a9b182Skjell 
565bca2bf17Sdhartmei char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
566bca2bf17Sdhartmei char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
56799a73934Sderaadt 
56814a9b182Skjell void
56981a15e5dSderaadt print_status(struct pf_status *s)
57014a9b182Skjell {
57181a15e5dSderaadt 
57299a73934Sderaadt 	time_t t = time(NULL);
57399a73934Sderaadt 	int i;
57499a73934Sderaadt 
575ae58c8acSdhartmei 	printf("Status: %s  Time: %u  Since: %u  Debug: ",
5767f08579dSkjell 	    s->running ? "Enabled" : "Disabled",
5777f08579dSkjell 	    t, s->since);
578ae58c8acSdhartmei 	switch (s->debug) {
579ae58c8acSdhartmei 		case 0:
580ae58c8acSdhartmei 			printf("None");
581ae58c8acSdhartmei 			break;
582ae58c8acSdhartmei 		case 1:
583ae58c8acSdhartmei 			printf("Urgent");
584ae58c8acSdhartmei 			break;
585ae58c8acSdhartmei 		case 2:
586ae58c8acSdhartmei 			printf("Misc");
587ae58c8acSdhartmei 			break;
588ae58c8acSdhartmei 	}
58930620b12Sfrantzen 	printf("\nBytes In IPv4: %-10llu  Bytes Out: %-10llu\n",
59030620b12Sfrantzen 	    s->bcounters[0][PF_IN], s->bcounters[0][PF_OUT]);
59130620b12Sfrantzen 	printf("         IPv6: %-10llu  Bytes Out: %-10llu\n",
59230620b12Sfrantzen 	    s->bcounters[1][PF_IN], s->bcounters[1][PF_OUT]);
59330620b12Sfrantzen 	printf("Inbound Packets IPv4:  Passed: %-10llu  Dropped: %-10llu\n",
59430620b12Sfrantzen 	    s->pcounters[0][PF_IN][PF_PASS],
59530620b12Sfrantzen 	    s->pcounters[0][PF_IN][PF_DROP]);
59630620b12Sfrantzen 	printf("                IPv6:  Passed: %-10llu  Dropped: %-10llu\n",
59730620b12Sfrantzen 	    s->pcounters[1][PF_IN][PF_PASS],
59830620b12Sfrantzen 	    s->pcounters[1][PF_IN][PF_DROP]);
59930620b12Sfrantzen 	printf("Outbound Packets IPv4: Passed: %-10llu  Dropped: %-10llu\n",
60030620b12Sfrantzen 	    s->pcounters[0][PF_OUT][PF_PASS],
60130620b12Sfrantzen 	    s->pcounters[0][PF_OUT][PF_DROP]);
60230620b12Sfrantzen 	printf("                 IPv6: Passed: %-10llu  Dropped: %-10llu\n",
60330620b12Sfrantzen 	    s->pcounters[1][PF_OUT][PF_PASS],
60430620b12Sfrantzen 	    s->pcounters[1][PF_OUT][PF_DROP]);
60584976600Sderaadt 	printf("States: %u\n", s->states);
60684976600Sderaadt 	printf("pf Counters\n");
607bca2bf17Sdhartmei 	for (i = 0; i < FCNT_MAX; i++)
608184bf464Sderaadt 		printf("%-25s %-8lld\n", pf_fcounters[i],
60984976600Sderaadt 		    s->fcounters[i]);
61099a73934Sderaadt 	printf("Counters\n");
61199a73934Sderaadt 	for (i = 0; i < PFRES_MAX; i++)
612184bf464Sderaadt 		printf("%-25s %-8lld\n", pf_reasons[i],
61399a73934Sderaadt 		    s->counters[i]);
61414a9b182Skjell }
61514a9b182Skjell 
61614a9b182Skjell void
617fdd4db37Sdhartmei print_state(struct pf_state *s, int opts)
61814a9b182Skjell {
6196d5ce0fbSderaadt 	struct pf_state_peer *src, *dst;
62080edb1f0Sdhartmei 	struct protoent *p;
62114a9b182Skjell 	u_int8_t hrs, min, sec;
622252d784aSderaadt 
62314a9b182Skjell 	if (s->direction == PF_OUT) {
62414a9b182Skjell 		src = &s->src;
62514a9b182Skjell 		dst = &s->dst;
62614a9b182Skjell 	} else {
62714a9b182Skjell 		src = &s->dst;
62814a9b182Skjell 		dst = &s->src;
62914a9b182Skjell 	}
63080edb1f0Sdhartmei 	if ((p = getprotobynumber(s->proto)) != NULL)
63180edb1f0Sdhartmei 		printf("%s ", p->p_name);
63280edb1f0Sdhartmei 	else
63380edb1f0Sdhartmei 		printf("%u ", s->proto);
63430620b12Sfrantzen 	if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) ||
63530620b12Sfrantzen 	    (s->lan.port != s->gwy.port)) {
6360eed2997Sdhartmei 		print_host(&s->lan, s->af, opts);
63714a9b182Skjell 		if (s->direction == PF_OUT)
63814a9b182Skjell 			printf(" -> ");
63914a9b182Skjell 		else
64014a9b182Skjell 			printf(" <- ");
64114a9b182Skjell 	}
6420eed2997Sdhartmei 	print_host(&s->gwy, s->af, opts);
64314a9b182Skjell 	if (s->direction == PF_OUT)
64414a9b182Skjell 		printf(" -> ");
64514a9b182Skjell 	else
64614a9b182Skjell 		printf(" <- ");
6470eed2997Sdhartmei 	print_host(&s->ext, s->af, opts);
64814a9b182Skjell 
649b96c47abSfrantzen 	printf("    ");
65014a9b182Skjell 	if (s->proto == IPPROTO_TCP) {
651b96c47abSfrantzen 		if (src->state <= TCPS_TIME_WAIT &&
652b96c47abSfrantzen 		    dst->state <= TCPS_TIME_WAIT) {
653b96c47abSfrantzen 			printf("   %s:%s\n", tcpstates[src->state],
65455507ad0Sfrantzen 			    tcpstates[dst->state]);
655b96c47abSfrantzen 		} else {
656b96c47abSfrantzen 			printf("   <BAD STATE LEVELS>\n");
657b96c47abSfrantzen 		}
658fdd4db37Sdhartmei 		if (opts & PF_OPT_VERBOSE) {
659b96c47abSfrantzen 			printf("   ");
66014a9b182Skjell 			print_seq(src);
66114a9b182Skjell 			printf("  ");
66214a9b182Skjell 			print_seq(dst);
66314a9b182Skjell 			printf("\n");
664fdd4db37Sdhartmei 		}
66555507ad0Sfrantzen 	} else {
666b96c47abSfrantzen 		printf("   %u:%u\n", src->state, dst->state);
66714a9b182Skjell 	}
66814a9b182Skjell 
669fdd4db37Sdhartmei 	if (opts & PF_OPT_VERBOSE) {
67014a9b182Skjell 		sec = s->creation % 60;
67114a9b182Skjell 		s->creation /= 60;
67214a9b182Skjell 		min = s->creation % 60;
67314a9b182Skjell 		s->creation /= 60;
67414a9b182Skjell 		hrs = s->creation;
67555507ad0Sfrantzen 		printf("   age %.2u:%.2u:%.2u", hrs, min, sec);
67614a9b182Skjell 		sec = s->expire % 60;
67714a9b182Skjell 		s->expire /= 60;
67814a9b182Skjell 		min = s->expire % 60;
67914a9b182Skjell 		s->expire /= 60;
68014a9b182Skjell 		hrs = s->expire;
68114a9b182Skjell 		printf(", expires in %.2u:%.2u:%.2u", hrs, min, sec);
682ab06fc45Sdhartmei 		printf(", %u pkts, %u bytes", s->packets, s->bytes);
683ab06fc45Sdhartmei 		if (s->rule.nr != USHRT_MAX)
684ab06fc45Sdhartmei 			printf(", rule %u", s->rule.nr);
685ab06fc45Sdhartmei 		printf("\n");
68614a9b182Skjell 	}
687fdd4db37Sdhartmei }
68814a9b182Skjell 
68914a9b182Skjell void
69081a15e5dSderaadt print_rule(struct pf_rule *r)
69114a9b182Skjell {
69278baf774Sdhartmei 	printf("@%d ", r->nr);
6938418a02fSprovos 	if (r->action == PF_PASS)
69414a9b182Skjell 		printf("pass ");
695b996d042Sdhartmei 	else if (r->action == PF_DROP) {
69614a9b182Skjell 		printf("block ");
69767d2a440Sprovos 		if (r->rule_flag & PFRULE_RETURNRST)
69814a9b182Skjell 			printf("return-rst ");
699b996d042Sdhartmei 		else if (r->return_icmp) {
700b996d042Sdhartmei 			struct icmpcodeent *ic;
701b996d042Sdhartmei 
702d14c53d7Swilfried 			if (r->af != AF_INET6)
703b996d042Sdhartmei 				printf("return-icmp");
704d14c53d7Swilfried 			else
705d14c53d7Swilfried 				printf("return-icmp6");
706b996d042Sdhartmei 			ic = geticmpcodebynumber(r->return_icmp >> 8,
707d14c53d7Swilfried 			    r->return_icmp & 255, r->af);
708d14c53d7Swilfried 
709d14c53d7Swilfried 			if (ic == NULL)
710d14c53d7Swilfried 				printf("(%u) ", r->return_icmp & 255);
7110eed2997Sdhartmei 			else if ((r->af != AF_INET6 && ic->code !=
7120eed2997Sdhartmei 			    ICMP_UNREACH_PORT) ||
7130eed2997Sdhartmei 			    (r->af == AF_INET6 && ic->code !=
7140eed2997Sdhartmei 			    ICMP6_DST_UNREACH_NOPORT))
715b996d042Sdhartmei 				printf("(%s) ", ic->name);
716b996d042Sdhartmei 			else
717b996d042Sdhartmei 				printf(" ");
718b996d042Sdhartmei 		}
719b996d042Sdhartmei 	} else
720b996d042Sdhartmei 		printf("scrub ");
72114a9b182Skjell 	if (r->direction == 0)
72214a9b182Skjell 		printf("in ");
72314a9b182Skjell 	else
72414a9b182Skjell 		printf("out ");
7257242ce7aSdhartmei 	if (r->log == 1)
72614a9b182Skjell 		printf("log ");
7277242ce7aSdhartmei 	else if (r->log == 2)
7287242ce7aSdhartmei 		printf("log-all ");
72914a9b182Skjell 	if (r->quick)
73014a9b182Skjell 		printf("quick ");
73114a9b182Skjell 	if (r->ifname[0])
73214a9b182Skjell 		printf("on %s ", r->ifname);
733cb3a4e31Sjasoni 	if (r->rt) {
734cb3a4e31Sjasoni 		if (r->rt == PF_ROUTETO)
735cb3a4e31Sjasoni 			printf("route-to ");
736cb3a4e31Sjasoni 		else if (r->rt == PF_DUPTO)
737cb3a4e31Sjasoni 			printf("dup-to ");
738cb3a4e31Sjasoni 		else if (r->rt == PF_FASTROUTE)
739cb3a4e31Sjasoni 			printf("fastroute");
740cb3a4e31Sjasoni 		if (r->rt_ifname[0])
741cb3a4e31Sjasoni 			printf("%s", r->rt_ifname);
742cb3a4e31Sjasoni 		if (r->af && !PF_AZERO(&r->rt_addr, r->af)) {
743032e40b7Sdhartmei 			struct pf_addr_wrap aw;
744032e40b7Sdhartmei 
745032e40b7Sdhartmei 			aw.addr = r->rt_addr;
746032e40b7Sdhartmei 			aw.addr_dyn = NULL;
747cb3a4e31Sjasoni 			printf(":");
748032e40b7Sdhartmei 			print_addr(&aw, NULL, r->af);
749cb3a4e31Sjasoni 		}
750cb3a4e31Sjasoni 		printf(" ");
751cb3a4e31Sjasoni 	}
75230620b12Sfrantzen 	if (r->af) {
75330620b12Sfrantzen 		if (r->af == AF_INET)
75430620b12Sfrantzen 			printf("inet ");
75530620b12Sfrantzen 		else
75630620b12Sfrantzen 			printf("inet6 ");
75730620b12Sfrantzen 	}
75814a9b182Skjell 	if (r->proto) {
75914a9b182Skjell 		struct protoent *p = getprotobynumber(r->proto);
76014a9b182Skjell 		if (p != NULL)
76114a9b182Skjell 			printf("proto %s ", p->p_name);
76214a9b182Skjell 		else
76314a9b182Skjell 			printf("proto %u ", r->proto);
76414a9b182Skjell 	}
765032e40b7Sdhartmei 	if (PF_AZERO(&r->src.addr.addr, AF_INET6) &&
76630620b12Sfrantzen 	    PF_AZERO(&r->src.mask, AF_INET6) &&
7673cb9a5b2Smickey 	    !r->src.noroute && !r->dst.noroute &&
768032e40b7Sdhartmei 	    !r->src.port_op && PF_AZERO(&r->dst.addr.addr, AF_INET6) &&
76930620b12Sfrantzen 	    PF_AZERO(&r->dst.mask, AF_INET6) && !r->dst.port_op)
77014a9b182Skjell 		printf("all ");
77114a9b182Skjell 	else {
77214a9b182Skjell 		printf("from ");
7733cb9a5b2Smickey 		if (r->src.noroute)
7743cb9a5b2Smickey 			printf("no-route ");
775032e40b7Sdhartmei 		else if (PF_AZERO(&r->src.addr.addr, AF_INET6) &&
77630620b12Sfrantzen 		    PF_AZERO(&r->src.mask, AF_INET6))
77714a9b182Skjell 			printf("any ");
77814a9b182Skjell 		else {
77914a9b182Skjell 			if (r->src.not)
78014a9b182Skjell 				printf("! ");
78130620b12Sfrantzen 			print_addr(&r->src.addr, &r->src.mask, r->af);
78214a9b182Skjell 			printf(" ");
78314a9b182Skjell 		}
78414a9b182Skjell 		if (r->src.port_op)
78514a9b182Skjell 			print_port(r->src.port_op, r->src.port[0],
7865df8e51cSsmart 			    r->src.port[1],
7875df8e51cSsmart 			    r->proto == IPPROTO_TCP ? "tcp" : "udp");
78814a9b182Skjell 
78914a9b182Skjell 		printf("to ");
7903cb9a5b2Smickey 		if (r->dst.noroute)
7913cb9a5b2Smickey 			printf("no-route ");
792032e40b7Sdhartmei 		else if (PF_AZERO(&r->dst.addr.addr, AF_INET6) &&
79330620b12Sfrantzen 		    PF_AZERO(&r->dst.mask, AF_INET6))
79414a9b182Skjell 			printf("any ");
79514a9b182Skjell 		else {
79614a9b182Skjell 			if (r->dst.not)
79714a9b182Skjell 				printf("! ");
79830620b12Sfrantzen 			print_addr(&r->dst.addr, &r->dst.mask, r->af);
79914a9b182Skjell 			printf(" ");
80014a9b182Skjell 		}
80114a9b182Skjell 		if (r->dst.port_op)
80214a9b182Skjell 			print_port(r->dst.port_op, r->dst.port[0],
8035df8e51cSsmart 			    r->dst.port[1],
8045df8e51cSsmart 			    r->proto == IPPROTO_TCP ? "tcp" : "udp");
80514a9b182Skjell 	}
806*5d9ac2dcSdhartmei 	if (r->ruid.op) {
807*5d9ac2dcSdhartmei 		print_uid(r->ruid.op, r->ruid.uid[0], r->ruid.uid[1], "ruid");
808*5d9ac2dcSdhartmei 	}
809*5d9ac2dcSdhartmei 	if (r->euid.op) {
810*5d9ac2dcSdhartmei 		print_uid(r->euid.op, r->euid.uid[0], r->euid.uid[1], "euid");
811*5d9ac2dcSdhartmei 	}
81214a9b182Skjell 	if (r->flags || r->flagset) {
81314a9b182Skjell 		printf("flags ");
81414a9b182Skjell 		print_flags(r->flags);
81514a9b182Skjell 		printf("/");
81614a9b182Skjell 		print_flags(r->flagset);
81714a9b182Skjell 		printf(" ");
81814a9b182Skjell 	}
819082ebc44Swilfried 	if (r->type) {
820082ebc44Swilfried 		struct icmptypeent *p;
821082ebc44Swilfried 
822d14c53d7Swilfried 		p = geticmptypebynumber(r->type-1, r->af);
823d14c53d7Swilfried 		if (r->af != AF_INET6)
824d14c53d7Swilfried 			printf("icmp-type");
825082ebc44Swilfried 		else
826d14c53d7Swilfried 			printf("ipv6-icmp-type");
827d14c53d7Swilfried 		if (p != NULL)
828d14c53d7Swilfried 			printf(" %s ", p->name);
829d14c53d7Swilfried 		else
830d14c53d7Swilfried 			printf(" %u ", r->type-1);
831082ebc44Swilfried 		if (r->code) {
832082ebc44Swilfried 			struct icmpcodeent *p;
833082ebc44Swilfried 
834d14c53d7Swilfried 			p = geticmpcodebynumber(r->type-1, r->code-1, r->af);
835082ebc44Swilfried 			if (p != NULL)
836082ebc44Swilfried 				printf("code %s ", p->name);
837082ebc44Swilfried 			else
83814a9b182Skjell 				printf("code %u ", r->code-1);
839082ebc44Swilfried 		}
840082ebc44Swilfried 	}
841b96c47abSfrantzen 	if (r->keep_state == PF_STATE_NORMAL)
84214a9b182Skjell 		printf("keep state ");
843b96c47abSfrantzen 	else if (r->keep_state == PF_STATE_MODULATE)
844b96c47abSfrantzen 		printf("modulate state ");
8456673dee2Sdhartmei 	if (r->rule_flag & PFRULE_FRAGMENT)
8466673dee2Sdhartmei 		printf("fragment ");
84767d2a440Sprovos 	if (r->rule_flag & PFRULE_NODF)
84867d2a440Sprovos 		printf("no-df ");
849e258bfd4Sprovos 	if (r->min_ttl)
85034c76dcbSprovos 		printf("min-ttl %d ", r->min_ttl);
851f48d62b3Sdhartmei 	if (r->allow_opts)
852f48d62b3Sdhartmei 		printf("allow-opts ");
853455ef0c1Sdhartmei 	if (r->label[0])
854455ef0c1Sdhartmei 		printf("label %s", r->label);
85567d2a440Sprovos 
85614a9b182Skjell 	printf("\n");
85714a9b182Skjell }
85814a9b182Skjell 
8591f8f21bdSmillert int
860ff352a37Smarkus parse_flags(char *s)
86114a9b182Skjell {
862ff352a37Smarkus 	char *p, *q;
86314a9b182Skjell 	u_int8_t f = 0;
86481a15e5dSderaadt 
865ff352a37Smarkus 	for (p = s; *p; p++) {
866ff352a37Smarkus 		if ((q = strchr(tcpflags, *p)) == NULL)
867ff352a37Smarkus 			return -1;
868ff352a37Smarkus 		else
869ff352a37Smarkus 			f |= 1 << (q - tcpflags);
87014a9b182Skjell 	}
871dbfb98deSprovos 	return (f ? f : 63);
87214a9b182Skjell }
8730eed2997Sdhartmei 
8740eed2997Sdhartmei struct hostent *
8750eed2997Sdhartmei getpfhostname(const char *addr_str)
8760eed2997Sdhartmei {
8771feb912bSdhartmei 	in_addr_t		 addr_num;
8780eed2997Sdhartmei 	struct hostent		*hp;
8790eed2997Sdhartmei 	static struct hostent	 myhp;
8800eed2997Sdhartmei 
8810eed2997Sdhartmei 	addr_num = inet_addr(addr_str);
8820eed2997Sdhartmei 	if (addr_num == INADDR_NONE) {
8830eed2997Sdhartmei 		myhp.h_name = (char *)addr_str;
8840eed2997Sdhartmei 		hp = &myhp;
8850eed2997Sdhartmei 		return (hp);
8860eed2997Sdhartmei 	}
8870eed2997Sdhartmei 	hp = gethostbyaddr((char *)&addr_num, sizeof(addr_num), AF_INET);
8880eed2997Sdhartmei 	if (hp == NULL) {
8890eed2997Sdhartmei 		myhp.h_name = (char *)addr_str;
8900eed2997Sdhartmei 		hp = &myhp;
8910eed2997Sdhartmei 	}
8920eed2997Sdhartmei 	return (hp);
8930eed2997Sdhartmei }
894