xref: /openbsd/sbin/pfctl/pfctl_parser.c (revision d85e4ad6)
1*d85e4ad6Sdhartmei /*	$OpenBSD: pfctl_parser.c,v 1.90 2002/06/19 17:44:02 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>
41252d784aSderaadt #include <net/pfvar.h>
429f13c6caSmillert #include <arpa/inet.h>
43252d784aSderaadt 
4414a9b182Skjell #include <stdio.h>
4514a9b182Skjell #include <stdlib.h>
4614a9b182Skjell #include <string.h>
4714a9b182Skjell #include <ctype.h>
4814a9b182Skjell #include <netdb.h>
496329fa59Sderaadt #include <stdarg.h>
506329fa59Sderaadt #include <errno.h>
51ff352a37Smarkus #include <err.h>
5214a9b182Skjell 
5314a9b182Skjell #include "pfctl_parser.h"
54828e0448Smickey #include "pf_print_state.h"
5514a9b182Skjell 
565d9ac2dcSdhartmei void		 print_op (u_int8_t, const char *, const char *);
5781a15e5dSderaadt void		 print_port (u_int8_t, u_int16_t, u_int16_t, char *);
585d9ac2dcSdhartmei void		 print_uid (u_int8_t, uid_t, uid_t, const char *);
59c16ab608Sdhartmei void		 print_gid (u_int8_t, gid_t, gid_t, const char *);
6081a15e5dSderaadt void		 print_flags (u_int8_t);
6115e76891Sdhartmei void		 print_fromto(struct pf_rule_addr *, struct pf_rule_addr *,
6215e76891Sdhartmei 		    u_int8_t, u_int8_t);
6314a9b182Skjell 
64bc795af0Shugh char *tcpflags = "FSRPAUEW";
6514a9b182Skjell 
667d27d81aSdhartmei static const 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 }
92082ebc44Swilfried };
93082ebc44Swilfried 
947d27d81aSdhartmei static const struct icmptypeent icmp6_type[] = {
9530620b12Sfrantzen 	{ "unreach",	ICMP6_DST_UNREACH },
9630620b12Sfrantzen 	{ "toobig",	ICMP6_PACKET_TOO_BIG },
9730620b12Sfrantzen 	{ "timex",	ICMP6_TIME_EXCEEDED },
9830620b12Sfrantzen 	{ "paramprob",	ICMP6_PARAM_PROB },
9930620b12Sfrantzen 	{ "echoreq",	ICMP6_ECHO_REQUEST },
10030620b12Sfrantzen 	{ "echorep",	ICMP6_ECHO_REPLY },
10130620b12Sfrantzen 	{ "groupqry",	ICMP6_MEMBERSHIP_QUERY },
10230620b12Sfrantzen 	{ "listqry",	MLD6_LISTENER_QUERY },
10330620b12Sfrantzen 	{ "grouprep",	ICMP6_MEMBERSHIP_REPORT },
10430620b12Sfrantzen 	{ "listenrep",	MLD6_LISTENER_REPORT },
10530620b12Sfrantzen 	{ "groupterm",	ICMP6_MEMBERSHIP_REDUCTION },
10630620b12Sfrantzen 	{ "listendone", MLD6_LISTENER_DONE },
10730620b12Sfrantzen 	{ "routersol",	ND_ROUTER_SOLICIT },
10830620b12Sfrantzen 	{ "routeradv",	ND_ROUTER_ADVERT },
10930620b12Sfrantzen 	{ "neighbrsol", ND_NEIGHBOR_SOLICIT },
11030620b12Sfrantzen 	{ "neighbradv", ND_NEIGHBOR_ADVERT },
11130620b12Sfrantzen 	{ "redir",	ND_REDIRECT },
11230620b12Sfrantzen 	{ "routrrenum", ICMP6_ROUTER_RENUMBERING },
11330620b12Sfrantzen 	{ "wrureq",	ICMP6_WRUREQUEST },
11430620b12Sfrantzen 	{ "wrurep",	ICMP6_WRUREPLY },
11530620b12Sfrantzen 	{ "fqdnreq",	ICMP6_FQDN_QUERY },
11630620b12Sfrantzen 	{ "fqdnrep",	ICMP6_FQDN_REPLY },
11730620b12Sfrantzen 	{ "niqry",	ICMP6_NI_QUERY },
11830620b12Sfrantzen 	{ "nirep",	ICMP6_NI_REPLY },
11930620b12Sfrantzen 	{ "mtraceresp",	MLD6_MTRACE_RESP },
12030620b12Sfrantzen 	{ "mtrace",	MLD6_MTRACE }
12130620b12Sfrantzen };
12230620b12Sfrantzen 
1237d27d81aSdhartmei static const struct icmpcodeent icmp_code[] = {
124082ebc44Swilfried 	{ "net-unr",		ICMP_UNREACH,	ICMP_UNREACH_NET },
125082ebc44Swilfried 	{ "host-unr",		ICMP_UNREACH,	ICMP_UNREACH_HOST },
126082ebc44Swilfried 	{ "proto-unr",		ICMP_UNREACH,	ICMP_UNREACH_PROTOCOL },
127082ebc44Swilfried 	{ "port-unr",		ICMP_UNREACH,	ICMP_UNREACH_PORT },
128082ebc44Swilfried 	{ "needfrag",		ICMP_UNREACH,	ICMP_UNREACH_NEEDFRAG },
129082ebc44Swilfried 	{ "srcfail",		ICMP_UNREACH,	ICMP_UNREACH_SRCFAIL },
130082ebc44Swilfried 	{ "net-unk",		ICMP_UNREACH,	ICMP_UNREACH_NET_UNKNOWN },
131082ebc44Swilfried 	{ "host-unk",		ICMP_UNREACH,	ICMP_UNREACH_HOST_UNKNOWN },
132082ebc44Swilfried 	{ "isolate",		ICMP_UNREACH,	ICMP_UNREACH_ISOLATED },
133082ebc44Swilfried 	{ "net-prohib",		ICMP_UNREACH,	ICMP_UNREACH_NET_PROHIB },
134082ebc44Swilfried 	{ "host-prohib",	ICMP_UNREACH,	ICMP_UNREACH_HOST_PROHIB },
135082ebc44Swilfried 	{ "net-tos",		ICMP_UNREACH,	ICMP_UNREACH_TOSNET },
136082ebc44Swilfried 	{ "host-tos",		ICMP_UNREACH,	ICMP_UNREACH_TOSHOST },
137082ebc44Swilfried 	{ "filter-prohib",	ICMP_UNREACH,	ICMP_UNREACH_FILTER_PROHIB },
138082ebc44Swilfried 	{ "host-preced",	ICMP_UNREACH,	ICMP_UNREACH_HOST_PRECEDENCE },
139082ebc44Swilfried 	{ "cutoff-preced",	ICMP_UNREACH,	ICMP_UNREACH_PRECEDENCE_CUTOFF },
140082ebc44Swilfried 	{ "redir-net",		ICMP_REDIRECT,	ICMP_REDIRECT_NET },
141082ebc44Swilfried 	{ "redir-host",		ICMP_REDIRECT,	ICMP_REDIRECT_HOST },
142082ebc44Swilfried 	{ "redir-tos-net",	ICMP_REDIRECT,	ICMP_REDIRECT_TOSNET },
143082ebc44Swilfried 	{ "redir-tos-host",	ICMP_REDIRECT,	ICMP_REDIRECT_TOSHOST },
14402cbcc9eSwilfried 	{ "normal-adv",		ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL },
14502cbcc9eSwilfried 	{ "common-adv",		ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON },
146082ebc44Swilfried 	{ "transit",		ICMP_TIMXCEED,	ICMP_TIMXCEED_INTRANS },
147082ebc44Swilfried 	{ "reassemb",		ICMP_TIMXCEED,	ICMP_TIMXCEED_REASS },
148082ebc44Swilfried 	{ "badhead",		ICMP_PARAMPROB,	ICMP_PARAMPROB_ERRATPTR },
149082ebc44Swilfried 	{ "optmiss",		ICMP_PARAMPROB,	ICMP_PARAMPROB_OPTABSENT },
15002cbcc9eSwilfried 	{ "badlen",		ICMP_PARAMPROB,	ICMP_PARAMPROB_LENGTH },
15102cbcc9eSwilfried 	{ "unknown-ind",	ICMP_PHOTURIS,	ICMP_PHOTURIS_UNKNOWN_INDEX },
15202cbcc9eSwilfried 	{ "auth-fail",		ICMP_PHOTURIS,	ICMP_PHOTURIS_AUTH_FAILED },
15302cbcc9eSwilfried 	{ "decrypt-fail",	ICMP_PHOTURIS,	ICMP_PHOTURIS_DECRYPT_FAILED }
154082ebc44Swilfried };
155082ebc44Swilfried 
1567d27d81aSdhartmei static const struct icmpcodeent icmp6_code[] = {
1571d32ee3bSdhartmei 	{ "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN },
1581d32ee3bSdhartmei 	{ "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE },
15930620b12Sfrantzen 	{ "notnbr-unr",	ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR },
16030620b12Sfrantzen 	{ "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE },
16130620b12Sfrantzen 	{ "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR },
16230620b12Sfrantzen 	{ "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT },
16330620b12Sfrantzen 	{ "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT },
16430620b12Sfrantzen 	{ "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY },
16530620b12Sfrantzen 	{ "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER },
16630620b12Sfrantzen 	{ "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER },
16730620b12Sfrantzen 	{ "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK },
16830620b12Sfrantzen 	{ "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER }
16930620b12Sfrantzen };
17030620b12Sfrantzen 
171d593fb91Sdrahn const struct pf_timeout pf_timeouts[] = {
172d593fb91Sdrahn 	{ "tcp.first",		PFTM_TCP_FIRST_PACKET },
173d593fb91Sdrahn 	{ "tcp.opening",	PFTM_TCP_OPENING },
174d593fb91Sdrahn 	{ "tcp.established",	PFTM_TCP_ESTABLISHED },
175d593fb91Sdrahn 	{ "tcp.closing",	PFTM_TCP_CLOSING },
176d593fb91Sdrahn 	{ "tcp.finwait",	PFTM_TCP_FIN_WAIT },
177d593fb91Sdrahn 	{ "tcp.closed",		PFTM_TCP_CLOSED },
178d593fb91Sdrahn 	{ "udp.first",		PFTM_UDP_FIRST_PACKET },
179d593fb91Sdrahn 	{ "udp.single",		PFTM_UDP_SINGLE },
180d593fb91Sdrahn 	{ "udp.multiple",	PFTM_UDP_MULTIPLE },
181d593fb91Sdrahn 	{ "icmp.first",		PFTM_ICMP_FIRST_PACKET },
182d593fb91Sdrahn 	{ "icmp.error",		PFTM_ICMP_ERROR_REPLY },
183d593fb91Sdrahn 	{ "other.first",	PFTM_OTHER_FIRST_PACKET },
184d593fb91Sdrahn 	{ "other.single",	PFTM_OTHER_SINGLE },
185d593fb91Sdrahn 	{ "other.multiple",	PFTM_OTHER_MULTIPLE },
186d593fb91Sdrahn 	{ "frag",		PFTM_FRAG },
187d593fb91Sdrahn 	{ "interval",		PFTM_INTERVAL },
188d593fb91Sdrahn 	{ NULL,			0 }
189d593fb91Sdrahn };
190d593fb91Sdrahn 
1917d27d81aSdhartmei const struct icmptypeent *
192d14c53d7Swilfried geticmptypebynumber(u_int8_t type, u_int8_t af)
193082ebc44Swilfried {
194ed99c291Sderaadt 	unsigned int i;
195082ebc44Swilfried 
196d14c53d7Swilfried 	if (af != AF_INET6) {
197082ebc44Swilfried 		for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) {
198082ebc44Swilfried 			if (type == icmp_type[i].type)
199082ebc44Swilfried 				return (&icmp_type[i]);
200082ebc44Swilfried 		}
20130620b12Sfrantzen 	} else {
20230620b12Sfrantzen 		for (i=0; i < (sizeof (icmp6_type) /
20330620b12Sfrantzen 		    sizeof(icmp6_type[0])); i++) {
20430620b12Sfrantzen 			if (type == icmp6_type[i].type)
20530620b12Sfrantzen 				 return (&icmp6_type[i]);
20630620b12Sfrantzen 		}
20730620b12Sfrantzen 	}
20830620b12Sfrantzen 	return (NULL);
209082ebc44Swilfried }
210082ebc44Swilfried 
2117d27d81aSdhartmei const struct icmptypeent *
212d14c53d7Swilfried geticmptypebyname(char *w, u_int8_t af)
213082ebc44Swilfried {
214ed99c291Sderaadt 	unsigned int i;
215082ebc44Swilfried 
216d14c53d7Swilfried 	if (af != AF_INET6) {
217082ebc44Swilfried 		for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0])); i++) {
218082ebc44Swilfried 			if (!strcmp(w, icmp_type[i].name))
219082ebc44Swilfried 				return (&icmp_type[i]);
220082ebc44Swilfried 		}
22130620b12Sfrantzen 	} else {
22230620b12Sfrantzen 		for (i=0; i < (sizeof (icmp6_type) /
22330620b12Sfrantzen 		    sizeof(icmp6_type[0])); i++) {
22430620b12Sfrantzen 			if (!strcmp(w, icmp6_type[i].name))
22530620b12Sfrantzen 				return (&icmp6_type[i]);
22630620b12Sfrantzen 		}
22730620b12Sfrantzen 	}
22830620b12Sfrantzen 	return (NULL);
229082ebc44Swilfried }
230082ebc44Swilfried 
2317d27d81aSdhartmei const struct icmpcodeent *
232d14c53d7Swilfried geticmpcodebynumber(u_int8_t type, u_int8_t code, u_int8_t af)
233082ebc44Swilfried {
234ed99c291Sderaadt 	unsigned int i;
235082ebc44Swilfried 
236d14c53d7Swilfried 	if (af != AF_INET6) {
237082ebc44Swilfried 		for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) {
23830620b12Sfrantzen 			if (type == icmp_code[i].type &&
23930620b12Sfrantzen 			    code == icmp_code[i].code)
240082ebc44Swilfried 				return (&icmp_code[i]);
241082ebc44Swilfried 		}
24230620b12Sfrantzen 	} else {
24330620b12Sfrantzen 		for (i=0; i < (sizeof (icmp6_code) /
24430620b12Sfrantzen 		   sizeof(icmp6_code[0])); i++) {
24530620b12Sfrantzen 			if (type == icmp6_code[i].type &&
24630620b12Sfrantzen 			    code == icmp6_code[i].code)
24730620b12Sfrantzen 				return (&icmp6_code[i]);
24830620b12Sfrantzen 		}
24930620b12Sfrantzen 	}
25030620b12Sfrantzen 	return (NULL);
251082ebc44Swilfried }
252082ebc44Swilfried 
2537d27d81aSdhartmei const struct icmpcodeent *
254d14c53d7Swilfried geticmpcodebyname(u_long type, char *w, u_int8_t af)
255082ebc44Swilfried {
256ed99c291Sderaadt 	unsigned int i;
257082ebc44Swilfried 
258d14c53d7Swilfried 	if (af != AF_INET6) {
259082ebc44Swilfried 		for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0])); i++) {
26030620b12Sfrantzen 			if (type == icmp_code[i].type &&
26130620b12Sfrantzen 			    !strcmp(w, icmp_code[i].name))
262082ebc44Swilfried 				return (&icmp_code[i]);
263082ebc44Swilfried 		}
26430620b12Sfrantzen 	} else {
26530620b12Sfrantzen 		for (i=0; i < (sizeof (icmp6_code) /
26630620b12Sfrantzen 		    sizeof(icmp6_code[0])); i++) {
26730620b12Sfrantzen 			if (type == icmp6_code[i].type &&
26830620b12Sfrantzen 			    !strcmp(w, icmp6_code[i].name))
26930620b12Sfrantzen 				return (&icmp6_code[i]);
27030620b12Sfrantzen 		}
27130620b12Sfrantzen 	}
27230620b12Sfrantzen 	return (NULL);
27330620b12Sfrantzen }
27430620b12Sfrantzen 
27581a15e5dSderaadt void
2765d9ac2dcSdhartmei print_op(u_int8_t op, const char *a1, const char *a2)
2775d9ac2dcSdhartmei {
2785d9ac2dcSdhartmei 	if (op == PF_OP_IRG)
2795d9ac2dcSdhartmei 		printf("%s >< %s ", a1, a2);
2805d9ac2dcSdhartmei 	else if (op == PF_OP_XRG)
2815d9ac2dcSdhartmei 		printf("%s <> %s ", a1, a2);
2821308506cShenning 	else if (op == PF_OP_EQ)
2835d9ac2dcSdhartmei 		printf("= %s ", a1);
2841308506cShenning 	else if (op == PF_OP_NE)
2855d9ac2dcSdhartmei 		printf("!= %s ", a1);
2861308506cShenning 	else if (op == PF_OP_LT)
2875d9ac2dcSdhartmei 		printf("< %s ", a1);
2885d9ac2dcSdhartmei 	else if (op == PF_OP_LE)
2895d9ac2dcSdhartmei 		printf("<= %s ", a1);
2905d9ac2dcSdhartmei 	else if (op == PF_OP_GT)
2915d9ac2dcSdhartmei 		printf("> %s ", a1);
2925d9ac2dcSdhartmei 	else if (op == PF_OP_GE)
2935d9ac2dcSdhartmei 		printf(">= %s ", a1);
2945d9ac2dcSdhartmei }
2955d9ac2dcSdhartmei 
2965d9ac2dcSdhartmei void
29714a9b182Skjell print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto)
29814a9b182Skjell {
299e31d21c9Sdhartmei 	char a1[6], a2[6];
30014a9b182Skjell 	struct servent *s = getservbyport(p1, proto);
30181a15e5dSderaadt 
30214a9b182Skjell 	p1 = ntohs(p1);
30314a9b182Skjell 	p2 = ntohs(p2);
3045d9ac2dcSdhartmei 	snprintf(a1, sizeof(a1), "%u", p1);
3055d9ac2dcSdhartmei 	snprintf(a2, sizeof(a2), "%u", p2);
30614a9b182Skjell 	printf("port ");
3075d9ac2dcSdhartmei 	if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE))
3085d9ac2dcSdhartmei 		print_op(op, s->s_name, a2);
30914a9b182Skjell 	else
3105d9ac2dcSdhartmei 		print_op(op, a1, a2);
3115d9ac2dcSdhartmei }
3125d9ac2dcSdhartmei 
3135d9ac2dcSdhartmei void
3145d9ac2dcSdhartmei print_uid(u_int8_t op, uid_t u1, uid_t u2, const char *t)
3155d9ac2dcSdhartmei {
316d8fcd2dfSdhartmei 	char a1[11], a2[11];
3175d9ac2dcSdhartmei 
3185d9ac2dcSdhartmei 	snprintf(a1, sizeof(a1), "%u", u1);
3195d9ac2dcSdhartmei 	snprintf(a2, sizeof(a2), "%u", u2);
3205d9ac2dcSdhartmei 	printf("%s ", t);
3215d9ac2dcSdhartmei 	if (u1 == UID_MAX && (op == PF_OP_EQ || op == PF_OP_NE))
3225d9ac2dcSdhartmei 		print_op(op, "unknown", a2);
32314a9b182Skjell 	else
3245d9ac2dcSdhartmei 		print_op(op, a1, a2);
32514a9b182Skjell }
32614a9b182Skjell 
32781a15e5dSderaadt void
328c16ab608Sdhartmei print_gid(u_int8_t op, gid_t g1, gid_t g2, const char *t)
329c16ab608Sdhartmei {
330d8fcd2dfSdhartmei 	char a1[11], a2[11];
331c16ab608Sdhartmei 
332c16ab608Sdhartmei 	snprintf(a1, sizeof(a1), "%u", g1);
333c16ab608Sdhartmei 	snprintf(a2, sizeof(a2), "%u", g2);
334c16ab608Sdhartmei 	printf("%s ", t);
335c16ab608Sdhartmei 	if (g1 == GID_MAX && (op == PF_OP_EQ || op == PF_OP_NE))
336c16ab608Sdhartmei 		print_op(op, "unknown", a2);
337c16ab608Sdhartmei 	else
338c16ab608Sdhartmei 		print_op(op, a1, a2);
339c16ab608Sdhartmei }
340c16ab608Sdhartmei 
341c16ab608Sdhartmei void
34214a9b182Skjell print_flags(u_int8_t f)
34314a9b182Skjell {
34414a9b182Skjell 	int i;
34581a15e5dSderaadt 
346bc795af0Shugh 	for (i = 0; tcpflags[i]; ++i)
34714a9b182Skjell 		if (f & (1 << i))
34814a9b182Skjell 			printf("%c", tcpflags[i]);
34914a9b182Skjell }
35014a9b182Skjell 
35114a9b182Skjell void
35215e76891Sdhartmei print_fromto(struct pf_rule_addr *src, struct pf_rule_addr *dst,
35315e76891Sdhartmei     u_int8_t af, u_int8_t proto)
35415e76891Sdhartmei {
35515e76891Sdhartmei 	if (PF_AZERO(&src->addr.addr, AF_INET6) &&
35615e76891Sdhartmei 	    PF_AZERO(&src->mask, AF_INET6) &&
35715e76891Sdhartmei 	    !src->noroute && !dst->noroute &&
35815e76891Sdhartmei 	    !src->port_op && PF_AZERO(&dst->addr.addr, AF_INET6) &&
35915e76891Sdhartmei 	    PF_AZERO(&dst->mask, AF_INET6) && !dst->port_op)
36015e76891Sdhartmei 		printf("all ");
36115e76891Sdhartmei 	else {
36215e76891Sdhartmei 		printf("from ");
36315e76891Sdhartmei 		if (src->noroute)
36415e76891Sdhartmei 			printf("no-route ");
36515e76891Sdhartmei 		else if (PF_AZERO(&src->addr.addr, AF_INET6) &&
36615e76891Sdhartmei 		    PF_AZERO(&src->mask, AF_INET6))
36715e76891Sdhartmei 			printf("any ");
36815e76891Sdhartmei 		else {
36915e76891Sdhartmei 			if (src->not)
37015e76891Sdhartmei 				printf("! ");
37115e76891Sdhartmei 			print_addr(&src->addr, &src->mask, af);
37215e76891Sdhartmei 			printf(" ");
37315e76891Sdhartmei 		}
37415e76891Sdhartmei 		if (src->port_op)
37515e76891Sdhartmei 			print_port(src->port_op, src->port[0],
37615e76891Sdhartmei 			    src->port[1],
37715e76891Sdhartmei 			    proto == IPPROTO_TCP ? "tcp" : "udp");
37815e76891Sdhartmei 
37915e76891Sdhartmei 		printf("to ");
38015e76891Sdhartmei 		if (dst->noroute)
38115e76891Sdhartmei 			printf("no-route ");
38215e76891Sdhartmei 		else if (PF_AZERO(&dst->addr.addr, AF_INET6) &&
38315e76891Sdhartmei 		    PF_AZERO(&dst->mask, AF_INET6))
38415e76891Sdhartmei 			printf("any ");
38515e76891Sdhartmei 		else {
38615e76891Sdhartmei 			if (dst->not)
38715e76891Sdhartmei 				printf("! ");
38815e76891Sdhartmei 			print_addr(&dst->addr, &dst->mask, af);
38915e76891Sdhartmei 			printf(" ");
39015e76891Sdhartmei 		}
39115e76891Sdhartmei 		if (dst->port_op)
39215e76891Sdhartmei 			print_port(dst->port_op, dst->port[0],
39315e76891Sdhartmei 			    dst->port[1],
39415e76891Sdhartmei 			    proto == IPPROTO_TCP ? "tcp" : "udp");
39515e76891Sdhartmei 	}
39615e76891Sdhartmei }
39715e76891Sdhartmei 
39815e76891Sdhartmei void
39981a15e5dSderaadt print_nat(struct pf_nat *n)
40014a9b182Skjell {
401f27db9bcSdhartmei 	if (n->no)
402f27db9bcSdhartmei 		printf("no ");
403f27db9bcSdhartmei 	printf("nat ");
40428964e80Sdhartmei 	if (n->ifname[0]) {
40528964e80Sdhartmei 		printf("on ");
406870b51d7Schris 		if (n->ifnot)
407870b51d7Schris 			printf("! ");
408870b51d7Schris 		printf("%s ", n->ifname);
40928964e80Sdhartmei 	}
410032e40b7Sdhartmei 	if (n->af) {
411032e40b7Sdhartmei 		if (n->af == AF_INET)
412032e40b7Sdhartmei 			printf("inet ");
413032e40b7Sdhartmei 		else
414032e40b7Sdhartmei 			printf("inet6 ");
415032e40b7Sdhartmei 	}
41680edb1f0Sdhartmei 	if (n->proto) {
41780edb1f0Sdhartmei 		struct protoent *p = getprotobynumber(n->proto);
418ed99c291Sderaadt 
419ab745e3bSmpech 		if (p != NULL)
42080edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
42180edb1f0Sdhartmei 		else
42280edb1f0Sdhartmei 			printf("proto %u ", n->proto);
42380edb1f0Sdhartmei 	}
42415e76891Sdhartmei 	print_fromto(&n->src, &n->dst, n->af, n->proto);
425f27db9bcSdhartmei 	if (!n->no) {
42628964e80Sdhartmei 		printf("-> ");
42730620b12Sfrantzen 		print_addr(&n->raddr, NULL, n->af);
428e4b04189Sdhartmei 		if (n->proxy_port[0] != PF_NAT_PROXY_PORT_LOW ||
429e4b04189Sdhartmei 		    n->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) {
430e4b04189Sdhartmei 			if (n->proxy_port[0] == n->proxy_port[1])
431e4b04189Sdhartmei 				printf(" port %u", n->proxy_port[0]);
432e4b04189Sdhartmei 			else
433e4b04189Sdhartmei 				printf(" port %u:%u", n->proxy_port[0],
434e4b04189Sdhartmei 				    n->proxy_port[1]);
435e4b04189Sdhartmei 		}
436f27db9bcSdhartmei 	}
43714a9b182Skjell 	printf("\n");
43814a9b182Skjell }
43914a9b182Skjell 
44014a9b182Skjell void
441a3e657d0Sjasoni print_binat(struct pf_binat *b)
442a3e657d0Sjasoni {
443f27db9bcSdhartmei 	if (b->no)
444f27db9bcSdhartmei 		printf("no ");
445f27db9bcSdhartmei 	printf("binat ");
446a3e657d0Sjasoni 	if (b->ifname[0]) {
447a3e657d0Sjasoni 		printf("on ");
448a3e657d0Sjasoni 		printf("%s ", b->ifname);
449a3e657d0Sjasoni 	}
450032e40b7Sdhartmei 	if (b->af) {
451032e40b7Sdhartmei 		if (b->af == AF_INET)
452032e40b7Sdhartmei 			printf("inet ");
453032e40b7Sdhartmei 		else
454032e40b7Sdhartmei 			printf("inet6 ");
455032e40b7Sdhartmei 	}
45680edb1f0Sdhartmei 	if (b->proto) {
45780edb1f0Sdhartmei 		struct protoent *p = getprotobynumber(b->proto);
458ed99c291Sderaadt 
45980edb1f0Sdhartmei 		if (p != NULL)
46080edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
46180edb1f0Sdhartmei 		else
46280edb1f0Sdhartmei 			printf("proto %u ", b->proto);
463a3e657d0Sjasoni 	}
464a3e657d0Sjasoni 	printf("from ");
46530620b12Sfrantzen 	print_addr(&b->saddr, NULL, b->af);
466a3e657d0Sjasoni 	printf(" ");
467a3e657d0Sjasoni 	printf("to ");
468032e40b7Sdhartmei 	if (!PF_AZERO(&b->daddr.addr, b->af) || !PF_AZERO(&b->dmask, b->af)) {
469a3e657d0Sjasoni 		if (b->dnot)
470a3e657d0Sjasoni 			printf("! ");
47130620b12Sfrantzen 		print_addr(&b->daddr, &b->dmask, b->af);
472a3e657d0Sjasoni 		printf(" ");
473a3e657d0Sjasoni 	} else
474a3e657d0Sjasoni 		printf("any ");
475f27db9bcSdhartmei 	if (!b->no) {
476a3e657d0Sjasoni 		printf("-> ");
47730620b12Sfrantzen 		print_addr(&b->raddr, NULL, b->af);
478f27db9bcSdhartmei 	}
479a3e657d0Sjasoni 	printf("\n");
480a3e657d0Sjasoni }
481a3e657d0Sjasoni 
482a3e657d0Sjasoni void
48381a15e5dSderaadt print_rdr(struct pf_rdr *r)
48414a9b182Skjell {
485f27db9bcSdhartmei 	if (r->no)
486f27db9bcSdhartmei 		printf("no ");
487f27db9bcSdhartmei 	printf("rdr ");
48828964e80Sdhartmei 	if (r->ifname[0]) {
48928964e80Sdhartmei 		printf("on ");
490870b51d7Schris 		if (r->ifnot)
491870b51d7Schris 			printf("! ");
492870b51d7Schris 		printf("%s ", r->ifname);
49328964e80Sdhartmei 	}
494032e40b7Sdhartmei 	if (r->af) {
495032e40b7Sdhartmei 		if (r->af == AF_INET)
496032e40b7Sdhartmei 			printf("inet ");
497032e40b7Sdhartmei 		else
498032e40b7Sdhartmei 			printf("inet6 ");
499032e40b7Sdhartmei 	}
50080edb1f0Sdhartmei 	if (r->proto) {
50180edb1f0Sdhartmei 		struct protoent *p = getprotobynumber(r->proto);
502ed99c291Sderaadt 
50380edb1f0Sdhartmei 		if (p != NULL)
50480edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
50580edb1f0Sdhartmei 		else
50680edb1f0Sdhartmei 			printf("proto %u ", r->proto);
507e3d52469Smillert 	}
50828964e80Sdhartmei 	printf("from ");
509032e40b7Sdhartmei 	if (!PF_AZERO(&r->saddr.addr, r->af) || !PF_AZERO(&r->smask, r->af)) {
51028964e80Sdhartmei 		if (r->snot)
51128964e80Sdhartmei 			printf("! ");
51230620b12Sfrantzen 		print_addr(&r->saddr, &r->smask, r->af);
51328964e80Sdhartmei 		printf(" ");
51428964e80Sdhartmei 	} else
51528964e80Sdhartmei 		printf("any ");
51628964e80Sdhartmei 	printf("to ");
517032e40b7Sdhartmei 	if (!PF_AZERO(&r->daddr.addr, r->af) || !PF_AZERO(&r->dmask, r->af)) {
518e7bd5eebSdhartmei 		if (r->dnot)
51914a9b182Skjell 			printf("! ");
52030620b12Sfrantzen 		print_addr(&r->daddr, &r->dmask, r->af);
52128964e80Sdhartmei 		printf(" ");
52228964e80Sdhartmei 	} else
52328964e80Sdhartmei 		printf("any ");
52480edb1f0Sdhartmei 	if (r->dport) {
525cb07131dSkjell 		printf("port %u", ntohs(r->dport));
526cb07131dSkjell 		if (r->opts & PF_DPORT_RANGE)
527cb07131dSkjell 			printf(":%u", ntohs(r->dport2));
52880edb1f0Sdhartmei 	}
529f27db9bcSdhartmei 	if (!r->no) {
530cb07131dSkjell 		printf(" -> ");
53130620b12Sfrantzen 		print_addr(&r->raddr, NULL, r->af);
53228964e80Sdhartmei 		printf(" ");
53380edb1f0Sdhartmei 		if (r->rport) {
53414a9b182Skjell 			printf("port %u", ntohs(r->rport));
535cb07131dSkjell 			if (r->opts & PF_RPORT_RANGE)
536cb07131dSkjell 				printf(":*");
53780edb1f0Sdhartmei 		}
538f27db9bcSdhartmei 	}
53914a9b182Skjell 	printf("\n");
54014a9b182Skjell }
54114a9b182Skjell 
542bca2bf17Sdhartmei char *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
543bca2bf17Sdhartmei char *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
54499a73934Sderaadt 
54514a9b182Skjell void
54681a15e5dSderaadt print_status(struct pf_status *s)
54714a9b182Skjell {
548c474e331Shenning 	time_t runtime;
54999a73934Sderaadt 	int i;
550c474e331Shenning 	char statline[80];
55199a73934Sderaadt 
552c474e331Shenning 	runtime = time(NULL) - s->since;
553c474e331Shenning 
554*d85e4ad6Sdhartmei 	if (s->running) {
555*d85e4ad6Sdhartmei 		unsigned sec, min, hrs, day = runtime;
556*d85e4ad6Sdhartmei 
557*d85e4ad6Sdhartmei 		sec = day % 60;
558*d85e4ad6Sdhartmei 		day /= 60;
559*d85e4ad6Sdhartmei 		min = day % 60;
560*d85e4ad6Sdhartmei 		day /= 60;
561*d85e4ad6Sdhartmei 		hrs = day % 24;
562*d85e4ad6Sdhartmei 		day /= 24;
563c474e331Shenning 		snprintf(statline, sizeof(statline),
564*d85e4ad6Sdhartmei 		    "Status: Enabled for %u days %.2u:%.2u:%.2u",
565*d85e4ad6Sdhartmei 		    day, hrs, min, sec);
566*d85e4ad6Sdhartmei 	} else
567c474e331Shenning 		snprintf(statline, sizeof(statline), "Status: Disabled");
568c474e331Shenning 	printf("%-34s", statline);
569ae58c8acSdhartmei 	switch (s->debug) {
570ae58c8acSdhartmei 	case 0:
571c474e331Shenning 		printf("%25s\n\n", "Debug: None");
572ae58c8acSdhartmei 		break;
573ae58c8acSdhartmei 	case 1:
574c474e331Shenning 		printf("%25s\n\n", "Debug: Urgent");
575ae58c8acSdhartmei 		break;
576ae58c8acSdhartmei 	case 2:
577c474e331Shenning 		printf("%25s\n\n", "Debug: Misc");
578ae58c8acSdhartmei 		break;
579ae58c8acSdhartmei 	}
580c474e331Shenning 	if (s->ifname[0] != 0) {
581c474e331Shenning 		printf("Interface Stats for %-16s %5s %16s\n",
582c474e331Shenning 		    s->ifname, "IPv4", "IPv6");
583c474e331Shenning 		printf("  %-25s %14llu %16llu\n", "Bytes In",
584c474e331Shenning 		    s->bcounters[0][PF_IN], s->bcounters[1][PF_IN]);
585c474e331Shenning 		printf("  %-25s %14llu %16llu\n", "Bytes Out",
586c474e331Shenning 		    s->bcounters[0][PF_OUT], s->bcounters[1][PF_OUT]);
587c474e331Shenning 		printf("  Packets In\n");
588c474e331Shenning 		printf("    %-23s %14llu %16llu\n", "Passed",
58930620b12Sfrantzen 		    s->pcounters[0][PF_IN][PF_PASS],
590c474e331Shenning 		    s->pcounters[1][PF_IN][PF_PASS]);
591c474e331Shenning 		printf("    %-23s %14llu %16llu\n", "Blocked",
592c474e331Shenning 		    s->pcounters[0][PF_IN][PF_DROP],
59330620b12Sfrantzen 		    s->pcounters[1][PF_IN][PF_DROP]);
594c474e331Shenning 		printf("  Packets Out\n");
595c474e331Shenning 		printf("    %-23s %14llu %16llu\n", "Passed",
59630620b12Sfrantzen 		    s->pcounters[0][PF_OUT][PF_PASS],
597c474e331Shenning 		    s->pcounters[1][PF_OUT][PF_PASS]);
598c474e331Shenning 		printf("    %-23s %14llu %16llu\n\n", "Blocked",
599c474e331Shenning 		    s->pcounters[0][PF_OUT][PF_DROP],
60030620b12Sfrantzen 		    s->pcounters[1][PF_OUT][PF_DROP]);
601c474e331Shenning 	}
602c474e331Shenning 	printf("%-27s %14s %16s\n", "State Table", "Total", "Rate");
603c474e331Shenning 	printf("  %-25s %14u %14s\n", "current entries", s->states, "");
604c474e331Shenning 	for (i = 0; i < FCNT_MAX; i++) {
605c474e331Shenning 		printf("  %-25s %14lld ", pf_fcounters[i],
60684976600Sderaadt 			    s->fcounters[i]);
607c474e331Shenning 		if (runtime > 0)
608c474e331Shenning 			printf("%14.1f/s\n",
609c474e331Shenning 			    (double)s->fcounters[i] / (double)runtime);
610c474e331Shenning 		else
611c474e331Shenning 			printf("%14s\n", "");
612c474e331Shenning 	}
61399a73934Sderaadt 	printf("Counters\n");
614c474e331Shenning 	for (i = 0; i < PFRES_MAX; i++) {
615c474e331Shenning 		printf("  %-25s %14lld ", pf_reasons[i],
61699a73934Sderaadt 		    s->counters[i]);
617c474e331Shenning 		if (runtime > 0)
618c474e331Shenning 			printf("%14.1f/s\n",
619c474e331Shenning 			    (double)s->counters[i] / (double)runtime);
620c474e331Shenning 		else
621c474e331Shenning 			printf("%14s\n", "");
622c474e331Shenning 	}
62314a9b182Skjell }
62414a9b182Skjell 
62514a9b182Skjell void
62681a15e5dSderaadt print_rule(struct pf_rule *r)
62714a9b182Skjell {
628cc5f0329Sdhartmei 	int i, opts;
629cc5f0329Sdhartmei 
63078baf774Sdhartmei 	printf("@%d ", r->nr);
6318418a02fSprovos 	if (r->action == PF_PASS)
63214a9b182Skjell 		printf("pass ");
633b996d042Sdhartmei 	else if (r->action == PF_DROP) {
63414a9b182Skjell 		printf("block ");
6351f77cc8aSpb 		if (r->rule_flag & PFRULE_RETURNRST) {
6361f77cc8aSpb 			if (!r->return_ttl)
63714a9b182Skjell 				printf("return-rst ");
6381f77cc8aSpb 			else
6391f77cc8aSpb 				printf("return-rst(ttl %d) ", r->return_ttl);
6401f77cc8aSpb 		} else if (r->return_icmp) {
6417d27d81aSdhartmei 			const struct icmpcodeent *ic;
642b996d042Sdhartmei 
643d14c53d7Swilfried 			if (r->af != AF_INET6)
644b996d042Sdhartmei 				printf("return-icmp");
645d14c53d7Swilfried 			else
646d14c53d7Swilfried 				printf("return-icmp6");
647b996d042Sdhartmei 			ic = geticmpcodebynumber(r->return_icmp >> 8,
648d14c53d7Swilfried 			    r->return_icmp & 255, r->af);
649d14c53d7Swilfried 
650d14c53d7Swilfried 			if (ic == NULL)
651d14c53d7Swilfried 				printf("(%u) ", r->return_icmp & 255);
6520eed2997Sdhartmei 			else if ((r->af != AF_INET6 && ic->code !=
6530eed2997Sdhartmei 			    ICMP_UNREACH_PORT) ||
6540eed2997Sdhartmei 			    (r->af == AF_INET6 && ic->code !=
6550eed2997Sdhartmei 			    ICMP6_DST_UNREACH_NOPORT))
656b996d042Sdhartmei 				printf("(%s) ", ic->name);
657b996d042Sdhartmei 			else
658b996d042Sdhartmei 				printf(" ");
659b996d042Sdhartmei 		}
660cc42ff11Sfrantzen 	} else {
661b996d042Sdhartmei 		printf("scrub ");
662cc42ff11Sfrantzen 	}
66314a9b182Skjell 	if (r->direction == 0)
66414a9b182Skjell 		printf("in ");
66514a9b182Skjell 	else
66614a9b182Skjell 		printf("out ");
6677242ce7aSdhartmei 	if (r->log == 1)
66814a9b182Skjell 		printf("log ");
6697242ce7aSdhartmei 	else if (r->log == 2)
6707242ce7aSdhartmei 		printf("log-all ");
67114a9b182Skjell 	if (r->quick)
67214a9b182Skjell 		printf("quick ");
67314a9b182Skjell 	if (r->ifname[0])
67414a9b182Skjell 		printf("on %s ", r->ifname);
675cb3a4e31Sjasoni 	if (r->rt) {
676cb3a4e31Sjasoni 		if (r->rt == PF_ROUTETO)
677cb3a4e31Sjasoni 			printf("route-to ");
678cb3a4e31Sjasoni 		else if (r->rt == PF_DUPTO)
679cb3a4e31Sjasoni 			printf("dup-to ");
680cb3a4e31Sjasoni 		else if (r->rt == PF_FASTROUTE)
681cb3a4e31Sjasoni 			printf("fastroute");
682cb3a4e31Sjasoni 		if (r->rt_ifname[0])
683cb3a4e31Sjasoni 			printf("%s", r->rt_ifname);
684cb3a4e31Sjasoni 		if (r->af && !PF_AZERO(&r->rt_addr, r->af)) {
685032e40b7Sdhartmei 			struct pf_addr_wrap aw;
686032e40b7Sdhartmei 
687032e40b7Sdhartmei 			aw.addr = r->rt_addr;
688032e40b7Sdhartmei 			aw.addr_dyn = NULL;
689cb3a4e31Sjasoni 			printf(":");
690032e40b7Sdhartmei 			print_addr(&aw, NULL, r->af);
691cb3a4e31Sjasoni 		}
692cb3a4e31Sjasoni 		printf(" ");
693cb3a4e31Sjasoni 	}
69430620b12Sfrantzen 	if (r->af) {
69530620b12Sfrantzen 		if (r->af == AF_INET)
69630620b12Sfrantzen 			printf("inet ");
69730620b12Sfrantzen 		else
69830620b12Sfrantzen 			printf("inet6 ");
69930620b12Sfrantzen 	}
70014a9b182Skjell 	if (r->proto) {
70114a9b182Skjell 		struct protoent *p = getprotobynumber(r->proto);
702ed99c291Sderaadt 
70314a9b182Skjell 		if (p != NULL)
70414a9b182Skjell 			printf("proto %s ", p->p_name);
70514a9b182Skjell 		else
70614a9b182Skjell 			printf("proto %u ", r->proto);
70714a9b182Skjell 	}
70815e76891Sdhartmei 	print_fromto(&r->src, &r->dst, r->af, r->proto);
709c16ab608Sdhartmei 	if (r->uid.op)
710c16ab608Sdhartmei 		print_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user");
711c16ab608Sdhartmei 	if (r->gid.op)
712c16ab608Sdhartmei 		print_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group");
71314a9b182Skjell 	if (r->flags || r->flagset) {
71414a9b182Skjell 		printf("flags ");
71514a9b182Skjell 		print_flags(r->flags);
71614a9b182Skjell 		printf("/");
71714a9b182Skjell 		print_flags(r->flagset);
71814a9b182Skjell 		printf(" ");
71914a9b182Skjell 	}
720082ebc44Swilfried 	if (r->type) {
7217d27d81aSdhartmei 		const struct icmptypeent *p;
722082ebc44Swilfried 
723d14c53d7Swilfried 		p = geticmptypebynumber(r->type-1, r->af);
724d14c53d7Swilfried 		if (r->af != AF_INET6)
725d14c53d7Swilfried 			printf("icmp-type");
726082ebc44Swilfried 		else
727d14c53d7Swilfried 			printf("ipv6-icmp-type");
728d14c53d7Swilfried 		if (p != NULL)
729d14c53d7Swilfried 			printf(" %s ", p->name);
730d14c53d7Swilfried 		else
731d14c53d7Swilfried 			printf(" %u ", r->type-1);
732082ebc44Swilfried 		if (r->code) {
7337d27d81aSdhartmei 			const struct icmpcodeent *p;
734082ebc44Swilfried 
735d14c53d7Swilfried 			p = geticmpcodebynumber(r->type-1, r->code-1, r->af);
736082ebc44Swilfried 			if (p != NULL)
737082ebc44Swilfried 				printf("code %s ", p->name);
738082ebc44Swilfried 			else
73914a9b182Skjell 				printf("code %u ", r->code-1);
740082ebc44Swilfried 		}
741082ebc44Swilfried 	}
742b96c47abSfrantzen 	if (r->keep_state == PF_STATE_NORMAL)
74314a9b182Skjell 		printf("keep state ");
744b96c47abSfrantzen 	else if (r->keep_state == PF_STATE_MODULATE)
745b96c47abSfrantzen 		printf("modulate state ");
746cc5f0329Sdhartmei 	opts = 0;
747b3c86969Sdhartmei 	if (r->max_states)
748cc5f0329Sdhartmei 		opts = 1;
749cc5f0329Sdhartmei 	for (i = 0; !opts && i < PFTM_MAX; ++i)
750cc5f0329Sdhartmei 		if (r->timeout[i])
751cc5f0329Sdhartmei 			opts = 1;
752cc5f0329Sdhartmei 	if (opts) {
753cc5f0329Sdhartmei 		printf("(");
754cc5f0329Sdhartmei 		if (r->max_states) {
755cc5f0329Sdhartmei 			printf("max %u", r->max_states);
756cc5f0329Sdhartmei 			opts = 0;
757cc5f0329Sdhartmei 		}
758cc5f0329Sdhartmei 		for (i = 0; i < PFTM_MAX; ++i)
759cc5f0329Sdhartmei 			if (r->timeout[i]) {
760cc5f0329Sdhartmei 				if (!opts)
761cc5f0329Sdhartmei 					printf(", ");
762cc5f0329Sdhartmei 				opts = 0;
763cc5f0329Sdhartmei 				printf("%s %u", pf_timeouts[i].name,
764cc5f0329Sdhartmei 				    r->timeout[i]);
765cc5f0329Sdhartmei 			}
766cc5f0329Sdhartmei 		printf(") ");
767cc5f0329Sdhartmei 	}
7686673dee2Sdhartmei 	if (r->rule_flag & PFRULE_FRAGMENT)
7696673dee2Sdhartmei 		printf("fragment ");
77067d2a440Sprovos 	if (r->rule_flag & PFRULE_NODF)
77167d2a440Sprovos 		printf("no-df ");
772e258bfd4Sprovos 	if (r->min_ttl)
77334c76dcbSprovos 		printf("min-ttl %d ", r->min_ttl);
774cfa91859Sjasoni 	if (r->max_mss)
775cfa91859Sjasoni 		printf("max-mss %d ", r->max_mss);
776f48d62b3Sdhartmei 	if (r->allow_opts)
777f48d62b3Sdhartmei 		printf("allow-opts ");
778b02af636Sfrantzen 	if (r->action == PF_SCRUB) {
779b02af636Sfrantzen 		if (r->rule_flag & PFRULE_FRAGDROP)
780b02af636Sfrantzen 			printf("fragment drop-ovl ");
781b02af636Sfrantzen 		else if (r->rule_flag & PFRULE_FRAGCROP)
782b02af636Sfrantzen 			printf("fragment crop ");
783b02af636Sfrantzen 		else
784b02af636Sfrantzen 			printf("fragment reassemble ");
785b02af636Sfrantzen 	}
786455ef0c1Sdhartmei 	if (r->label[0])
787455ef0c1Sdhartmei 		printf("label %s", r->label);
78867d2a440Sprovos 
78914a9b182Skjell 	printf("\n");
79014a9b182Skjell }
79114a9b182Skjell 
7921f8f21bdSmillert int
793ff352a37Smarkus parse_flags(char *s)
79414a9b182Skjell {
795ff352a37Smarkus 	char *p, *q;
79614a9b182Skjell 	u_int8_t f = 0;
79781a15e5dSderaadt 
798ff352a37Smarkus 	for (p = s; *p; p++) {
799ff352a37Smarkus 		if ((q = strchr(tcpflags, *p)) == NULL)
800ff352a37Smarkus 			return -1;
801ff352a37Smarkus 		else
802ff352a37Smarkus 			f |= 1 << (q - tcpflags);
80314a9b182Skjell 	}
804bc795af0Shugh 	return (f ? f : PF_TH_ALL);
80514a9b182Skjell }
806