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