xref: /openbsd/sbin/pfctl/pfctl_parser.c (revision c16ab608)
1*c16ab608Sdhartmei /*	$OpenBSD: pfctl_parser.c,v 1.70 2002/05/12 00:54:56 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 *);
615d9ac2dcSdhartmei void		 print_op (u_int8_t, const char *, const char *);
6281a15e5dSderaadt void		 print_port (u_int8_t, u_int16_t, u_int16_t, char *);
635d9ac2dcSdhartmei void		 print_uid (u_int8_t, uid_t, uid_t, const char *);
64*c16ab608Sdhartmei void		 print_gid (u_int8_t, gid_t, gid_t, const char *);
6581a15e5dSderaadt void		 print_flags (u_int8_t);
6614a9b182Skjell 
6781a15e5dSderaadt char *tcpflags = "FSRPAU";
6814a9b182Skjell 
69082ebc44Swilfried struct icmptypeent icmp_type[] = {
70082ebc44Swilfried 	{ "echoreq",	ICMP_ECHO },
71082ebc44Swilfried 	{ "echorep",	ICMP_ECHOREPLY },
72082ebc44Swilfried 	{ "unreach",	ICMP_UNREACH },
73082ebc44Swilfried 	{ "squench",	ICMP_SOURCEQUENCH },
74082ebc44Swilfried 	{ "redir",	ICMP_REDIRECT },
75082ebc44Swilfried 	{ "althost",	ICMP_ALTHOSTADDR },
76082ebc44Swilfried 	{ "routeradv",	ICMP_ROUTERADVERT },
77082ebc44Swilfried 	{ "routersol",	ICMP_ROUTERSOLICIT },
78082ebc44Swilfried 	{ "timex",	ICMP_TIMXCEED },
79082ebc44Swilfried 	{ "paramprob",	ICMP_PARAMPROB },
80082ebc44Swilfried 	{ "timereq",	ICMP_TSTAMP },
81082ebc44Swilfried 	{ "timerep",	ICMP_TSTAMPREPLY },
82082ebc44Swilfried 	{ "inforeq",	ICMP_IREQ },
83082ebc44Swilfried 	{ "inforep",	ICMP_IREQREPLY },
84082ebc44Swilfried 	{ "maskreq",	ICMP_MASKREQ },
8502cbcc9eSwilfried 	{ "maskrep",	ICMP_MASKREPLY },
8602cbcc9eSwilfried 	{ "trace",	ICMP_TRACEROUTE },
8702cbcc9eSwilfried 	{ "dataconv",	ICMP_DATACONVERR },
8802cbcc9eSwilfried 	{ "mobredir",	ICMP_MOBILE_REDIRECT },
8902cbcc9eSwilfried 	{ "ipv6-where",	ICMP_IPV6_WHEREAREYOU },
9002cbcc9eSwilfried 	{ "ipv6-here",	ICMP_IPV6_IAMHERE },
9102cbcc9eSwilfried 	{ "mobregreq",	ICMP_MOBILE_REGREQUEST },
9202cbcc9eSwilfried 	{ "mobregrep",	ICMP_MOBILE_REGREPLY },
9302cbcc9eSwilfried 	{ "skip",	ICMP_SKIP },
9402cbcc9eSwilfried 	{ "photuris",	ICMP_PHOTURIS }
9502cbcc9eSwilfried 
96082ebc44Swilfried };
97082ebc44Swilfried 
9830620b12Sfrantzen struct icmptypeent icmp6_type[] = {
9930620b12Sfrantzen 	{ "unreach",	ICMP6_DST_UNREACH },
10030620b12Sfrantzen 	{ "toobig",	ICMP6_PACKET_TOO_BIG },
10130620b12Sfrantzen 	{ "timex",	ICMP6_TIME_EXCEEDED },
10230620b12Sfrantzen 	{ "paramprob",	ICMP6_PARAM_PROB },
10330620b12Sfrantzen 	{ "echoreq",	ICMP6_ECHO_REQUEST },
10430620b12Sfrantzen 	{ "echorep",	ICMP6_ECHO_REPLY },
10530620b12Sfrantzen 	{ "groupqry",	ICMP6_MEMBERSHIP_QUERY },
10630620b12Sfrantzen 	{ "listqry",	MLD6_LISTENER_QUERY },
10730620b12Sfrantzen 	{ "grouprep",	ICMP6_MEMBERSHIP_REPORT },
10830620b12Sfrantzen 	{ "listenrep",	MLD6_LISTENER_REPORT },
10930620b12Sfrantzen 	{ "groupterm",	ICMP6_MEMBERSHIP_REDUCTION },
11030620b12Sfrantzen 	{ "listendone", MLD6_LISTENER_DONE },
11130620b12Sfrantzen 	{ "routersol",	ND_ROUTER_SOLICIT },
11230620b12Sfrantzen 	{ "routeradv",	ND_ROUTER_ADVERT },
11330620b12Sfrantzen 	{ "neighbrsol", ND_NEIGHBOR_SOLICIT },
11430620b12Sfrantzen 	{ "neighbradv", ND_NEIGHBOR_ADVERT },
11530620b12Sfrantzen 	{ "redir",	ND_REDIRECT },
11630620b12Sfrantzen 	{ "routrrenum", ICMP6_ROUTER_RENUMBERING },
11730620b12Sfrantzen 	{ "wrureq",	ICMP6_WRUREQUEST },
11830620b12Sfrantzen 	{ "wrurep",	ICMP6_WRUREPLY },
11930620b12Sfrantzen 	{ "fqdnreq",	ICMP6_FQDN_QUERY },
12030620b12Sfrantzen 	{ "fqdnrep",	ICMP6_FQDN_REPLY },
12130620b12Sfrantzen 	{ "niqry",	ICMP6_NI_QUERY },
12230620b12Sfrantzen 	{ "nirep",	ICMP6_NI_REPLY },
12330620b12Sfrantzen 	{ "mtraceresp",	MLD6_MTRACE_RESP },
12430620b12Sfrantzen 	{ "mtrace",	MLD6_MTRACE }
12530620b12Sfrantzen };
12630620b12Sfrantzen 
127082ebc44Swilfried struct icmpcodeent icmp_code[] = {
128082ebc44Swilfried 	{ "net-unr",		ICMP_UNREACH,	ICMP_UNREACH_NET },
129082ebc44Swilfried 	{ "host-unr",		ICMP_UNREACH,	ICMP_UNREACH_HOST },
130082ebc44Swilfried 	{ "proto-unr",		ICMP_UNREACH,	ICMP_UNREACH_PROTOCOL },
131082ebc44Swilfried 	{ "port-unr",		ICMP_UNREACH,	ICMP_UNREACH_PORT },
132082ebc44Swilfried 	{ "needfrag",		ICMP_UNREACH,	ICMP_UNREACH_NEEDFRAG },
133082ebc44Swilfried 	{ "srcfail",		ICMP_UNREACH,	ICMP_UNREACH_SRCFAIL },
134082ebc44Swilfried 	{ "net-unk",		ICMP_UNREACH,	ICMP_UNREACH_NET_UNKNOWN },
135082ebc44Swilfried 	{ "host-unk",		ICMP_UNREACH,	ICMP_UNREACH_HOST_UNKNOWN },
136082ebc44Swilfried 	{ "isolate",		ICMP_UNREACH,	ICMP_UNREACH_ISOLATED },
137082ebc44Swilfried 	{ "net-prohib",		ICMP_UNREACH,	ICMP_UNREACH_NET_PROHIB },
138082ebc44Swilfried 	{ "host-prohib",	ICMP_UNREACH,	ICMP_UNREACH_HOST_PROHIB },
139082ebc44Swilfried 	{ "net-tos",		ICMP_UNREACH,	ICMP_UNREACH_TOSNET },
140082ebc44Swilfried 	{ "host-tos",		ICMP_UNREACH,	ICMP_UNREACH_TOSHOST },
141082ebc44Swilfried 	{ "filter-prohib",	ICMP_UNREACH,	ICMP_UNREACH_FILTER_PROHIB },
142082ebc44Swilfried 	{ "host-preced",	ICMP_UNREACH,	ICMP_UNREACH_HOST_PRECEDENCE },
143082ebc44Swilfried 	{ "cutoff-preced",	ICMP_UNREACH,	ICMP_UNREACH_PRECEDENCE_CUTOFF },
144082ebc44Swilfried 	{ "redir-net",		ICMP_REDIRECT,	ICMP_REDIRECT_NET },
145082ebc44Swilfried 	{ "redir-host",		ICMP_REDIRECT,	ICMP_REDIRECT_HOST },
146082ebc44Swilfried 	{ "redir-tos-net",	ICMP_REDIRECT,	ICMP_REDIRECT_TOSNET },
147082ebc44Swilfried 	{ "redir-tos-host",	ICMP_REDIRECT,	ICMP_REDIRECT_TOSHOST },
14802cbcc9eSwilfried 	{ "normal-adv",		ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL },
14902cbcc9eSwilfried 	{ "common-adv",		ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON },
150082ebc44Swilfried 	{ "transit",		ICMP_TIMXCEED,	ICMP_TIMXCEED_INTRANS },
151082ebc44Swilfried 	{ "reassemb",		ICMP_TIMXCEED,	ICMP_TIMXCEED_REASS },
152082ebc44Swilfried 	{ "badhead",		ICMP_PARAMPROB,	ICMP_PARAMPROB_ERRATPTR },
153082ebc44Swilfried 	{ "optmiss",		ICMP_PARAMPROB,	ICMP_PARAMPROB_OPTABSENT },
15402cbcc9eSwilfried 	{ "badlen",		ICMP_PARAMPROB,	ICMP_PARAMPROB_LENGTH },
15502cbcc9eSwilfried 	{ "unknown-ind",	ICMP_PHOTURIS,	ICMP_PHOTURIS_UNKNOWN_INDEX },
15602cbcc9eSwilfried 	{ "auth-fail",		ICMP_PHOTURIS,	ICMP_PHOTURIS_AUTH_FAILED },
15702cbcc9eSwilfried 	{ "decrypt-fail",	ICMP_PHOTURIS,	ICMP_PHOTURIS_DECRYPT_FAILED }
158082ebc44Swilfried };
159082ebc44Swilfried 
16030620b12Sfrantzen struct icmpcodeent icmp6_code[] = {
1611d32ee3bSdhartmei 	{ "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN },
1621d32ee3bSdhartmei 	{ "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE },
16330620b12Sfrantzen 	{ "notnbr-unr",	ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR },
16430620b12Sfrantzen 	{ "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE },
16530620b12Sfrantzen 	{ "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR },
16630620b12Sfrantzen 	{ "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT },
16730620b12Sfrantzen 	{ "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT },
16830620b12Sfrantzen 	{ "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY },
16930620b12Sfrantzen 	{ "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER },
17030620b12Sfrantzen 	{ "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER },
17130620b12Sfrantzen 	{ "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK },
17230620b12Sfrantzen 	{ "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER }
17330620b12Sfrantzen };
17430620b12Sfrantzen 
17530620b12Sfrantzen 
176082ebc44Swilfried struct icmptypeent *
177d14c53d7Swilfried geticmptypebynumber(u_int8_t type, u_int8_t af)
178082ebc44Swilfried {
179d77ee430Sdhartmei 	unsigned i;
180082ebc44Swilfried 
181d14c53d7Swilfried 	if (af != AF_INET6) {
182082ebc44Swilfried 		for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) {
183082ebc44Swilfried 			if(type == icmp_type[i].type)
184082ebc44Swilfried 				return (&icmp_type[i]);
185082ebc44Swilfried 		}
18630620b12Sfrantzen 	} else {
18730620b12Sfrantzen 		for(i=0; i < (sizeof (icmp6_type) /
18830620b12Sfrantzen 		    sizeof(icmp6_type[0])); i++) {
18930620b12Sfrantzen 			if(type == icmp6_type[i].type)
19030620b12Sfrantzen 				 return (&icmp6_type[i]);
19130620b12Sfrantzen 		}
19230620b12Sfrantzen 	}
19330620b12Sfrantzen 	return (NULL);
194082ebc44Swilfried }
195082ebc44Swilfried 
196082ebc44Swilfried struct icmptypeent *
197d14c53d7Swilfried geticmptypebyname(char *w, u_int8_t af)
198082ebc44Swilfried {
199d77ee430Sdhartmei 	unsigned i;
200082ebc44Swilfried 
201d14c53d7Swilfried 	if (af != AF_INET6) {
202082ebc44Swilfried 		for(i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) {
203082ebc44Swilfried 			if(!strcmp(w, icmp_type[i].name))
204082ebc44Swilfried 				return (&icmp_type[i]);
205082ebc44Swilfried 		}
20630620b12Sfrantzen 	} else {
20730620b12Sfrantzen 		for(i=0; i < (sizeof (icmp6_type) /
20830620b12Sfrantzen 		    sizeof(icmp6_type[0])); i++) {
20930620b12Sfrantzen 			if(!strcmp(w, icmp6_type[i].name))
21030620b12Sfrantzen 				return (&icmp6_type[i]);
21130620b12Sfrantzen 		}
21230620b12Sfrantzen 	}
21330620b12Sfrantzen 	return (NULL);
214082ebc44Swilfried }
215082ebc44Swilfried 
216082ebc44Swilfried struct icmpcodeent *
217d14c53d7Swilfried geticmpcodebynumber(u_int8_t type, u_int8_t code, u_int8_t af)
218082ebc44Swilfried {
219d77ee430Sdhartmei 	unsigned i;
220082ebc44Swilfried 
221d14c53d7Swilfried 	if (af != AF_INET6) {
222082ebc44Swilfried 		for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) {
22330620b12Sfrantzen 			if (type == icmp_code[i].type &&
22430620b12Sfrantzen 			    code == icmp_code[i].code)
225082ebc44Swilfried 				return (&icmp_code[i]);
226082ebc44Swilfried 		}
22730620b12Sfrantzen 	} else {
22830620b12Sfrantzen 		for(i=0; i < (sizeof (icmp6_code) /
22930620b12Sfrantzen 		   sizeof(icmp6_code[0])); i++) {
23030620b12Sfrantzen 			if (type == icmp6_code[i].type &&
23130620b12Sfrantzen 			    code == icmp6_code[i].code)
23230620b12Sfrantzen 				return (&icmp6_code[i]);
23330620b12Sfrantzen 		}
23430620b12Sfrantzen 	}
23530620b12Sfrantzen 	return (NULL);
236082ebc44Swilfried }
237082ebc44Swilfried 
238082ebc44Swilfried struct icmpcodeent *
239d14c53d7Swilfried geticmpcodebyname(u_long type, char *w, u_int8_t af)
240082ebc44Swilfried {
241d77ee430Sdhartmei 	unsigned i;
242082ebc44Swilfried 
243d14c53d7Swilfried 	if (af != AF_INET6) {
244082ebc44Swilfried 		for(i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) {
24530620b12Sfrantzen 			if (type == icmp_code[i].type &&
24630620b12Sfrantzen 			    !strcmp(w, icmp_code[i].name))
247082ebc44Swilfried 				return (&icmp_code[i]);
248082ebc44Swilfried 		}
24930620b12Sfrantzen 	} else {
25030620b12Sfrantzen 		for(i=0; i < (sizeof (icmp6_code) /
25130620b12Sfrantzen 		    sizeof(icmp6_code[0])); i++) {
25230620b12Sfrantzen 			if (type == icmp6_code[i].type &&
25330620b12Sfrantzen 			    !strcmp(w, icmp6_code[i].name))
25430620b12Sfrantzen 				return (&icmp6_code[i]);
25530620b12Sfrantzen 		}
25630620b12Sfrantzen 	}
25730620b12Sfrantzen 	return (NULL);
25830620b12Sfrantzen }
25930620b12Sfrantzen 
26030620b12Sfrantzen int
261ece4c078Smpech unmask(struct pf_addr *m, u_int8_t af)
26230620b12Sfrantzen {
26330620b12Sfrantzen 	int i = 31, j = 0, b = 0, msize;
26430620b12Sfrantzen 	u_int32_t tmp;
26530620b12Sfrantzen 
26630620b12Sfrantzen 	if (af == AF_INET)
26730620b12Sfrantzen 		msize = 1;
26830620b12Sfrantzen 	else
26930620b12Sfrantzen 		msize = 4;
27030620b12Sfrantzen 	while (j < msize && m->addr32[j] == 0xffffffff) {
27130620b12Sfrantzen 			b += 32;
27230620b12Sfrantzen 			j++;
27330620b12Sfrantzen 	}
27430620b12Sfrantzen 	if (j < msize) {
27530620b12Sfrantzen 		tmp = ntohl(m->addr32[j]);
27630620b12Sfrantzen 		for (i = 31; tmp & (1 << i); --i)
27730620b12Sfrantzen 			b++;
27830620b12Sfrantzen 	}
27930620b12Sfrantzen 	return (b);
280082ebc44Swilfried }
281082ebc44Swilfried 
28281a15e5dSderaadt void
283032e40b7Sdhartmei print_addr(struct pf_addr_wrap *addr, struct pf_addr *mask, u_int8_t af)
28414a9b182Skjell {
28530620b12Sfrantzen 	char buf[48];
28630620b12Sfrantzen 
287032e40b7Sdhartmei 	if (addr->addr_dyn != NULL)
288032e40b7Sdhartmei 		printf("(%s)", addr->addr.pfa.ifname);
289032e40b7Sdhartmei 	else {
290032e40b7Sdhartmei 		if (inet_ntop(af, &addr->addr, buf, sizeof(buf)) == NULL)
291ded7153fSdhartmei 			printf("?");
292ded7153fSdhartmei 		else
293ded7153fSdhartmei 			printf("%s", buf);
294032e40b7Sdhartmei 	}
29530620b12Sfrantzen 	if (mask != NULL) {
296032e40b7Sdhartmei 		int bits = unmask(mask, af);
297032e40b7Sdhartmei 
298032e40b7Sdhartmei 		if (bits != (af == AF_INET ? 32 : 128))
299032e40b7Sdhartmei 			printf("/%u", bits);
30030620b12Sfrantzen 	}
30114a9b182Skjell }
30214a9b182Skjell 
30381a15e5dSderaadt void
3040eed2997Sdhartmei print_name(struct pf_addr *addr, struct pf_addr *mask, int af)
3050eed2997Sdhartmei {
3060eed2997Sdhartmei 	char buf[48];
3070eed2997Sdhartmei 	struct hostent *hp;
3080eed2997Sdhartmei 
309ded7153fSdhartmei 	if (inet_ntop(af, addr, buf, sizeof(buf)) == NULL)
310ded7153fSdhartmei 		printf("?");
311ded7153fSdhartmei 	else {
312ded7153fSdhartmei 		hp = getpfhostname(buf);
3130eed2997Sdhartmei 		printf("%s", hp->h_name);
314ded7153fSdhartmei 	}
3150eed2997Sdhartmei 	if (mask != NULL) {
316032e40b7Sdhartmei 
3170eed2997Sdhartmei 		if (!PF_AZERO(mask, af))
3180eed2997Sdhartmei 			printf("/%u", unmask(mask, af));
3190eed2997Sdhartmei 	}
3200eed2997Sdhartmei }
3210eed2997Sdhartmei 
3220eed2997Sdhartmei void
3230eed2997Sdhartmei print_host(struct pf_state_host *h, u_int8_t af, int opts)
32414a9b182Skjell {
32514a9b182Skjell 	u_int16_t p = ntohs(h->port);
32681a15e5dSderaadt 
3270eed2997Sdhartmei 	if (opts & PF_OPT_USEDNS)
3280eed2997Sdhartmei 		print_name(&h->addr, NULL, af);
329032e40b7Sdhartmei 	else {
330032e40b7Sdhartmei 		struct pf_addr_wrap aw;
331032e40b7Sdhartmei 
332032e40b7Sdhartmei 		aw.addr = h->addr;
333032e40b7Sdhartmei 		aw.addr_dyn = NULL;
334032e40b7Sdhartmei 		print_addr(&aw, NULL, af);
335032e40b7Sdhartmei 	}
3360eed2997Sdhartmei 
33780edb1f0Sdhartmei 	if (p) {
33830620b12Sfrantzen 		if (af == AF_INET)
33930620b12Sfrantzen 			printf(":%u", p);
34030620b12Sfrantzen 		else
34130620b12Sfrantzen 			printf("[%u]", p);
34214a9b182Skjell 	}
34380edb1f0Sdhartmei }
34414a9b182Skjell 
34530620b12Sfrantzen 
34681a15e5dSderaadt void
3476d5ce0fbSderaadt print_seq(struct pf_state_peer *p)
34814a9b182Skjell {
349b96c47abSfrantzen 	if (p->seqdiff)
350b96c47abSfrantzen 		printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo,
351b96c47abSfrantzen 		    p->seqdiff);
352b96c47abSfrantzen 	else
35314a9b182Skjell 		printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo);
35414a9b182Skjell }
35514a9b182Skjell 
35681a15e5dSderaadt void
3575d9ac2dcSdhartmei print_op(u_int8_t op, const char *a1, const char *a2)
3585d9ac2dcSdhartmei {
3595d9ac2dcSdhartmei 	if (op == PF_OP_IRG)
3605d9ac2dcSdhartmei 		printf("%s >< %s ", a1, a2);
3615d9ac2dcSdhartmei 	else if (op == PF_OP_XRG)
3625d9ac2dcSdhartmei 		printf("%s <> %s ", a1, a2);
3635d9ac2dcSdhartmei 	else if (op == PF_OP_EQ) {
3645d9ac2dcSdhartmei 		printf("= %s ", a1);
3655d9ac2dcSdhartmei 	} else if (op == PF_OP_NE) {
3665d9ac2dcSdhartmei 		printf("!= %s ", a1);
3675d9ac2dcSdhartmei 	} else if (op == PF_OP_LT)
3685d9ac2dcSdhartmei 		printf("< %s ", a1);
3695d9ac2dcSdhartmei 	else if (op == PF_OP_LE)
3705d9ac2dcSdhartmei 		printf("<= %s ", a1);
3715d9ac2dcSdhartmei 	else if (op == PF_OP_GT)
3725d9ac2dcSdhartmei 		printf("> %s ", a1);
3735d9ac2dcSdhartmei 	else if (op == PF_OP_GE)
3745d9ac2dcSdhartmei 		printf(">= %s ", a1);
3755d9ac2dcSdhartmei }
3765d9ac2dcSdhartmei 
3775d9ac2dcSdhartmei void
37814a9b182Skjell print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto)
37914a9b182Skjell {
3805d9ac2dcSdhartmei 	char a1[5], a2[5];
38114a9b182Skjell 	struct servent *s = getservbyport(p1, proto);
38281a15e5dSderaadt 
38314a9b182Skjell 	p1 = ntohs(p1);
38414a9b182Skjell 	p2 = ntohs(p2);
3855d9ac2dcSdhartmei 	snprintf(a1, sizeof(a1), "%u", p1);
3865d9ac2dcSdhartmei 	snprintf(a2, sizeof(a2), "%u", p2);
38714a9b182Skjell 	printf("port ");
3885d9ac2dcSdhartmei 	if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE))
3895d9ac2dcSdhartmei 		print_op(op, s->s_name, a2);
39014a9b182Skjell 	else
3915d9ac2dcSdhartmei 		print_op(op, a1, a2);
3925d9ac2dcSdhartmei }
3935d9ac2dcSdhartmei 
3945d9ac2dcSdhartmei void
3955d9ac2dcSdhartmei print_uid(u_int8_t op, uid_t u1, uid_t u2, const char *t)
3965d9ac2dcSdhartmei {
3975d9ac2dcSdhartmei 	char a1[5], a2[5];
3985d9ac2dcSdhartmei 
3995d9ac2dcSdhartmei 	snprintf(a1, sizeof(a1), "%u", u1);
4005d9ac2dcSdhartmei 	snprintf(a2, sizeof(a2), "%u", u2);
4015d9ac2dcSdhartmei 	printf("%s ", t);
4025d9ac2dcSdhartmei 	if (u1 == UID_MAX && (op == PF_OP_EQ || op == PF_OP_NE))
4035d9ac2dcSdhartmei 		print_op(op, "unknown", a2);
40414a9b182Skjell 	else
4055d9ac2dcSdhartmei 		print_op(op, a1, a2);
40614a9b182Skjell }
40714a9b182Skjell 
40881a15e5dSderaadt void
409*c16ab608Sdhartmei print_gid(u_int8_t op, gid_t g1, gid_t g2, const char *t)
410*c16ab608Sdhartmei {
411*c16ab608Sdhartmei 	char a1[5], a2[5];
412*c16ab608Sdhartmei 
413*c16ab608Sdhartmei 	snprintf(a1, sizeof(a1), "%u", g1);
414*c16ab608Sdhartmei 	snprintf(a2, sizeof(a2), "%u", g2);
415*c16ab608Sdhartmei 	printf("%s ", t);
416*c16ab608Sdhartmei 	if (g1 == GID_MAX && (op == PF_OP_EQ || op == PF_OP_NE))
417*c16ab608Sdhartmei 		print_op(op, "unknown", a2);
418*c16ab608Sdhartmei 	else
419*c16ab608Sdhartmei 		print_op(op, a1, a2);
420*c16ab608Sdhartmei }
421*c16ab608Sdhartmei 
422*c16ab608Sdhartmei void
42314a9b182Skjell print_flags(u_int8_t f)
42414a9b182Skjell {
42514a9b182Skjell 	int i;
42681a15e5dSderaadt 
42714a9b182Skjell 	for (i = 0; i < 6; ++i)
42814a9b182Skjell 		if (f & (1 << i))
42914a9b182Skjell 			printf("%c", tcpflags[i]);
43014a9b182Skjell }
43114a9b182Skjell 
43214a9b182Skjell void
43381a15e5dSderaadt print_nat(struct pf_nat *n)
43414a9b182Skjell {
435f27db9bcSdhartmei 	if (n->no)
436f27db9bcSdhartmei 		printf("no ");
437f27db9bcSdhartmei 	printf("nat ");
43828964e80Sdhartmei 	if (n->ifname[0]) {
43928964e80Sdhartmei 		printf("on ");
440870b51d7Schris 		if (n->ifnot)
441870b51d7Schris 			printf("! ");
442870b51d7Schris 		printf("%s ", n->ifname);
44328964e80Sdhartmei 	}
444032e40b7Sdhartmei 	if (n->af) {
445032e40b7Sdhartmei 		if (n->af == AF_INET)
446032e40b7Sdhartmei 			printf("inet ");
447032e40b7Sdhartmei 		else
448032e40b7Sdhartmei 			printf("inet6 ");
449032e40b7Sdhartmei 	}
45080edb1f0Sdhartmei 	if (n->proto) {
45180edb1f0Sdhartmei 		struct protoent *p = getprotobynumber(n->proto);
452ab745e3bSmpech 		if (p != NULL)
45380edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
45480edb1f0Sdhartmei 		else
45580edb1f0Sdhartmei 			printf("proto %u ", n->proto);
45680edb1f0Sdhartmei 	}
45728964e80Sdhartmei 	printf("from ");
458032e40b7Sdhartmei 	if (!PF_AZERO(&n->saddr.addr, n->af) || !PF_AZERO(&n->smask, n->af)) {
45928964e80Sdhartmei 		if (n->snot)
46014a9b182Skjell 			printf("! ");
46130620b12Sfrantzen 		print_addr(&n->saddr, &n->smask, n->af);
46228964e80Sdhartmei 		printf(" ");
46328964e80Sdhartmei 	} else
46428964e80Sdhartmei 		printf("any ");
46528964e80Sdhartmei 	printf("to ");
466032e40b7Sdhartmei 	if (!PF_AZERO(&n->daddr.addr, n->af) || !PF_AZERO(&n->dmask, n->af)) {
46705885aacSfrantzen 		if (n->dnot)
46828964e80Sdhartmei 			printf("! ");
46930620b12Sfrantzen 		print_addr(&n->daddr, &n->dmask, n->af);
47028964e80Sdhartmei 		printf(" ");
47128964e80Sdhartmei 	} else
47228964e80Sdhartmei 		printf("any ");
473f27db9bcSdhartmei 	if (!n->no) {
47428964e80Sdhartmei 		printf("-> ");
47530620b12Sfrantzen 		print_addr(&n->raddr, NULL, n->af);
476f27db9bcSdhartmei 	}
47714a9b182Skjell 	printf("\n");
47814a9b182Skjell }
47914a9b182Skjell 
48014a9b182Skjell void
481a3e657d0Sjasoni print_binat(struct pf_binat *b)
482a3e657d0Sjasoni {
483f27db9bcSdhartmei 	if (b->no)
484f27db9bcSdhartmei 		printf("no ");
485f27db9bcSdhartmei 	printf("binat ");
486a3e657d0Sjasoni 	if (b->ifname[0]) {
487a3e657d0Sjasoni 		printf("on ");
488a3e657d0Sjasoni 		printf("%s ", b->ifname);
489a3e657d0Sjasoni 	}
490032e40b7Sdhartmei 	if (b->af) {
491032e40b7Sdhartmei 		if (b->af == AF_INET)
492032e40b7Sdhartmei 			printf("inet ");
493032e40b7Sdhartmei 		else
494032e40b7Sdhartmei 			printf("inet6 ");
495032e40b7Sdhartmei 	}
49680edb1f0Sdhartmei 	if (b->proto) {
49780edb1f0Sdhartmei 		struct protoent *p = getprotobynumber(b->proto);
49880edb1f0Sdhartmei 		if (p != NULL)
49980edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
50080edb1f0Sdhartmei 		else
50180edb1f0Sdhartmei 			printf("proto %u ", b->proto);
502a3e657d0Sjasoni 	}
503a3e657d0Sjasoni 	printf("from ");
50430620b12Sfrantzen 	print_addr(&b->saddr, NULL, b->af);
505a3e657d0Sjasoni 	printf(" ");
506a3e657d0Sjasoni 	printf("to ");
507032e40b7Sdhartmei 	if (!PF_AZERO(&b->daddr.addr, b->af) || !PF_AZERO(&b->dmask, b->af)) {
508a3e657d0Sjasoni 		if (b->dnot)
509a3e657d0Sjasoni 			printf("! ");
51030620b12Sfrantzen 		print_addr(&b->daddr, &b->dmask, b->af);
511a3e657d0Sjasoni 		printf(" ");
512a3e657d0Sjasoni 	} else
513a3e657d0Sjasoni 		printf("any ");
514f27db9bcSdhartmei 	if (!b->no) {
515a3e657d0Sjasoni 	 	printf("-> ");
51630620b12Sfrantzen 		print_addr(&b->raddr, NULL, b->af);
517f27db9bcSdhartmei 	}
518a3e657d0Sjasoni 	printf("\n");
519a3e657d0Sjasoni }
520a3e657d0Sjasoni 
521a3e657d0Sjasoni void
52281a15e5dSderaadt print_rdr(struct pf_rdr *r)
52314a9b182Skjell {
524f27db9bcSdhartmei 	if (r->no)
525f27db9bcSdhartmei 		printf("no ");
526f27db9bcSdhartmei 	printf("rdr ");
52728964e80Sdhartmei 	if (r->ifname[0]) {
52828964e80Sdhartmei 		printf("on ");
529870b51d7Schris 		if (r->ifnot)
530870b51d7Schris 			printf("! ");
531870b51d7Schris 		printf("%s ", r->ifname);
53228964e80Sdhartmei 	}
533032e40b7Sdhartmei 	if (r->af) {
534032e40b7Sdhartmei 		if (r->af == AF_INET)
535032e40b7Sdhartmei 			printf("inet ");
536032e40b7Sdhartmei 		else
537032e40b7Sdhartmei 			printf("inet6 ");
538032e40b7Sdhartmei 	}
53980edb1f0Sdhartmei 	if (r->proto) {
54080edb1f0Sdhartmei 		struct protoent *p = getprotobynumber(r->proto);
54180edb1f0Sdhartmei 		if (p != NULL)
54280edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
54380edb1f0Sdhartmei 		else
54480edb1f0Sdhartmei 			printf("proto %u ", r->proto);
545e3d52469Smillert 	}
54628964e80Sdhartmei 	printf("from ");
547032e40b7Sdhartmei 	if (!PF_AZERO(&r->saddr.addr, r->af) || !PF_AZERO(&r->smask, r->af)) {
54828964e80Sdhartmei 		if (r->snot)
54928964e80Sdhartmei 			printf("! ");
55030620b12Sfrantzen 		print_addr(&r->saddr, &r->smask, r->af);
55128964e80Sdhartmei 		printf(" ");
55228964e80Sdhartmei 	} else
55328964e80Sdhartmei 		printf("any ");
55428964e80Sdhartmei 	printf("to ");
555032e40b7Sdhartmei 	if (!PF_AZERO(&r->daddr.addr, r->af) || !PF_AZERO(&r->dmask, r->af)) {
556e7bd5eebSdhartmei 		if (r->dnot)
55714a9b182Skjell 			printf("! ");
55830620b12Sfrantzen 		print_addr(&r->daddr, &r->dmask, r->af);
55928964e80Sdhartmei 		printf(" ");
56028964e80Sdhartmei 	} else
56128964e80Sdhartmei 		printf("any ");
56280edb1f0Sdhartmei 	if (r->dport) {
563cb07131dSkjell 		printf("port %u", ntohs(r->dport));
564cb07131dSkjell 		if (r->opts & PF_DPORT_RANGE)
565cb07131dSkjell 			printf(":%u", ntohs(r->dport2));
56680edb1f0Sdhartmei 	}
567f27db9bcSdhartmei 	if (!r->no) {
568cb07131dSkjell 		printf(" -> ");
56930620b12Sfrantzen 		print_addr(&r->raddr, NULL, r->af);
57028964e80Sdhartmei 		printf(" ");
57180edb1f0Sdhartmei 		if (r->rport) {
57214a9b182Skjell 			printf("port %u", ntohs(r->rport));
573cb07131dSkjell 			if (r->opts & PF_RPORT_RANGE)
574cb07131dSkjell 				printf(":*");
57580edb1f0Sdhartmei 		}
576f27db9bcSdhartmei 	}
57714a9b182Skjell 	printf("\n");
57814a9b182Skjell }
57914a9b182Skjell 
580bca2bf17Sdhartmei char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
581bca2bf17Sdhartmei char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
58299a73934Sderaadt 
58314a9b182Skjell void
58481a15e5dSderaadt print_status(struct pf_status *s)
58514a9b182Skjell {
58681a15e5dSderaadt 
58799a73934Sderaadt 	time_t t = time(NULL);
58899a73934Sderaadt 	int i;
58999a73934Sderaadt 
590ae58c8acSdhartmei 	printf("Status: %s  Time: %u  Since: %u  Debug: ",
5917f08579dSkjell 	    s->running ? "Enabled" : "Disabled",
5927f08579dSkjell 	    t, s->since);
593ae58c8acSdhartmei 	switch (s->debug) {
594ae58c8acSdhartmei 		case 0:
595ae58c8acSdhartmei 			printf("None");
596ae58c8acSdhartmei 			break;
597ae58c8acSdhartmei 		case 1:
598ae58c8acSdhartmei 			printf("Urgent");
599ae58c8acSdhartmei 			break;
600ae58c8acSdhartmei 		case 2:
601ae58c8acSdhartmei 			printf("Misc");
602ae58c8acSdhartmei 			break;
603ae58c8acSdhartmei 	}
60430620b12Sfrantzen 	printf("\nBytes In IPv4: %-10llu  Bytes Out: %-10llu\n",
60530620b12Sfrantzen 	    s->bcounters[0][PF_IN], s->bcounters[0][PF_OUT]);
60630620b12Sfrantzen 	printf("         IPv6: %-10llu  Bytes Out: %-10llu\n",
60730620b12Sfrantzen 	    s->bcounters[1][PF_IN], s->bcounters[1][PF_OUT]);
60830620b12Sfrantzen 	printf("Inbound Packets IPv4:  Passed: %-10llu  Dropped: %-10llu\n",
60930620b12Sfrantzen 	    s->pcounters[0][PF_IN][PF_PASS],
61030620b12Sfrantzen 	    s->pcounters[0][PF_IN][PF_DROP]);
61130620b12Sfrantzen 	printf("                IPv6:  Passed: %-10llu  Dropped: %-10llu\n",
61230620b12Sfrantzen 	    s->pcounters[1][PF_IN][PF_PASS],
61330620b12Sfrantzen 	    s->pcounters[1][PF_IN][PF_DROP]);
61430620b12Sfrantzen 	printf("Outbound Packets IPv4: Passed: %-10llu  Dropped: %-10llu\n",
61530620b12Sfrantzen 	    s->pcounters[0][PF_OUT][PF_PASS],
61630620b12Sfrantzen 	    s->pcounters[0][PF_OUT][PF_DROP]);
61730620b12Sfrantzen 	printf("                 IPv6: Passed: %-10llu  Dropped: %-10llu\n",
61830620b12Sfrantzen 	    s->pcounters[1][PF_OUT][PF_PASS],
61930620b12Sfrantzen 	    s->pcounters[1][PF_OUT][PF_DROP]);
62084976600Sderaadt 	printf("States: %u\n", s->states);
62184976600Sderaadt 	printf("pf Counters\n");
622bca2bf17Sdhartmei 	for (i = 0; i < FCNT_MAX; i++)
623184bf464Sderaadt 		printf("%-25s %-8lld\n", pf_fcounters[i],
62484976600Sderaadt 		    s->fcounters[i]);
62599a73934Sderaadt 	printf("Counters\n");
62699a73934Sderaadt 	for (i = 0; i < PFRES_MAX; i++)
627184bf464Sderaadt 		printf("%-25s %-8lld\n", pf_reasons[i],
62899a73934Sderaadt 		    s->counters[i]);
62914a9b182Skjell }
63014a9b182Skjell 
63114a9b182Skjell void
632fdd4db37Sdhartmei print_state(struct pf_state *s, int opts)
63314a9b182Skjell {
6346d5ce0fbSderaadt 	struct pf_state_peer *src, *dst;
63580edb1f0Sdhartmei 	struct protoent *p;
63614a9b182Skjell 	u_int8_t hrs, min, sec;
637252d784aSderaadt 
63814a9b182Skjell 	if (s->direction == PF_OUT) {
63914a9b182Skjell 		src = &s->src;
64014a9b182Skjell 		dst = &s->dst;
64114a9b182Skjell 	} else {
64214a9b182Skjell 		src = &s->dst;
64314a9b182Skjell 		dst = &s->src;
64414a9b182Skjell 	}
64580edb1f0Sdhartmei 	if ((p = getprotobynumber(s->proto)) != NULL)
64680edb1f0Sdhartmei 		printf("%s ", p->p_name);
64780edb1f0Sdhartmei 	else
64880edb1f0Sdhartmei 		printf("%u ", s->proto);
64930620b12Sfrantzen 	if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) ||
65030620b12Sfrantzen 	    (s->lan.port != s->gwy.port)) {
6510eed2997Sdhartmei 		print_host(&s->lan, s->af, opts);
65214a9b182Skjell 		if (s->direction == PF_OUT)
65314a9b182Skjell 			printf(" -> ");
65414a9b182Skjell 		else
65514a9b182Skjell 			printf(" <- ");
65614a9b182Skjell 	}
6570eed2997Sdhartmei 	print_host(&s->gwy, s->af, opts);
65814a9b182Skjell 	if (s->direction == PF_OUT)
65914a9b182Skjell 		printf(" -> ");
66014a9b182Skjell 	else
66114a9b182Skjell 		printf(" <- ");
6620eed2997Sdhartmei 	print_host(&s->ext, s->af, opts);
66314a9b182Skjell 
664b96c47abSfrantzen 	printf("    ");
66514a9b182Skjell 	if (s->proto == IPPROTO_TCP) {
666b96c47abSfrantzen 		if (src->state <= TCPS_TIME_WAIT &&
667b96c47abSfrantzen 		    dst->state <= TCPS_TIME_WAIT) {
668b96c47abSfrantzen 			printf("   %s:%s\n", tcpstates[src->state],
66955507ad0Sfrantzen 			    tcpstates[dst->state]);
670b96c47abSfrantzen 		} else {
671b96c47abSfrantzen 			printf("   <BAD STATE LEVELS>\n");
672b96c47abSfrantzen 		}
673fdd4db37Sdhartmei 		if (opts & PF_OPT_VERBOSE) {
674b96c47abSfrantzen 			printf("   ");
67514a9b182Skjell 			print_seq(src);
67614a9b182Skjell 			printf("  ");
67714a9b182Skjell 			print_seq(dst);
67814a9b182Skjell 			printf("\n");
679fdd4db37Sdhartmei 		}
68055507ad0Sfrantzen 	} else {
681b96c47abSfrantzen 		printf("   %u:%u\n", src->state, dst->state);
68214a9b182Skjell 	}
68314a9b182Skjell 
684fdd4db37Sdhartmei 	if (opts & PF_OPT_VERBOSE) {
68514a9b182Skjell 		sec = s->creation % 60;
68614a9b182Skjell 		s->creation /= 60;
68714a9b182Skjell 		min = s->creation % 60;
68814a9b182Skjell 		s->creation /= 60;
68914a9b182Skjell 		hrs = s->creation;
69055507ad0Sfrantzen 		printf("   age %.2u:%.2u:%.2u", hrs, min, sec);
69114a9b182Skjell 		sec = s->expire % 60;
69214a9b182Skjell 		s->expire /= 60;
69314a9b182Skjell 		min = s->expire % 60;
69414a9b182Skjell 		s->expire /= 60;
69514a9b182Skjell 		hrs = s->expire;
69614a9b182Skjell 		printf(", expires in %.2u:%.2u:%.2u", hrs, min, sec);
697ab06fc45Sdhartmei 		printf(", %u pkts, %u bytes", s->packets, s->bytes);
698ab06fc45Sdhartmei 		if (s->rule.nr != USHRT_MAX)
699ab06fc45Sdhartmei 			printf(", rule %u", s->rule.nr);
700ab06fc45Sdhartmei 		printf("\n");
70114a9b182Skjell 	}
702fdd4db37Sdhartmei }
70314a9b182Skjell 
70414a9b182Skjell void
70581a15e5dSderaadt print_rule(struct pf_rule *r)
70614a9b182Skjell {
70778baf774Sdhartmei 	printf("@%d ", r->nr);
7088418a02fSprovos 	if (r->action == PF_PASS)
70914a9b182Skjell 		printf("pass ");
710b996d042Sdhartmei 	else if (r->action == PF_DROP) {
71114a9b182Skjell 		printf("block ");
71267d2a440Sprovos 		if (r->rule_flag & PFRULE_RETURNRST)
71314a9b182Skjell 			printf("return-rst ");
714b996d042Sdhartmei 		else if (r->return_icmp) {
715b996d042Sdhartmei 			struct icmpcodeent *ic;
716b996d042Sdhartmei 
717d14c53d7Swilfried 			if (r->af != AF_INET6)
718b996d042Sdhartmei 				printf("return-icmp");
719d14c53d7Swilfried 			else
720d14c53d7Swilfried 				printf("return-icmp6");
721b996d042Sdhartmei 			ic = geticmpcodebynumber(r->return_icmp >> 8,
722d14c53d7Swilfried 			    r->return_icmp & 255, r->af);
723d14c53d7Swilfried 
724d14c53d7Swilfried 			if (ic == NULL)
725d14c53d7Swilfried 				printf("(%u) ", r->return_icmp & 255);
7260eed2997Sdhartmei 			else if ((r->af != AF_INET6 && ic->code !=
7270eed2997Sdhartmei 			    ICMP_UNREACH_PORT) ||
7280eed2997Sdhartmei 			    (r->af == AF_INET6 && ic->code !=
7290eed2997Sdhartmei 			    ICMP6_DST_UNREACH_NOPORT))
730b996d042Sdhartmei 				printf("(%s) ", ic->name);
731b996d042Sdhartmei 			else
732b996d042Sdhartmei 				printf(" ");
733b996d042Sdhartmei 		}
734b996d042Sdhartmei 	} else
735b996d042Sdhartmei 		printf("scrub ");
73614a9b182Skjell 	if (r->direction == 0)
73714a9b182Skjell 		printf("in ");
73814a9b182Skjell 	else
73914a9b182Skjell 		printf("out ");
7407242ce7aSdhartmei 	if (r->log == 1)
74114a9b182Skjell 		printf("log ");
7427242ce7aSdhartmei 	else if (r->log == 2)
7437242ce7aSdhartmei 		printf("log-all ");
74414a9b182Skjell 	if (r->quick)
74514a9b182Skjell 		printf("quick ");
74614a9b182Skjell 	if (r->ifname[0])
74714a9b182Skjell 		printf("on %s ", r->ifname);
748cb3a4e31Sjasoni 	if (r->rt) {
749cb3a4e31Sjasoni 		if (r->rt == PF_ROUTETO)
750cb3a4e31Sjasoni 			printf("route-to ");
751cb3a4e31Sjasoni 		else if (r->rt == PF_DUPTO)
752cb3a4e31Sjasoni 			printf("dup-to ");
753cb3a4e31Sjasoni 		else if (r->rt == PF_FASTROUTE)
754cb3a4e31Sjasoni 			printf("fastroute");
755cb3a4e31Sjasoni 		if (r->rt_ifname[0])
756cb3a4e31Sjasoni 			printf("%s", r->rt_ifname);
757cb3a4e31Sjasoni 		if (r->af && !PF_AZERO(&r->rt_addr, r->af)) {
758032e40b7Sdhartmei 			struct pf_addr_wrap aw;
759032e40b7Sdhartmei 
760032e40b7Sdhartmei 			aw.addr = r->rt_addr;
761032e40b7Sdhartmei 			aw.addr_dyn = NULL;
762cb3a4e31Sjasoni 			printf(":");
763032e40b7Sdhartmei 			print_addr(&aw, NULL, r->af);
764cb3a4e31Sjasoni 		}
765cb3a4e31Sjasoni 		printf(" ");
766cb3a4e31Sjasoni 	}
76730620b12Sfrantzen 	if (r->af) {
76830620b12Sfrantzen 		if (r->af == AF_INET)
76930620b12Sfrantzen 			printf("inet ");
77030620b12Sfrantzen 		else
77130620b12Sfrantzen 			printf("inet6 ");
77230620b12Sfrantzen 	}
77314a9b182Skjell 	if (r->proto) {
77414a9b182Skjell 		struct protoent *p = getprotobynumber(r->proto);
77514a9b182Skjell 		if (p != NULL)
77614a9b182Skjell 			printf("proto %s ", p->p_name);
77714a9b182Skjell 		else
77814a9b182Skjell 			printf("proto %u ", r->proto);
77914a9b182Skjell 	}
780032e40b7Sdhartmei 	if (PF_AZERO(&r->src.addr.addr, AF_INET6) &&
78130620b12Sfrantzen 	    PF_AZERO(&r->src.mask, AF_INET6) &&
7823cb9a5b2Smickey 	    !r->src.noroute && !r->dst.noroute &&
783032e40b7Sdhartmei 	    !r->src.port_op && PF_AZERO(&r->dst.addr.addr, AF_INET6) &&
78430620b12Sfrantzen 	    PF_AZERO(&r->dst.mask, AF_INET6) && !r->dst.port_op)
78514a9b182Skjell 		printf("all ");
78614a9b182Skjell 	else {
78714a9b182Skjell 		printf("from ");
7883cb9a5b2Smickey 		if (r->src.noroute)
7893cb9a5b2Smickey 			printf("no-route ");
790032e40b7Sdhartmei 		else if (PF_AZERO(&r->src.addr.addr, AF_INET6) &&
79130620b12Sfrantzen 		    PF_AZERO(&r->src.mask, AF_INET6))
79214a9b182Skjell 			printf("any ");
79314a9b182Skjell 		else {
79414a9b182Skjell 			if (r->src.not)
79514a9b182Skjell 				printf("! ");
79630620b12Sfrantzen 			print_addr(&r->src.addr, &r->src.mask, r->af);
79714a9b182Skjell 			printf(" ");
79814a9b182Skjell 		}
79914a9b182Skjell 		if (r->src.port_op)
80014a9b182Skjell 			print_port(r->src.port_op, r->src.port[0],
8015df8e51cSsmart 			    r->src.port[1],
8025df8e51cSsmart 			    r->proto == IPPROTO_TCP ? "tcp" : "udp");
80314a9b182Skjell 
80414a9b182Skjell 		printf("to ");
8053cb9a5b2Smickey 		if (r->dst.noroute)
8063cb9a5b2Smickey 			printf("no-route ");
807032e40b7Sdhartmei 		else if (PF_AZERO(&r->dst.addr.addr, AF_INET6) &&
80830620b12Sfrantzen 		    PF_AZERO(&r->dst.mask, AF_INET6))
80914a9b182Skjell 			printf("any ");
81014a9b182Skjell 		else {
81114a9b182Skjell 			if (r->dst.not)
81214a9b182Skjell 				printf("! ");
81330620b12Sfrantzen 			print_addr(&r->dst.addr, &r->dst.mask, r->af);
81414a9b182Skjell 			printf(" ");
81514a9b182Skjell 		}
81614a9b182Skjell 		if (r->dst.port_op)
81714a9b182Skjell 			print_port(r->dst.port_op, r->dst.port[0],
8185df8e51cSsmart 			    r->dst.port[1],
8195df8e51cSsmart 			    r->proto == IPPROTO_TCP ? "tcp" : "udp");
82014a9b182Skjell 	}
821*c16ab608Sdhartmei 	if (r->uid.op)
822*c16ab608Sdhartmei 		print_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user");
823*c16ab608Sdhartmei 	if (r->gid.op)
824*c16ab608Sdhartmei 		print_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group");
82514a9b182Skjell 	if (r->flags || r->flagset) {
82614a9b182Skjell 		printf("flags ");
82714a9b182Skjell 		print_flags(r->flags);
82814a9b182Skjell 		printf("/");
82914a9b182Skjell 		print_flags(r->flagset);
83014a9b182Skjell 		printf(" ");
83114a9b182Skjell 	}
832082ebc44Swilfried 	if (r->type) {
833082ebc44Swilfried 		struct icmptypeent *p;
834082ebc44Swilfried 
835d14c53d7Swilfried 		p = geticmptypebynumber(r->type-1, r->af);
836d14c53d7Swilfried 		if (r->af != AF_INET6)
837d14c53d7Swilfried 			printf("icmp-type");
838082ebc44Swilfried 		else
839d14c53d7Swilfried 			printf("ipv6-icmp-type");
840d14c53d7Swilfried 		if (p != NULL)
841d14c53d7Swilfried 			printf(" %s ", p->name);
842d14c53d7Swilfried 		else
843d14c53d7Swilfried 			printf(" %u ", r->type-1);
844082ebc44Swilfried 		if (r->code) {
845082ebc44Swilfried 			struct icmpcodeent *p;
846082ebc44Swilfried 
847d14c53d7Swilfried 			p = geticmpcodebynumber(r->type-1, r->code-1, r->af);
848082ebc44Swilfried 			if (p != NULL)
849082ebc44Swilfried 				printf("code %s ", p->name);
850082ebc44Swilfried 			else
85114a9b182Skjell 				printf("code %u ", r->code-1);
852082ebc44Swilfried 		}
853082ebc44Swilfried 	}
854b96c47abSfrantzen 	if (r->keep_state == PF_STATE_NORMAL)
85514a9b182Skjell 		printf("keep state ");
856b96c47abSfrantzen 	else if (r->keep_state == PF_STATE_MODULATE)
857b96c47abSfrantzen 		printf("modulate state ");
8586673dee2Sdhartmei 	if (r->rule_flag & PFRULE_FRAGMENT)
8596673dee2Sdhartmei 		printf("fragment ");
86067d2a440Sprovos 	if (r->rule_flag & PFRULE_NODF)
86167d2a440Sprovos 		printf("no-df ");
862e258bfd4Sprovos 	if (r->min_ttl)
86334c76dcbSprovos 		printf("min-ttl %d ", r->min_ttl);
864cfa91859Sjasoni 	if (r->max_mss)
865cfa91859Sjasoni 		printf("max-mss %d ", r->max_mss);
866f48d62b3Sdhartmei 	if (r->allow_opts)
867f48d62b3Sdhartmei 		printf("allow-opts ");
868455ef0c1Sdhartmei 	if (r->label[0])
869455ef0c1Sdhartmei 		printf("label %s", r->label);
87067d2a440Sprovos 
87114a9b182Skjell 	printf("\n");
87214a9b182Skjell }
87314a9b182Skjell 
8741f8f21bdSmillert int
875ff352a37Smarkus parse_flags(char *s)
87614a9b182Skjell {
877ff352a37Smarkus 	char *p, *q;
87814a9b182Skjell 	u_int8_t f = 0;
87981a15e5dSderaadt 
880ff352a37Smarkus 	for (p = s; *p; p++) {
881ff352a37Smarkus 		if ((q = strchr(tcpflags, *p)) == NULL)
882ff352a37Smarkus 			return -1;
883ff352a37Smarkus 		else
884ff352a37Smarkus 			f |= 1 << (q - tcpflags);
88514a9b182Skjell 	}
886dbfb98deSprovos 	return (f ? f : 63);
88714a9b182Skjell }
8880eed2997Sdhartmei 
8890eed2997Sdhartmei struct hostent *
8900eed2997Sdhartmei getpfhostname(const char *addr_str)
8910eed2997Sdhartmei {
8921feb912bSdhartmei 	in_addr_t		 addr_num;
8930eed2997Sdhartmei 	struct hostent		*hp;
8940eed2997Sdhartmei 	static struct hostent	 myhp;
8950eed2997Sdhartmei 
8960eed2997Sdhartmei 	addr_num = inet_addr(addr_str);
8970eed2997Sdhartmei 	if (addr_num == INADDR_NONE) {
8980eed2997Sdhartmei 		myhp.h_name = (char *)addr_str;
8990eed2997Sdhartmei 		hp = &myhp;
9000eed2997Sdhartmei 		return (hp);
9010eed2997Sdhartmei 	}
9020eed2997Sdhartmei 	hp = gethostbyaddr((char *)&addr_num, sizeof(addr_num), AF_INET);
9030eed2997Sdhartmei 	if (hp == NULL) {
9040eed2997Sdhartmei 		myhp.h_name = (char *)addr_str;
9050eed2997Sdhartmei 		hp = &myhp;
9060eed2997Sdhartmei 	}
9070eed2997Sdhartmei 	return (hp);
9080eed2997Sdhartmei }
909