xref: /openbsd/sbin/pfctl/pfctl_parser.c (revision 132c30cc)
1*132c30ccShenning /*	$OpenBSD: pfctl_parser.c,v 1.147 2003/03/27 18:01:57 henning 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>
5294e9410bShenning #include <ifaddrs.h>
5314a9b182Skjell 
5414a9b182Skjell #include "pfctl_parser.h"
55eb824e11Sderaadt #include "pfctl.h"
5614a9b182Skjell 
575d9ac2dcSdhartmei void		 print_op (u_int8_t, const char *, const char *);
58*132c30ccShenning void		 print_port (u_int8_t, u_int16_t, u_int16_t, const char *);
595d9ac2dcSdhartmei void		 print_uid (u_int8_t, uid_t, uid_t, const char *);
60c16ab608Sdhartmei void		 print_gid (u_int8_t, gid_t, gid_t, const char *);
6181a15e5dSderaadt void		 print_flags (u_int8_t);
6215e76891Sdhartmei void		 print_fromto(struct pf_rule_addr *, struct pf_rule_addr *,
6344f5ed0aScedric 		    u_int8_t, u_int8_t, int);
6414a9b182Skjell 
65f2370d27Shenning struct node_host	*host_if(const char *, int);
66383ebbbfShenning struct node_host	*host_v4(const char *, int);
67f2370d27Shenning struct node_host	*host_v6(const char *, int);
68f2370d27Shenning struct node_host	*host_dns(const char *, int, int);
692a6c1abaShenning 
70bc795af0Shugh char *tcpflags = "FSRPAUEW";
7114a9b182Skjell 
727d27d81aSdhartmei static const struct icmptypeent icmp_type[] = {
73082ebc44Swilfried 	{ "echoreq",	ICMP_ECHO },
74082ebc44Swilfried 	{ "echorep",	ICMP_ECHOREPLY },
75082ebc44Swilfried 	{ "unreach",	ICMP_UNREACH },
76082ebc44Swilfried 	{ "squench",	ICMP_SOURCEQUENCH },
77082ebc44Swilfried 	{ "redir",	ICMP_REDIRECT },
78082ebc44Swilfried 	{ "althost",	ICMP_ALTHOSTADDR },
79082ebc44Swilfried 	{ "routeradv",	ICMP_ROUTERADVERT },
80082ebc44Swilfried 	{ "routersol",	ICMP_ROUTERSOLICIT },
81082ebc44Swilfried 	{ "timex",	ICMP_TIMXCEED },
82082ebc44Swilfried 	{ "paramprob",	ICMP_PARAMPROB },
83082ebc44Swilfried 	{ "timereq",	ICMP_TSTAMP },
84082ebc44Swilfried 	{ "timerep",	ICMP_TSTAMPREPLY },
85082ebc44Swilfried 	{ "inforeq",	ICMP_IREQ },
86082ebc44Swilfried 	{ "inforep",	ICMP_IREQREPLY },
87082ebc44Swilfried 	{ "maskreq",	ICMP_MASKREQ },
8802cbcc9eSwilfried 	{ "maskrep",	ICMP_MASKREPLY },
8902cbcc9eSwilfried 	{ "trace",	ICMP_TRACEROUTE },
9002cbcc9eSwilfried 	{ "dataconv",	ICMP_DATACONVERR },
9102cbcc9eSwilfried 	{ "mobredir",	ICMP_MOBILE_REDIRECT },
9202cbcc9eSwilfried 	{ "ipv6-where",	ICMP_IPV6_WHEREAREYOU },
9302cbcc9eSwilfried 	{ "ipv6-here",	ICMP_IPV6_IAMHERE },
9402cbcc9eSwilfried 	{ "mobregreq",	ICMP_MOBILE_REGREQUEST },
9502cbcc9eSwilfried 	{ "mobregrep",	ICMP_MOBILE_REGREPLY },
9602cbcc9eSwilfried 	{ "skip",	ICMP_SKIP },
9702cbcc9eSwilfried 	{ "photuris",	ICMP_PHOTURIS }
98082ebc44Swilfried };
99082ebc44Swilfried 
1007d27d81aSdhartmei static const struct icmptypeent icmp6_type[] = {
10130620b12Sfrantzen 	{ "unreach",	ICMP6_DST_UNREACH },
10230620b12Sfrantzen 	{ "toobig",	ICMP6_PACKET_TOO_BIG },
10330620b12Sfrantzen 	{ "timex",	ICMP6_TIME_EXCEEDED },
10430620b12Sfrantzen 	{ "paramprob",	ICMP6_PARAM_PROB },
10530620b12Sfrantzen 	{ "echoreq",	ICMP6_ECHO_REQUEST },
10630620b12Sfrantzen 	{ "echorep",	ICMP6_ECHO_REPLY },
10730620b12Sfrantzen 	{ "groupqry",	ICMP6_MEMBERSHIP_QUERY },
10830620b12Sfrantzen 	{ "listqry",	MLD6_LISTENER_QUERY },
10930620b12Sfrantzen 	{ "grouprep",	ICMP6_MEMBERSHIP_REPORT },
11030620b12Sfrantzen 	{ "listenrep",	MLD6_LISTENER_REPORT },
11130620b12Sfrantzen 	{ "groupterm",	ICMP6_MEMBERSHIP_REDUCTION },
11230620b12Sfrantzen 	{ "listendone", MLD6_LISTENER_DONE },
11330620b12Sfrantzen 	{ "routersol",	ND_ROUTER_SOLICIT },
11430620b12Sfrantzen 	{ "routeradv",	ND_ROUTER_ADVERT },
11530620b12Sfrantzen 	{ "neighbrsol", ND_NEIGHBOR_SOLICIT },
11630620b12Sfrantzen 	{ "neighbradv", ND_NEIGHBOR_ADVERT },
11730620b12Sfrantzen 	{ "redir",	ND_REDIRECT },
11830620b12Sfrantzen 	{ "routrrenum", ICMP6_ROUTER_RENUMBERING },
11930620b12Sfrantzen 	{ "wrureq",	ICMP6_WRUREQUEST },
12030620b12Sfrantzen 	{ "wrurep",	ICMP6_WRUREPLY },
12130620b12Sfrantzen 	{ "fqdnreq",	ICMP6_FQDN_QUERY },
12230620b12Sfrantzen 	{ "fqdnrep",	ICMP6_FQDN_REPLY },
12330620b12Sfrantzen 	{ "niqry",	ICMP6_NI_QUERY },
12430620b12Sfrantzen 	{ "nirep",	ICMP6_NI_REPLY },
12530620b12Sfrantzen 	{ "mtraceresp",	MLD6_MTRACE_RESP },
12630620b12Sfrantzen 	{ "mtrace",	MLD6_MTRACE }
12730620b12Sfrantzen };
12830620b12Sfrantzen 
1297d27d81aSdhartmei static const struct icmpcodeent icmp_code[] = {
130082ebc44Swilfried 	{ "net-unr",		ICMP_UNREACH,	ICMP_UNREACH_NET },
131082ebc44Swilfried 	{ "host-unr",		ICMP_UNREACH,	ICMP_UNREACH_HOST },
132082ebc44Swilfried 	{ "proto-unr",		ICMP_UNREACH,	ICMP_UNREACH_PROTOCOL },
133082ebc44Swilfried 	{ "port-unr",		ICMP_UNREACH,	ICMP_UNREACH_PORT },
134082ebc44Swilfried 	{ "needfrag",		ICMP_UNREACH,	ICMP_UNREACH_NEEDFRAG },
135082ebc44Swilfried 	{ "srcfail",		ICMP_UNREACH,	ICMP_UNREACH_SRCFAIL },
136082ebc44Swilfried 	{ "net-unk",		ICMP_UNREACH,	ICMP_UNREACH_NET_UNKNOWN },
137082ebc44Swilfried 	{ "host-unk",		ICMP_UNREACH,	ICMP_UNREACH_HOST_UNKNOWN },
138082ebc44Swilfried 	{ "isolate",		ICMP_UNREACH,	ICMP_UNREACH_ISOLATED },
139082ebc44Swilfried 	{ "net-prohib",		ICMP_UNREACH,	ICMP_UNREACH_NET_PROHIB },
140082ebc44Swilfried 	{ "host-prohib",	ICMP_UNREACH,	ICMP_UNREACH_HOST_PROHIB },
141082ebc44Swilfried 	{ "net-tos",		ICMP_UNREACH,	ICMP_UNREACH_TOSNET },
142082ebc44Swilfried 	{ "host-tos",		ICMP_UNREACH,	ICMP_UNREACH_TOSHOST },
143082ebc44Swilfried 	{ "filter-prohib",	ICMP_UNREACH,	ICMP_UNREACH_FILTER_PROHIB },
144082ebc44Swilfried 	{ "host-preced",	ICMP_UNREACH,	ICMP_UNREACH_HOST_PRECEDENCE },
145082ebc44Swilfried 	{ "cutoff-preced",	ICMP_UNREACH,	ICMP_UNREACH_PRECEDENCE_CUTOFF },
146082ebc44Swilfried 	{ "redir-net",		ICMP_REDIRECT,	ICMP_REDIRECT_NET },
147082ebc44Swilfried 	{ "redir-host",		ICMP_REDIRECT,	ICMP_REDIRECT_HOST },
148082ebc44Swilfried 	{ "redir-tos-net",	ICMP_REDIRECT,	ICMP_REDIRECT_TOSNET },
149082ebc44Swilfried 	{ "redir-tos-host",	ICMP_REDIRECT,	ICMP_REDIRECT_TOSHOST },
15002cbcc9eSwilfried 	{ "normal-adv",		ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NORMAL },
15102cbcc9eSwilfried 	{ "common-adv",		ICMP_ROUTERADVERT, ICMP_ROUTERADVERT_NOROUTE_COMMON },
152082ebc44Swilfried 	{ "transit",		ICMP_TIMXCEED,	ICMP_TIMXCEED_INTRANS },
153082ebc44Swilfried 	{ "reassemb",		ICMP_TIMXCEED,	ICMP_TIMXCEED_REASS },
154082ebc44Swilfried 	{ "badhead",		ICMP_PARAMPROB,	ICMP_PARAMPROB_ERRATPTR },
155082ebc44Swilfried 	{ "optmiss",		ICMP_PARAMPROB,	ICMP_PARAMPROB_OPTABSENT },
15602cbcc9eSwilfried 	{ "badlen",		ICMP_PARAMPROB,	ICMP_PARAMPROB_LENGTH },
15702cbcc9eSwilfried 	{ "unknown-ind",	ICMP_PHOTURIS,	ICMP_PHOTURIS_UNKNOWN_INDEX },
15802cbcc9eSwilfried 	{ "auth-fail",		ICMP_PHOTURIS,	ICMP_PHOTURIS_AUTH_FAILED },
15902cbcc9eSwilfried 	{ "decrypt-fail",	ICMP_PHOTURIS,	ICMP_PHOTURIS_DECRYPT_FAILED }
160082ebc44Swilfried };
161082ebc44Swilfried 
1627d27d81aSdhartmei static const struct icmpcodeent icmp6_code[] = {
1631d32ee3bSdhartmei 	{ "admin-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN },
1641d32ee3bSdhartmei 	{ "noroute-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE },
16530620b12Sfrantzen 	{ "notnbr-unr",	ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOTNEIGHBOR },
16630620b12Sfrantzen 	{ "beyond-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_BEYONDSCOPE },
16730620b12Sfrantzen 	{ "addr-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR },
16830620b12Sfrantzen 	{ "port-unr", ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT },
16930620b12Sfrantzen 	{ "transit", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT },
17030620b12Sfrantzen 	{ "reassemb", ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY },
17130620b12Sfrantzen 	{ "badhead", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER },
17230620b12Sfrantzen 	{ "nxthdr", ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER },
17330620b12Sfrantzen 	{ "redironlink", ND_REDIRECT, ND_REDIRECT_ONLINK },
17430620b12Sfrantzen 	{ "redirrouter", ND_REDIRECT, ND_REDIRECT_ROUTER }
17530620b12Sfrantzen };
17630620b12Sfrantzen 
177d593fb91Sdrahn const struct pf_timeout pf_timeouts[] = {
178d593fb91Sdrahn 	{ "tcp.first",		PFTM_TCP_FIRST_PACKET },
179d593fb91Sdrahn 	{ "tcp.opening",	PFTM_TCP_OPENING },
180d593fb91Sdrahn 	{ "tcp.established",	PFTM_TCP_ESTABLISHED },
181d593fb91Sdrahn 	{ "tcp.closing",	PFTM_TCP_CLOSING },
182d593fb91Sdrahn 	{ "tcp.finwait",	PFTM_TCP_FIN_WAIT },
183d593fb91Sdrahn 	{ "tcp.closed",		PFTM_TCP_CLOSED },
184d593fb91Sdrahn 	{ "udp.first",		PFTM_UDP_FIRST_PACKET },
185d593fb91Sdrahn 	{ "udp.single",		PFTM_UDP_SINGLE },
186d593fb91Sdrahn 	{ "udp.multiple",	PFTM_UDP_MULTIPLE },
187d593fb91Sdrahn 	{ "icmp.first",		PFTM_ICMP_FIRST_PACKET },
188d593fb91Sdrahn 	{ "icmp.error",		PFTM_ICMP_ERROR_REPLY },
189d593fb91Sdrahn 	{ "other.first",	PFTM_OTHER_FIRST_PACKET },
190d593fb91Sdrahn 	{ "other.single",	PFTM_OTHER_SINGLE },
191d593fb91Sdrahn 	{ "other.multiple",	PFTM_OTHER_MULTIPLE },
192d593fb91Sdrahn 	{ "frag",		PFTM_FRAG },
193d593fb91Sdrahn 	{ "interval",		PFTM_INTERVAL },
194d593fb91Sdrahn 	{ NULL,			0 }
195d593fb91Sdrahn };
196d593fb91Sdrahn 
1977d27d81aSdhartmei const struct icmptypeent *
198bb9f691eSmcbride geticmptypebynumber(u_int8_t type, sa_family_t af)
199082ebc44Swilfried {
200ed99c291Sderaadt 	unsigned int	i;
201082ebc44Swilfried 
202d14c53d7Swilfried 	if (af != AF_INET6) {
203e4ebe044Shenning 		for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0]));
204e4ebe044Shenning 		    i++) {
205082ebc44Swilfried 			if (type == icmp_type[i].type)
206082ebc44Swilfried 				return (&icmp_type[i]);
207082ebc44Swilfried 		}
20830620b12Sfrantzen 	} else {
20930620b12Sfrantzen 		for (i=0; i < (sizeof (icmp6_type) /
21030620b12Sfrantzen 		    sizeof(icmp6_type[0])); i++) {
21130620b12Sfrantzen 			if (type == icmp6_type[i].type)
21230620b12Sfrantzen 				 return (&icmp6_type[i]);
21330620b12Sfrantzen 		}
21430620b12Sfrantzen 	}
21530620b12Sfrantzen 	return (NULL);
216082ebc44Swilfried }
217082ebc44Swilfried 
2187d27d81aSdhartmei const struct icmptypeent *
219bb9f691eSmcbride geticmptypebyname(char *w, sa_family_t af)
220082ebc44Swilfried {
221ed99c291Sderaadt 	unsigned int	i;
222082ebc44Swilfried 
223d14c53d7Swilfried 	if (af != AF_INET6) {
224e4ebe044Shenning 		for (i=0; i < (sizeof (icmp_type) / sizeof(icmp_type[0]));
225e4ebe044Shenning 		    i++) {
226082ebc44Swilfried 			if (!strcmp(w, icmp_type[i].name))
227082ebc44Swilfried 				return (&icmp_type[i]);
228082ebc44Swilfried 		}
22930620b12Sfrantzen 	} else {
23030620b12Sfrantzen 		for (i=0; i < (sizeof (icmp6_type) /
23130620b12Sfrantzen 		    sizeof(icmp6_type[0])); i++) {
23230620b12Sfrantzen 			if (!strcmp(w, icmp6_type[i].name))
23330620b12Sfrantzen 				return (&icmp6_type[i]);
23430620b12Sfrantzen 		}
23530620b12Sfrantzen 	}
23630620b12Sfrantzen 	return (NULL);
237082ebc44Swilfried }
238082ebc44Swilfried 
2397d27d81aSdhartmei const struct icmpcodeent *
240bb9f691eSmcbride geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af)
241082ebc44Swilfried {
242ed99c291Sderaadt 	unsigned int	i;
243082ebc44Swilfried 
244d14c53d7Swilfried 	if (af != AF_INET6) {
245e4ebe044Shenning 		for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0]));
246e4ebe044Shenning 		    i++) {
24730620b12Sfrantzen 			if (type == icmp_code[i].type &&
24830620b12Sfrantzen 			    code == icmp_code[i].code)
249082ebc44Swilfried 				return (&icmp_code[i]);
250082ebc44Swilfried 		}
25130620b12Sfrantzen 	} else {
25230620b12Sfrantzen 		for (i=0; i < (sizeof (icmp6_code) /
25330620b12Sfrantzen 		   sizeof(icmp6_code[0])); i++) {
25430620b12Sfrantzen 			if (type == icmp6_code[i].type &&
25530620b12Sfrantzen 			    code == icmp6_code[i].code)
25630620b12Sfrantzen 				return (&icmp6_code[i]);
25730620b12Sfrantzen 		}
25830620b12Sfrantzen 	}
25930620b12Sfrantzen 	return (NULL);
260082ebc44Swilfried }
261082ebc44Swilfried 
2627d27d81aSdhartmei const struct icmpcodeent *
263bb9f691eSmcbride geticmpcodebyname(u_long type, char *w, sa_family_t af)
264082ebc44Swilfried {
265ed99c291Sderaadt 	unsigned int	i;
266082ebc44Swilfried 
267d14c53d7Swilfried 	if (af != AF_INET6) {
268e4ebe044Shenning 		for (i=0; i < (sizeof (icmp_code) / sizeof(icmp_code[0]));
269e4ebe044Shenning 		    i++) {
27030620b12Sfrantzen 			if (type == icmp_code[i].type &&
27130620b12Sfrantzen 			    !strcmp(w, icmp_code[i].name))
272082ebc44Swilfried 				return (&icmp_code[i]);
273082ebc44Swilfried 		}
27430620b12Sfrantzen 	} else {
27530620b12Sfrantzen 		for (i=0; i < (sizeof (icmp6_code) /
27630620b12Sfrantzen 		    sizeof(icmp6_code[0])); i++) {
27730620b12Sfrantzen 			if (type == icmp6_code[i].type &&
27830620b12Sfrantzen 			    !strcmp(w, icmp6_code[i].name))
27930620b12Sfrantzen 				return (&icmp6_code[i]);
28030620b12Sfrantzen 		}
28130620b12Sfrantzen 	}
28230620b12Sfrantzen 	return (NULL);
28330620b12Sfrantzen }
28430620b12Sfrantzen 
28581a15e5dSderaadt void
2865d9ac2dcSdhartmei print_op(u_int8_t op, const char *a1, const char *a2)
2875d9ac2dcSdhartmei {
2885d9ac2dcSdhartmei 	if (op == PF_OP_IRG)
2895d9ac2dcSdhartmei 		printf("%s >< %s ", a1, a2);
2905d9ac2dcSdhartmei 	else if (op == PF_OP_XRG)
2915d9ac2dcSdhartmei 		printf("%s <> %s ", a1, a2);
2921308506cShenning 	else if (op == PF_OP_EQ)
2935d9ac2dcSdhartmei 		printf("= %s ", a1);
2941308506cShenning 	else if (op == PF_OP_NE)
2955d9ac2dcSdhartmei 		printf("!= %s ", a1);
2961308506cShenning 	else if (op == PF_OP_LT)
2975d9ac2dcSdhartmei 		printf("< %s ", a1);
2985d9ac2dcSdhartmei 	else if (op == PF_OP_LE)
2995d9ac2dcSdhartmei 		printf("<= %s ", a1);
3005d9ac2dcSdhartmei 	else if (op == PF_OP_GT)
3015d9ac2dcSdhartmei 		printf("> %s ", a1);
3025d9ac2dcSdhartmei 	else if (op == PF_OP_GE)
3035d9ac2dcSdhartmei 		printf(">= %s ", a1);
3048da4e377Smcbride 	else if (op == PF_OP_RRG)
3058da4e377Smcbride 		printf("%s:%s ", a1, a2);
3065d9ac2dcSdhartmei }
3075d9ac2dcSdhartmei 
3085d9ac2dcSdhartmei void
309*132c30ccShenning print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto)
31014a9b182Skjell {
311e31d21c9Sdhartmei 	char		 a1[6], a2[6];
312e4ebe044Shenning 	struct servent	*s;
31381a15e5dSderaadt 
314e4ebe044Shenning 	s = getservbyport(p1, proto);
31514a9b182Skjell 	p1 = ntohs(p1);
31614a9b182Skjell 	p2 = ntohs(p2);
3175d9ac2dcSdhartmei 	snprintf(a1, sizeof(a1), "%u", p1);
3185d9ac2dcSdhartmei 	snprintf(a2, sizeof(a2), "%u", p2);
31914a9b182Skjell 	printf("port ");
3205d9ac2dcSdhartmei 	if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE))
3215d9ac2dcSdhartmei 		print_op(op, s->s_name, a2);
32214a9b182Skjell 	else
3235d9ac2dcSdhartmei 		print_op(op, a1, a2);
3245d9ac2dcSdhartmei }
3255d9ac2dcSdhartmei 
3265d9ac2dcSdhartmei void
3275d9ac2dcSdhartmei print_uid(u_int8_t op, uid_t u1, uid_t u2, const char *t)
3285d9ac2dcSdhartmei {
329d8fcd2dfSdhartmei 	char	a1[11], a2[11];
3305d9ac2dcSdhartmei 
3315d9ac2dcSdhartmei 	snprintf(a1, sizeof(a1), "%u", u1);
3325d9ac2dcSdhartmei 	snprintf(a2, sizeof(a2), "%u", u2);
3335d9ac2dcSdhartmei 	printf("%s ", t);
3345d9ac2dcSdhartmei 	if (u1 == UID_MAX && (op == PF_OP_EQ || op == PF_OP_NE))
3355d9ac2dcSdhartmei 		print_op(op, "unknown", a2);
33614a9b182Skjell 	else
3375d9ac2dcSdhartmei 		print_op(op, a1, a2);
33814a9b182Skjell }
33914a9b182Skjell 
34081a15e5dSderaadt void
341c16ab608Sdhartmei print_gid(u_int8_t op, gid_t g1, gid_t g2, const char *t)
342c16ab608Sdhartmei {
343d8fcd2dfSdhartmei 	char	a1[11], a2[11];
344c16ab608Sdhartmei 
345c16ab608Sdhartmei 	snprintf(a1, sizeof(a1), "%u", g1);
346c16ab608Sdhartmei 	snprintf(a2, sizeof(a2), "%u", g2);
347c16ab608Sdhartmei 	printf("%s ", t);
348c16ab608Sdhartmei 	if (g1 == GID_MAX && (op == PF_OP_EQ || op == PF_OP_NE))
349c16ab608Sdhartmei 		print_op(op, "unknown", a2);
350c16ab608Sdhartmei 	else
351c16ab608Sdhartmei 		print_op(op, a1, a2);
352c16ab608Sdhartmei }
353c16ab608Sdhartmei 
354c16ab608Sdhartmei void
35514a9b182Skjell print_flags(u_int8_t f)
35614a9b182Skjell {
35714a9b182Skjell 	int	i;
35881a15e5dSderaadt 
359bc795af0Shugh 	for (i = 0; tcpflags[i]; ++i)
36014a9b182Skjell 		if (f & (1 << i))
36114a9b182Skjell 			printf("%c", tcpflags[i]);
36214a9b182Skjell }
36314a9b182Skjell 
36414a9b182Skjell void
36515e76891Sdhartmei print_fromto(struct pf_rule_addr *src, struct pf_rule_addr *dst,
36644f5ed0aScedric     sa_family_t af, u_int8_t proto, int verbose)
36715e76891Sdhartmei {
368d0b1df00Sdhartmei 	if (src->addr.type != PF_ADDR_NOROUTE &&
369d0b1df00Sdhartmei 	    dst->addr.type != PF_ADDR_NOROUTE &&
370bcf142a4Sdhartmei 	    PF_AZERO(&src->addr.v.a.addr, AF_INET6) &&
371bcf142a4Sdhartmei 	    PF_AZERO(&src->addr.v.a.mask, AF_INET6) &&
372bcf142a4Sdhartmei 	    !src->port_op && PF_AZERO(&dst->addr.v.a.addr, AF_INET6) &&
373bcf142a4Sdhartmei 	    PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && !dst->port_op)
37415e76891Sdhartmei 		printf("all ");
37515e76891Sdhartmei 	else {
37615e76891Sdhartmei 		printf("from ");
377d0b1df00Sdhartmei 		if (src->addr.type == PF_ADDR_NOROUTE)
37815e76891Sdhartmei 			printf("no-route ");
379bcf142a4Sdhartmei 		else if (PF_AZERO(&src->addr.v.a.addr, AF_INET6) &&
380bcf142a4Sdhartmei 		    PF_AZERO(&src->addr.v.a.mask, AF_INET6))
38115e76891Sdhartmei 			printf("any ");
38215e76891Sdhartmei 		else {
38315e76891Sdhartmei 			if (src->not)
38415e76891Sdhartmei 				printf("! ");
38544f5ed0aScedric 			print_addr(&src->addr, af, verbose);
38615e76891Sdhartmei 			printf(" ");
38715e76891Sdhartmei 		}
38815e76891Sdhartmei 		if (src->port_op)
38915e76891Sdhartmei 			print_port(src->port_op, src->port[0],
39015e76891Sdhartmei 			    src->port[1],
39115e76891Sdhartmei 			    proto == IPPROTO_TCP ? "tcp" : "udp");
39215e76891Sdhartmei 
39315e76891Sdhartmei 		printf("to ");
394d0b1df00Sdhartmei 		if (dst->addr.type == PF_ADDR_NOROUTE)
39515e76891Sdhartmei 			printf("no-route ");
396bcf142a4Sdhartmei 		else if (PF_AZERO(&dst->addr.v.a.addr, AF_INET6) &&
397bcf142a4Sdhartmei 		    PF_AZERO(&dst->addr.v.a.mask, AF_INET6))
39815e76891Sdhartmei 			printf("any ");
39915e76891Sdhartmei 		else {
40015e76891Sdhartmei 			if (dst->not)
40115e76891Sdhartmei 				printf("! ");
40244f5ed0aScedric 			print_addr(&dst->addr, af, verbose);
40315e76891Sdhartmei 			printf(" ");
40415e76891Sdhartmei 		}
40515e76891Sdhartmei 		if (dst->port_op)
40615e76891Sdhartmei 			print_port(dst->port_op, dst->port[0],
40715e76891Sdhartmei 			    dst->port[1],
40815e76891Sdhartmei 			    proto == IPPROTO_TCP ? "tcp" : "udp");
40915e76891Sdhartmei 	}
41015e76891Sdhartmei }
41115e76891Sdhartmei 
41215e76891Sdhartmei void
413e8793aa9Smcbride print_rule(struct pf_rule *r, int verbose)
414e8793aa9Smcbride {
415e8793aa9Smcbride 	switch (r->action) {
416e8793aa9Smcbride 	case PF_NAT:
417e8793aa9Smcbride 	case PF_NONAT:
41860927d26Sdhartmei 		print_nat(r, verbose);
419e8793aa9Smcbride 		break;
420e8793aa9Smcbride 	case PF_BINAT:
421e8793aa9Smcbride 	case PF_NOBINAT:
42260927d26Sdhartmei 		print_binat(r, verbose);
423e8793aa9Smcbride 		break;
424e8793aa9Smcbride 	case PF_RDR:
425e8793aa9Smcbride 	case PF_NORDR:
42660927d26Sdhartmei 		print_rdr(r, verbose);
427e8793aa9Smcbride 		break;
428e8793aa9Smcbride 	default:
429e8793aa9Smcbride 	case PF_PASS:
430e8793aa9Smcbride 	case PF_DROP:
431e8793aa9Smcbride 	case PF_SCRUB:
432e8793aa9Smcbride 		print_filter(r, verbose);
433e8793aa9Smcbride 		break;
434e8793aa9Smcbride 	}
435e8793aa9Smcbride }
436e8793aa9Smcbride 
437e8793aa9Smcbride void
438e0c302d0Smcbride print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2,
439e0c302d0Smcbride     sa_family_t af, int id)
4403a44df3cSmcbride {
4413a44df3cSmcbride 	struct pf_pooladdr	*pooladdr;
4423a44df3cSmcbride 
4436c917913Smcbride 	if ((TAILQ_FIRST(&pool->list) != NULL) &&
4446c917913Smcbride 	    TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL)
4453a44df3cSmcbride 		printf("{ ");
4463a44df3cSmcbride 	TAILQ_FOREACH(pooladdr, &pool->list, entries){
4473a44df3cSmcbride 		switch (id) {
448e8793aa9Smcbride 		case PF_NAT:
449e8793aa9Smcbride 		case PF_RDR:
450e8793aa9Smcbride 		case PF_BINAT:
45144f5ed0aScedric 			print_addr(&pooladdr->addr.addr, af, 0);
4523a44df3cSmcbride 			break;
453e8793aa9Smcbride 		case PF_PASS:
454bcf142a4Sdhartmei 			if (PF_AZERO(&pooladdr->addr.addr.v.a.addr, af))
4553b9b234fSmcbride 				printf("%s", pooladdr->ifname);
456790504a6Sdhartmei 			else {
4573a44df3cSmcbride 				printf("(%s ", pooladdr->ifname);
45844f5ed0aScedric 				print_addr(&pooladdr->addr.addr, af, 0);
4593a44df3cSmcbride 				printf(")");
4603b9b234fSmcbride 			}
4613a44df3cSmcbride 			break;
462e8793aa9Smcbride 		default:
463e8793aa9Smcbride 			break;
4643a44df3cSmcbride 		}
4653a44df3cSmcbride 		if (TAILQ_NEXT(pooladdr, entries) != NULL)
4663a44df3cSmcbride 			printf(", ");
4673a44df3cSmcbride 		else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL)
4683a44df3cSmcbride 			printf(" }");
4693a44df3cSmcbride 	}
470e0c302d0Smcbride 	switch (id) {
471e8793aa9Smcbride 	case PF_NAT:
472e0c302d0Smcbride 		if (p1 != PF_NAT_PROXY_PORT_LOW ||
473e0c302d0Smcbride 		    p2 != PF_NAT_PROXY_PORT_HIGH) {
474e0c302d0Smcbride 			if (p1 == p2)
475e0c302d0Smcbride 				printf(" port %u", p1);
476e0c302d0Smcbride 			else
477e0c302d0Smcbride 				printf(" port %u:%u", p1, p2);
478e0c302d0Smcbride 		}
479e0c302d0Smcbride 		break;
480e8793aa9Smcbride 	case PF_RDR:
481e0c302d0Smcbride 		if (p1) {
4828da4e377Smcbride 			printf(" port %u", p1);
4838da4e377Smcbride 			if (p2 && (p2 != p1))
4848da4e377Smcbride 				printf(":%u", p2);
485e0c302d0Smcbride 		}
486e0c302d0Smcbride 		break;
487e0c302d0Smcbride 	default:
488e0c302d0Smcbride 		break;
489e0c302d0Smcbride 	}
490e0c302d0Smcbride 	switch (pool->opts & PF_POOL_TYPEMASK) {
491e0c302d0Smcbride 	case PF_POOL_NONE:
492e0c302d0Smcbride 		break;
493e0c302d0Smcbride 	case PF_POOL_BITMASK:
494e0c302d0Smcbride 		printf(" bitmask");
495e0c302d0Smcbride 		break;
496e0c302d0Smcbride 	case PF_POOL_RANDOM:
497e0c302d0Smcbride 		printf(" random");
498e0c302d0Smcbride 		break;
499e0c302d0Smcbride 	case PF_POOL_SRCHASH:
5000436fa02Smcbride 		printf(" source-hash 0x%08x%08x%08x%08x",
501e0c302d0Smcbride 		    pool->key.key32[0], pool->key.key32[1],
502e0c302d0Smcbride 		    pool->key.key32[2], pool->key.key32[3]);
503e0c302d0Smcbride 		break;
504e0c302d0Smcbride 	case PF_POOL_ROUNDROBIN:
505e0c302d0Smcbride 		printf(" round-robin");
506e0c302d0Smcbride 		break;
507e0c302d0Smcbride 	}
508e0c302d0Smcbride 	if (pool->opts & PF_POOL_STATICPORT)
509e0c302d0Smcbride 		printf(" static-port");
5103a44df3cSmcbride }
5113a44df3cSmcbride 
5123a44df3cSmcbride void
51360927d26Sdhartmei print_nat(struct pf_rule *n, int verbose)
51414a9b182Skjell {
51560927d26Sdhartmei 	if (verbose)
51660927d26Sdhartmei 		printf("@%d ", n->nr);
5176ac94451Sdhartmei 	if (n->anchorname[0])
5186ac94451Sdhartmei 		printf("nat-anchor %s ", n->anchorname);
5196ac94451Sdhartmei 	else {
520e8793aa9Smcbride 		if (n->action == PF_NONAT)
521f27db9bcSdhartmei 			printf("no ");
522f27db9bcSdhartmei 		printf("nat ");
5236ac94451Sdhartmei 	}
52428964e80Sdhartmei 	if (n->ifname[0]) {
52528964e80Sdhartmei 		printf("on ");
526870b51d7Schris 		if (n->ifnot)
527870b51d7Schris 			printf("! ");
528870b51d7Schris 		printf("%s ", n->ifname);
52928964e80Sdhartmei 	}
530032e40b7Sdhartmei 	if (n->af) {
531032e40b7Sdhartmei 		if (n->af == AF_INET)
532032e40b7Sdhartmei 			printf("inet ");
533032e40b7Sdhartmei 		else
534032e40b7Sdhartmei 			printf("inet6 ");
535032e40b7Sdhartmei 	}
53680edb1f0Sdhartmei 	if (n->proto) {
537e4ebe044Shenning 		struct protoent	*p;
538ed99c291Sderaadt 
539e4ebe044Shenning 		if ((p = getprotobynumber(n->proto)) != NULL)
54080edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
54180edb1f0Sdhartmei 		else
54280edb1f0Sdhartmei 			printf("proto %u ", n->proto);
54380edb1f0Sdhartmei 	}
54444f5ed0aScedric 	print_fromto(&n->src, &n->dst, n->af, n->proto, verbose);
545e8793aa9Smcbride 	if (!n->anchorname[0] && (n->action == PF_NAT)) {
54628964e80Sdhartmei 		printf("-> ");
547e8793aa9Smcbride 		print_pool(&n->rpool, n->rpool.proxy_port[0],
548e8793aa9Smcbride 		    n->rpool.proxy_port[1], n->af, PF_NAT);
549f27db9bcSdhartmei 	}
55014a9b182Skjell 	printf("\n");
55114a9b182Skjell }
55214a9b182Skjell 
55314a9b182Skjell void
55460927d26Sdhartmei print_binat(struct pf_rule *b, int verbose)
555a3e657d0Sjasoni {
55660927d26Sdhartmei 	if (verbose)
55760927d26Sdhartmei 		printf("@%d ", b->nr);
5586ac94451Sdhartmei 	if (b->anchorname[0])
5596ac94451Sdhartmei 		printf("binat-anchor %s ", b->anchorname);
5606ac94451Sdhartmei 	else {
561e8793aa9Smcbride 		if (b->action == PF_NOBINAT)
562f27db9bcSdhartmei 			printf("no ");
563f27db9bcSdhartmei 		printf("binat ");
5646ac94451Sdhartmei 	}
565a3e657d0Sjasoni 	if (b->ifname[0]) {
566a3e657d0Sjasoni 		printf("on ");
567a3e657d0Sjasoni 		printf("%s ", b->ifname);
568a3e657d0Sjasoni 	}
569032e40b7Sdhartmei 	if (b->af) {
570032e40b7Sdhartmei 		if (b->af == AF_INET)
571032e40b7Sdhartmei 			printf("inet ");
572032e40b7Sdhartmei 		else
573032e40b7Sdhartmei 			printf("inet6 ");
574032e40b7Sdhartmei 	}
57580edb1f0Sdhartmei 	if (b->proto) {
576e4ebe044Shenning 		struct protoent	*p;
577ed99c291Sderaadt 
578e4ebe044Shenning 		if ((p = getprotobynumber(b->proto)) != NULL)
57980edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
58080edb1f0Sdhartmei 		else
58180edb1f0Sdhartmei 			printf("proto %u ", b->proto);
582a3e657d0Sjasoni 	}
583fc8e917aScedric 	print_fromto(&b->src, &b->dst, b->af, b->proto, verbose);
584e8793aa9Smcbride 	if (!b->anchorname[0] && (b->action == PF_BINAT)) {
585a3e657d0Sjasoni 		printf("-> ");
586e8793aa9Smcbride 		print_pool(&b->rpool, 0, 0, b->af, PF_BINAT);
587f27db9bcSdhartmei 	}
588a3e657d0Sjasoni 	printf("\n");
589a3e657d0Sjasoni }
590a3e657d0Sjasoni 
591a3e657d0Sjasoni void
59260927d26Sdhartmei print_rdr(struct pf_rule *r, int verbose)
59314a9b182Skjell {
59460927d26Sdhartmei 	if (verbose)
59560927d26Sdhartmei 		printf("@%d ", r->nr);
5966ac94451Sdhartmei 	if (r->anchorname[0])
5976ac94451Sdhartmei 		printf("rdr-anchor %s ", r->anchorname);
5986ac94451Sdhartmei 	else {
599e8793aa9Smcbride 		if (r->action == PF_NORDR)
600f27db9bcSdhartmei 			printf("no ");
601f27db9bcSdhartmei 		printf("rdr ");
6026ac94451Sdhartmei 	}
60328964e80Sdhartmei 	if (r->ifname[0]) {
60428964e80Sdhartmei 		printf("on ");
605870b51d7Schris 		if (r->ifnot)
606870b51d7Schris 			printf("! ");
607870b51d7Schris 		printf("%s ", r->ifname);
60828964e80Sdhartmei 	}
609032e40b7Sdhartmei 	if (r->af) {
610032e40b7Sdhartmei 		if (r->af == AF_INET)
611032e40b7Sdhartmei 			printf("inet ");
612032e40b7Sdhartmei 		else
613032e40b7Sdhartmei 			printf("inet6 ");
614032e40b7Sdhartmei 	}
61580edb1f0Sdhartmei 	if (r->proto) {
616e4ebe044Shenning 		struct protoent	*p;
617ed99c291Sderaadt 
618e4ebe044Shenning 		if ((p = getprotobynumber(r->proto)) != NULL)
61980edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
62080edb1f0Sdhartmei 		else
62180edb1f0Sdhartmei 			printf("proto %u ", r->proto);
622e3d52469Smillert 	}
6238da4e377Smcbride 	print_fromto(&r->src, &r->dst, r->af, r->proto, verbose);
624e8793aa9Smcbride 	if (!r->anchorname[0] && (r->action == PF_RDR)) {
625cb07131dSkjell 		printf("-> ");
626e8793aa9Smcbride 		print_pool(&r->rpool, r->rpool.proxy_port[0],
627120f430eSmcbride 		    r->rpool.proxy_port[1], r->af, PF_RDR);
628f27db9bcSdhartmei 	}
62914a9b182Skjell 	printf("\n");
63014a9b182Skjell }
63114a9b182Skjell 
632*132c30ccShenning const char	*pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
633*132c30ccShenning const char	*pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
63499a73934Sderaadt 
63514a9b182Skjell void
63681a15e5dSderaadt print_status(struct pf_status *s)
63714a9b182Skjell {
638e4ebe044Shenning 	char	statline[80];
639c474e331Shenning 	time_t	runtime;
64099a73934Sderaadt 	int	i;
64199a73934Sderaadt 
642c474e331Shenning 	runtime = time(NULL) - s->since;
643c474e331Shenning 
644d85e4ad6Sdhartmei 	if (s->running) {
645d85e4ad6Sdhartmei 		unsigned	sec, min, hrs, day = runtime;
646d85e4ad6Sdhartmei 
647d85e4ad6Sdhartmei 		sec = day % 60;
648d85e4ad6Sdhartmei 		day /= 60;
649d85e4ad6Sdhartmei 		min = day % 60;
650d85e4ad6Sdhartmei 		day /= 60;
651d85e4ad6Sdhartmei 		hrs = day % 24;
652d85e4ad6Sdhartmei 		day /= 24;
653c474e331Shenning 		snprintf(statline, sizeof(statline),
654d85e4ad6Sdhartmei 		    "Status: Enabled for %u days %.2u:%.2u:%.2u",
655d85e4ad6Sdhartmei 		    day, hrs, min, sec);
656d85e4ad6Sdhartmei 	} else
657c474e331Shenning 		snprintf(statline, sizeof(statline), "Status: Disabled");
658c97b4ee1Shenning 	printf("%-44s", statline);
659ae58c8acSdhartmei 	switch (s->debug) {
660ae58c8acSdhartmei 	case 0:
661c97b4ee1Shenning 		printf("%15s\n\n", "Debug: None");
662ae58c8acSdhartmei 		break;
663ae58c8acSdhartmei 	case 1:
664c97b4ee1Shenning 		printf("%15s\n\n", "Debug: Urgent");
665ae58c8acSdhartmei 		break;
666ae58c8acSdhartmei 	case 2:
667c97b4ee1Shenning 		printf("%15s\n\n", "Debug: Misc");
668ae58c8acSdhartmei 		break;
669ae58c8acSdhartmei 	}
670c474e331Shenning 	if (s->ifname[0] != 0) {
671c474e331Shenning 		printf("Interface Stats for %-16s %5s %16s\n",
672c474e331Shenning 		    s->ifname, "IPv4", "IPv6");
673c474e331Shenning 		printf("  %-25s %14llu %16llu\n", "Bytes In",
6747189e280Sdhartmei 		    s->bcounters[0][0], s->bcounters[1][0]);
675c474e331Shenning 		printf("  %-25s %14llu %16llu\n", "Bytes Out",
6767189e280Sdhartmei 		    s->bcounters[0][1], s->bcounters[1][1]);
677c474e331Shenning 		printf("  Packets In\n");
678c474e331Shenning 		printf("    %-23s %14llu %16llu\n", "Passed",
6797189e280Sdhartmei 		    s->pcounters[0][0][PF_PASS],
6807189e280Sdhartmei 		    s->pcounters[1][0][PF_PASS]);
681c474e331Shenning 		printf("    %-23s %14llu %16llu\n", "Blocked",
6827189e280Sdhartmei 		    s->pcounters[0][0][PF_DROP],
6837189e280Sdhartmei 		    s->pcounters[1][0][PF_DROP]);
684c474e331Shenning 		printf("  Packets Out\n");
685c474e331Shenning 		printf("    %-23s %14llu %16llu\n", "Passed",
6867189e280Sdhartmei 		    s->pcounters[0][1][PF_PASS],
6877189e280Sdhartmei 		    s->pcounters[1][1][PF_PASS]);
688c474e331Shenning 		printf("    %-23s %14llu %16llu\n\n", "Blocked",
6897189e280Sdhartmei 		    s->pcounters[0][1][PF_DROP],
6907189e280Sdhartmei 		    s->pcounters[1][1][PF_DROP]);
691c474e331Shenning 	}
692c474e331Shenning 	printf("%-27s %14s %16s\n", "State Table", "Total", "Rate");
693c474e331Shenning 	printf("  %-25s %14u %14s\n", "current entries", s->states, "");
694c474e331Shenning 	for (i = 0; i < FCNT_MAX; i++) {
695c474e331Shenning 		printf("  %-25s %14lld ", pf_fcounters[i],
69684976600Sderaadt 			    s->fcounters[i]);
697c474e331Shenning 		if (runtime > 0)
698c474e331Shenning 			printf("%14.1f/s\n",
699c474e331Shenning 			    (double)s->fcounters[i] / (double)runtime);
700c474e331Shenning 		else
701c474e331Shenning 			printf("%14s\n", "");
702c474e331Shenning 	}
70399a73934Sderaadt 	printf("Counters\n");
704c474e331Shenning 	for (i = 0; i < PFRES_MAX; i++) {
705c474e331Shenning 		printf("  %-25s %14lld ", pf_reasons[i],
70699a73934Sderaadt 		    s->counters[i]);
707c474e331Shenning 		if (runtime > 0)
708c474e331Shenning 			printf("%14.1f/s\n",
709c474e331Shenning 			    (double)s->counters[i] / (double)runtime);
710c474e331Shenning 		else
711c474e331Shenning 			printf("%14s\n", "");
712c474e331Shenning 	}
71314a9b182Skjell }
71414a9b182Skjell 
71514a9b182Skjell void
716e8793aa9Smcbride print_filter(struct pf_rule *r, int verbose)
71714a9b182Skjell {
718cc5f0329Sdhartmei 	int	i, opts;
719cc5f0329Sdhartmei 
72074dc4fddShenning 	if (verbose)
72178baf774Sdhartmei 		printf("@%d ", r->nr);
7226ac94451Sdhartmei 	if (r->anchorname[0])
7236ac94451Sdhartmei 		printf("anchor %s ", r->anchorname);
7246ac94451Sdhartmei 	else if (r->action == PF_PASS)
72514a9b182Skjell 		printf("pass ");
726b996d042Sdhartmei 	else if (r->action == PF_DROP) {
72714a9b182Skjell 		printf("block ");
7288a87542aShenning 		if (r->rule_flag & PFRULE_RETURN)
7298a87542aShenning 			printf("return ");
7308a87542aShenning 		else if (r->rule_flag & PFRULE_RETURNRST) {
7311f77cc8aSpb 			if (!r->return_ttl)
73214a9b182Skjell 				printf("return-rst ");
7331f77cc8aSpb 			else
7341f77cc8aSpb 				printf("return-rst(ttl %d) ", r->return_ttl);
735328b2decShenning 		} else if (r->rule_flag & PFRULE_RETURNICMP) {
736328b2decShenning 			const struct icmpcodeent	*ic, *ic6;
737b996d042Sdhartmei 
738b996d042Sdhartmei 			ic = geticmpcodebynumber(r->return_icmp >> 8,
739328b2decShenning 			    r->return_icmp & 255, AF_INET);
740328b2decShenning 			ic6 = geticmpcodebynumber(r->return_icmp6 >> 8,
741328b2decShenning 			    r->return_icmp6 & 255, AF_INET6);
742d14c53d7Swilfried 
743328b2decShenning 			switch(r->af) {
744328b2decShenning 			case AF_INET:
745328b2decShenning 				printf("return-icmp");
746d14c53d7Swilfried 				if (ic == NULL)
747d14c53d7Swilfried 					printf("(%u) ", r->return_icmp & 255);
748b996d042Sdhartmei 				else
749328b2decShenning 					printf("(%s) ", ic->name);
750328b2decShenning 				break;
751328b2decShenning 			case AF_INET6:
752328b2decShenning 				printf("return-icmp6");
753328b2decShenning 				if (ic6 == NULL)
754328b2decShenning 					printf("(%u) ", r->return_icmp6 & 255);
755328b2decShenning 				else
756328b2decShenning 					printf("(%s) ", ic6->name);
757328b2decShenning 				break;
758328b2decShenning 			default:
759328b2decShenning 				printf("return-icmp");
760328b2decShenning 				if (ic == NULL)
761328b2decShenning 					printf("(%u, ", r->return_icmp & 255);
762328b2decShenning 				else
763328b2decShenning 					printf("(%s, ", ic->name);
764328b2decShenning 				if (ic6 == NULL)
765328b2decShenning 					printf("%u) ", r->return_icmp6 & 255);
766328b2decShenning 				else
767328b2decShenning 					printf("%s) ", ic6->name);
768328b2decShenning 				break;
769328b2decShenning 			}
770acf2444cShenning 		} else
771acf2444cShenning 			printf("drop ");
7726ac94451Sdhartmei 	} else
773b996d042Sdhartmei 		printf("scrub ");
7747189e280Sdhartmei 	if (r->direction == PF_IN)
77514a9b182Skjell 		printf("in ");
7767189e280Sdhartmei 	else if (r->direction == PF_OUT)
77714a9b182Skjell 		printf("out ");
7787242ce7aSdhartmei 	if (r->log == 1)
77914a9b182Skjell 		printf("log ");
7807242ce7aSdhartmei 	else if (r->log == 2)
7817242ce7aSdhartmei 		printf("log-all ");
78214a9b182Skjell 	if (r->quick)
78314a9b182Skjell 		printf("quick ");
7847d0c9138Shenning 	if (r->ifname[0]) {
7857d0c9138Shenning 		if (r->ifnot)
7867d0c9138Shenning 			printf("on ! %s ", r->ifname);
7877d0c9138Shenning 		else
78814a9b182Skjell 			printf("on %s ", r->ifname);
7897d0c9138Shenning 	}
790cb3a4e31Sjasoni 	if (r->rt) {
791cb3a4e31Sjasoni 		if (r->rt == PF_ROUTETO)
792cb3a4e31Sjasoni 			printf("route-to ");
793fa1cdd09Sdhartmei 		else if (r->rt == PF_REPLYTO)
794fa1cdd09Sdhartmei 			printf("reply-to ");
795cb3a4e31Sjasoni 		else if (r->rt == PF_DUPTO)
796cb3a4e31Sjasoni 			printf("dup-to ");
797cb3a4e31Sjasoni 		else if (r->rt == PF_FASTROUTE)
798cb3a4e31Sjasoni 			printf("fastroute ");
799790504a6Sdhartmei 		if (r->rt != PF_FASTROUTE) {
800e8793aa9Smcbride 			print_pool(&r->rpool, 0, 0, r->af, PF_PASS);
801790504a6Sdhartmei 			printf(" ");
802790504a6Sdhartmei 		}
803cb3a4e31Sjasoni 	}
80430620b12Sfrantzen 	if (r->af) {
80530620b12Sfrantzen 		if (r->af == AF_INET)
80630620b12Sfrantzen 			printf("inet ");
80730620b12Sfrantzen 		else
80830620b12Sfrantzen 			printf("inet6 ");
80930620b12Sfrantzen 	}
81014a9b182Skjell 	if (r->proto) {
811e4ebe044Shenning 		struct protoent	*p;
812ed99c291Sderaadt 
813e4ebe044Shenning 		if ((p = getprotobynumber(r->proto)) != NULL)
81414a9b182Skjell 			printf("proto %s ", p->p_name);
81514a9b182Skjell 		else
81614a9b182Skjell 			printf("proto %u ", r->proto);
81714a9b182Skjell 	}
81844f5ed0aScedric 	print_fromto(&r->src, &r->dst, r->af, r->proto, verbose);
819c16ab608Sdhartmei 	if (r->uid.op)
820c16ab608Sdhartmei 		print_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user");
821c16ab608Sdhartmei 	if (r->gid.op)
822c16ab608Sdhartmei 		print_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group");
82314a9b182Skjell 	if (r->flags || r->flagset) {
82414a9b182Skjell 		printf("flags ");
82514a9b182Skjell 		print_flags(r->flags);
82614a9b182Skjell 		printf("/");
82714a9b182Skjell 		print_flags(r->flagset);
82814a9b182Skjell 		printf(" ");
82914a9b182Skjell 	}
830082ebc44Swilfried 	if (r->type) {
831b49ca6bbShenning 		const struct icmptypeent	*it;
832082ebc44Swilfried 
833b49ca6bbShenning 		it = geticmptypebynumber(r->type-1, r->af);
834d14c53d7Swilfried 		if (r->af != AF_INET6)
835d14c53d7Swilfried 			printf("icmp-type");
836082ebc44Swilfried 		else
837d0cb3502Smcbride 			printf("icmp6-type");
838b49ca6bbShenning 		if (it != NULL)
839b49ca6bbShenning 			printf(" %s ", it->name);
840d14c53d7Swilfried 		else
841d14c53d7Swilfried 			printf(" %u ", r->type-1);
842082ebc44Swilfried 		if (r->code) {
843b49ca6bbShenning 			const struct icmpcodeent	*ic;
844082ebc44Swilfried 
845b49ca6bbShenning 			ic = geticmpcodebynumber(r->type-1, r->code-1, r->af);
846b49ca6bbShenning 			if (ic != NULL)
847b49ca6bbShenning 				printf("code %s ", ic->name);
848082ebc44Swilfried 			else
84914a9b182Skjell 				printf("code %u ", r->code-1);
850082ebc44Swilfried 		}
851082ebc44Swilfried 	}
852e4cbe364Sdhartmei 	if (r->tos)
853e4cbe364Sdhartmei 		printf("tos 0x%2.2x ", r->tos);
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 ");
858cc5f0329Sdhartmei 	opts = 0;
859b3c86969Sdhartmei 	if (r->max_states)
860cc5f0329Sdhartmei 		opts = 1;
861cc5f0329Sdhartmei 	for (i = 0; !opts && i < PFTM_MAX; ++i)
862cc5f0329Sdhartmei 		if (r->timeout[i])
863cc5f0329Sdhartmei 			opts = 1;
864cc5f0329Sdhartmei 	if (opts) {
865cc5f0329Sdhartmei 		printf("(");
866cc5f0329Sdhartmei 		if (r->max_states) {
867cc5f0329Sdhartmei 			printf("max %u", r->max_states);
868cc5f0329Sdhartmei 			opts = 0;
869cc5f0329Sdhartmei 		}
870cc5f0329Sdhartmei 		for (i = 0; i < PFTM_MAX; ++i)
871cc5f0329Sdhartmei 			if (r->timeout[i]) {
872cc5f0329Sdhartmei 				if (!opts)
873cc5f0329Sdhartmei 					printf(", ");
874cc5f0329Sdhartmei 				opts = 0;
875cc5f0329Sdhartmei 				printf("%s %u", pf_timeouts[i].name,
876cc5f0329Sdhartmei 				    r->timeout[i]);
877cc5f0329Sdhartmei 			}
878cc5f0329Sdhartmei 		printf(") ");
879cc5f0329Sdhartmei 	}
8806673dee2Sdhartmei 	if (r->rule_flag & PFRULE_FRAGMENT)
8816673dee2Sdhartmei 		printf("fragment ");
88267d2a440Sprovos 	if (r->rule_flag & PFRULE_NODF)
88367d2a440Sprovos 		printf("no-df ");
884edbe3066Sdhartmei 	if (r->rule_flag & PFRULE_RANDOMID)
885edbe3066Sdhartmei 		printf("random-id ");
886e258bfd4Sprovos 	if (r->min_ttl)
88734c76dcbSprovos 		printf("min-ttl %d ", r->min_ttl);
888cfa91859Sjasoni 	if (r->max_mss)
889cfa91859Sjasoni 		printf("max-mss %d ", r->max_mss);
890f48d62b3Sdhartmei 	if (r->allow_opts)
891f48d62b3Sdhartmei 		printf("allow-opts ");
892b02af636Sfrantzen 	if (r->action == PF_SCRUB) {
893b02af636Sfrantzen 		if (r->rule_flag & PFRULE_FRAGDROP)
894b02af636Sfrantzen 			printf("fragment drop-ovl ");
895b02af636Sfrantzen 		else if (r->rule_flag & PFRULE_FRAGCROP)
896b02af636Sfrantzen 			printf("fragment crop ");
897b02af636Sfrantzen 		else
898b02af636Sfrantzen 			printf("fragment reassemble ");
899b02af636Sfrantzen 	}
900455ef0c1Sdhartmei 	if (r->label[0])
901ff45dfa8Scamield 		printf("label \"%s\" ", r->label);
902f98324c6Shenning 	if (r->qname[0] && r->pqname[0])
903f98324c6Shenning 		printf("queue(%s, %s) ", r->qname, r->pqname);
904f98324c6Shenning 	else if (r->qname[0])
90578e1d2a6Shenning 		printf("queue %s ", r->qname);
90667d2a440Sprovos 
90714a9b182Skjell 	printf("\n");
90814a9b182Skjell }
90914a9b182Skjell 
9101f8f21bdSmillert int
911ff352a37Smarkus parse_flags(char *s)
91214a9b182Skjell {
913ff352a37Smarkus 	char		*p, *q;
91414a9b182Skjell 	u_int8_t	 f = 0;
91581a15e5dSderaadt 
916ff352a37Smarkus 	for (p = s; *p; p++) {
917ff352a37Smarkus 		if ((q = strchr(tcpflags, *p)) == NULL)
918ff352a37Smarkus 			return -1;
919ff352a37Smarkus 		else
920ff352a37Smarkus 			f |= 1 << (q - tcpflags);
92114a9b182Skjell 	}
922bc795af0Shugh 	return (f ? f : PF_TH_ALL);
92314a9b182Skjell }
92494e9410bShenning 
92594e9410bShenning void
92694e9410bShenning set_ipmask(struct node_host *h, u_int8_t b)
92794e9410bShenning {
92894e9410bShenning 	struct pf_addr	*m, *n;
92994e9410bShenning 	int		 i, j = 0;
93094e9410bShenning 
93194e9410bShenning 	m = &h->addr.v.a.mask;
93294e9410bShenning 
93394e9410bShenning 	for (i = 0; i < 4; i++)
93494e9410bShenning 		m->addr32[i] = 0;
93594e9410bShenning 
93694e9410bShenning 	while (b >= 32) {
93794e9410bShenning 		m->addr32[j++] = 0xffffffff;
93894e9410bShenning 		b -= 32;
93994e9410bShenning 	}
94094e9410bShenning 	for (i = 31; i > 31-b; --i)
94194e9410bShenning 		m->addr32[j] |= (1 << i);
94294e9410bShenning 	if (b)
94394e9410bShenning 		m->addr32[j] = htonl(m->addr32[j]);
94494e9410bShenning 
94594e9410bShenning 	/* Mask off bits of the address that will never be used. */
94694e9410bShenning 	n = &h->addr.v.a.addr;
94794e9410bShenning 	for (i = 0; i < 4; i++)
94894e9410bShenning 		n->addr32[i] = n->addr32[i] & m->addr32[i];
94994e9410bShenning }
95094e9410bShenning 
95194e9410bShenning /* interface lookup routines */
95294e9410bShenning 
95394e9410bShenning struct node_host	*iftab;
95494e9410bShenning 
95594e9410bShenning void
95694e9410bShenning ifa_load(void)
95794e9410bShenning {
95894e9410bShenning 	struct ifaddrs		*ifap, *ifa;
95994e9410bShenning 	struct node_host	*n = NULL, *h = NULL;
96094e9410bShenning 
96194e9410bShenning 	if (getifaddrs(&ifap) < 0)
96294e9410bShenning 		err(1, "getifaddrs");
96394e9410bShenning 
96494e9410bShenning 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
96594e9410bShenning 		if (!(ifa->ifa_addr->sa_family == AF_INET ||
96694e9410bShenning 		    ifa->ifa_addr->sa_family == AF_INET6 ||
96794e9410bShenning 		    ifa->ifa_addr->sa_family == AF_LINK))
96894e9410bShenning 				continue;
96994e9410bShenning 		n = calloc(1, sizeof(struct node_host));
97094e9410bShenning 		if (n == NULL)
97194e9410bShenning 			err(1, "address: calloc");
97294e9410bShenning 		n->af = ifa->ifa_addr->sa_family;
97394e9410bShenning 		n->ifa_flags = ifa->ifa_flags;
97494e9410bShenning #ifdef __KAME__
97594e9410bShenning 		if (n->af == AF_INET6 &&
97694e9410bShenning 		    IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)
97794e9410bShenning 		    ifa->ifa_addr)->sin6_addr) &&
97894e9410bShenning 		    ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 0) {
97994e9410bShenning 			struct sockaddr_in6	*sin6;
98094e9410bShenning 
98194e9410bShenning 			sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
98294e9410bShenning 			sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 |
98394e9410bShenning 			    sin6->sin6_addr.s6_addr[3];
98494e9410bShenning 			sin6->sin6_addr.s6_addr[2] = 0;
98594e9410bShenning 			sin6->sin6_addr.s6_addr[3] = 0;
98694e9410bShenning 		}
98794e9410bShenning #endif
98894e9410bShenning 		n->ifindex = 0;
98994e9410bShenning 		if (n->af == AF_INET) {
99094e9410bShenning 			memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *)
99194e9410bShenning 			    ifa->ifa_addr)->sin_addr.s_addr,
99294e9410bShenning 			    sizeof(struct in_addr));
99394e9410bShenning 			memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *)
99494e9410bShenning 			    ifa->ifa_netmask)->sin_addr.s_addr,
99594e9410bShenning 			    sizeof(struct in_addr));
99694e9410bShenning 			if (ifa->ifa_broadaddr != NULL)
99794e9410bShenning 				memcpy(&n->bcast, &((struct sockaddr_in *)
99894e9410bShenning 				    ifa->ifa_broadaddr)->sin_addr.s_addr,
99994e9410bShenning 				    sizeof(struct in_addr));
100094e9410bShenning 		} else if (n->af == AF_INET6) {
100194e9410bShenning 			memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *)
100294e9410bShenning 			    ifa->ifa_addr)->sin6_addr.s6_addr,
100394e9410bShenning 			    sizeof(struct in6_addr));
100494e9410bShenning 			memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *)
100594e9410bShenning 			    ifa->ifa_netmask)->sin6_addr.s6_addr,
100694e9410bShenning 			    sizeof(struct in6_addr));
100794e9410bShenning 			if (ifa->ifa_broadaddr != NULL)
100894e9410bShenning 				memcpy(&n->bcast, &((struct sockaddr_in6 *)
100994e9410bShenning 				    ifa->ifa_broadaddr)->sin6_addr.s6_addr,
101094e9410bShenning 				    sizeof(struct in6_addr));
101194e9410bShenning 			n->ifindex = ((struct sockaddr_in6 *)
101294e9410bShenning 			    ifa->ifa_addr)->sin6_scope_id;
101394e9410bShenning 		}
101494e9410bShenning 		if ((n->ifname = strdup(ifa->ifa_name)) == NULL)
101594e9410bShenning 			err(1, "ifa_load: strdup");
101694e9410bShenning 		n->next = NULL;
101794e9410bShenning 		n->tail = n;
101894e9410bShenning 		if (h == NULL)
101994e9410bShenning 			h = n;
102094e9410bShenning 		else {
102194e9410bShenning 			h->tail->next = n;
102294e9410bShenning 			h->tail = n;
102394e9410bShenning 		}
102494e9410bShenning 	}
102594e9410bShenning 	iftab = h;
102694e9410bShenning 	freeifaddrs(ifap);
102794e9410bShenning }
102894e9410bShenning 
102994e9410bShenning struct node_host *
10306cba701cShenning ifa_exists(const char *ifa_name)
103194e9410bShenning {
103294e9410bShenning 	struct node_host	*n;
103394e9410bShenning 
103494e9410bShenning 	if (iftab == NULL)
103594e9410bShenning 		ifa_load();
103694e9410bShenning 
103794e9410bShenning 	for (n = iftab; n; n = n->next) {
103894e9410bShenning 		if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
103994e9410bShenning 			return (n);
104094e9410bShenning 	}
104194e9410bShenning 	return (NULL);
104294e9410bShenning }
104394e9410bShenning 
104494e9410bShenning struct node_host *
10456cba701cShenning ifa_lookup(const char *ifa_name, enum pfctl_iflookup_mode mode)
104694e9410bShenning {
104794e9410bShenning 	struct node_host	*p = NULL, *h = NULL, *n = NULL;
104894e9410bShenning 	int			 return_all = 0;
104994e9410bShenning 
105094e9410bShenning 	if (!strncmp(ifa_name, "self", IFNAMSIZ))
105194e9410bShenning 		return_all = 1;
105294e9410bShenning 
105394e9410bShenning 	if (iftab == NULL)
105494e9410bShenning 		ifa_load();
105594e9410bShenning 
105694e9410bShenning 	for (p = iftab; p; p = p->next) {
105794e9410bShenning 		if (!((p->af == AF_INET || p->af == AF_INET6) &&
105894e9410bShenning 		    (!strncmp(p->ifname, ifa_name, IFNAMSIZ) || return_all)))
105994e9410bShenning 			continue;
106094e9410bShenning 		if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET)
106194e9410bShenning 			continue;
106294e9410bShenning 		if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0)
106394e9410bShenning 			continue;
106494e9410bShenning 		n = calloc(1, sizeof(struct node_host));
106594e9410bShenning 		if (n == NULL)
106694e9410bShenning 			err(1, "address: calloc");
106794e9410bShenning 		n->af = p->af;
106894e9410bShenning 		if (mode == PFCTL_IFLOOKUP_BCAST)
106994e9410bShenning 			memcpy(&n->addr.v.a.addr, &p->bcast,
107094e9410bShenning 			    sizeof(struct pf_addr));
107194e9410bShenning 		else
107294e9410bShenning 			memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr,
107394e9410bShenning 			    sizeof(struct pf_addr));
107494e9410bShenning 		if (mode == PFCTL_IFLOOKUP_NET)
107594e9410bShenning 			set_ipmask(n, unmask(&p->addr.v.a.mask, n->af));
107694e9410bShenning 		else {
107794e9410bShenning 			if (n->af == AF_INET) {
107894e9410bShenning 				if (p->ifa_flags & IFF_LOOPBACK &&
107994e9410bShenning 				    p->ifa_flags & IFF_LINK1)
108094e9410bShenning 					memcpy(&n->addr.v.a.mask,
108194e9410bShenning 					    &p->addr.v.a.mask,
108294e9410bShenning 					    sizeof(struct pf_addr));
108394e9410bShenning 				else
108494e9410bShenning 					set_ipmask(n, 32);
108594e9410bShenning 			} else
108694e9410bShenning 				set_ipmask(n, 128);
108794e9410bShenning 		}
108894e9410bShenning 		n->ifindex = p->ifindex;
108994e9410bShenning 
109094e9410bShenning 		n->next = NULL;
109194e9410bShenning 		n->tail = n;
109294e9410bShenning 		if (h == NULL)
109394e9410bShenning 			h = n;
109494e9410bShenning 		else {
109594e9410bShenning 			h->tail->next = n;
109694e9410bShenning 			h->tail = n;
109794e9410bShenning 		}
109894e9410bShenning 	}
109994e9410bShenning 	if (h == NULL && mode == PFCTL_IFLOOKUP_HOST) {
110094e9410bShenning 		fprintf(stderr, "no IP address found for %s\n", ifa_name);
110194e9410bShenning 	}
110294e9410bShenning 	return (h);
110394e9410bShenning }
110494e9410bShenning 
110594e9410bShenning struct node_host *
11066cba701cShenning host(const char *s, int mask)
110794e9410bShenning {
11082a6c1abaShenning 	struct node_host	*h = NULL;
11092a6c1abaShenning 	int			 v4mask, v6mask, cont = 1;
111094e9410bShenning 	char			*buf = NULL, *p, *q, *ps;
111194e9410bShenning 
111294e9410bShenning 	if ((p = strrchr(s, '/')) != NULL) {
111394e9410bShenning 		if (mask != -1) {
111494e9410bShenning 			fprintf(stderr, "address with netmask specified"
111594e9410bShenning 			    " and extra netmask supplied\n");
111694e9410bShenning 			return (NULL);
111794e9410bShenning 		}
111894e9410bShenning 		mask = strtol(p+1, &q, 0);
111994e9410bShenning 		if (!q || *q) {
112094e9410bShenning 			fprintf(stderr, "invalid netmask\n");
112194e9410bShenning 			return (NULL);
112294e9410bShenning 		}
1123e9275b6cShenning 		if ((buf = strdup(s)) == NULL)
1124e9275b6cShenning 			err(1, "host: strdup");
1125a81c851cShenning 		if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
112694e9410bShenning 			err(1, "host: malloc");
112794e9410bShenning 		strlcpy(ps, s, strlen(s) - strlen(p) + 1);
112894e9410bShenning 		v4mask = v6mask = mask;
112994e9410bShenning 	} else {
113094e9410bShenning 		if (asprintf(&ps, "%s", s) == -1)
113194e9410bShenning 			err(1, "host: asprintf");
113294e9410bShenning 		if (mask == -1) {
113394e9410bShenning 			if (asprintf(&buf, "%s", s) == -1)
113494e9410bShenning 				err(1, "host: asprintf");
113594e9410bShenning 			v4mask = 32;
113694e9410bShenning 			v6mask = 128;
113794e9410bShenning 		} else if (mask <= 128) {
113894e9410bShenning 			if (asprintf(&buf, "%s/%d", s, mask) == -1)
113994e9410bShenning 				err(1, "host: asprintf");
114094e9410bShenning 			v4mask = v6mask = mask;
114194e9410bShenning 		} else {
114211bd6590Shenning 			fprintf(stderr, "illegal mask %d\n", mask);
114394e9410bShenning 			return (NULL);
114494e9410bShenning 		}
114594e9410bShenning 	}
114694e9410bShenning 
11472a6c1abaShenning 	/* interface with this name exists? */
11484a36d485Shenning 	if (cont && (h = host_if(ps, mask)) != NULL)
11492a6c1abaShenning 		cont = 0;
11502a6c1abaShenning 
11512a6c1abaShenning 	/* IPv4 address? */
1152383ebbbfShenning 	if (cont && (h = host_v4(buf, mask)) != NULL)
11532a6c1abaShenning 		cont = 0;
11542a6c1abaShenning 	free(buf);
11552a6c1abaShenning 
11562a6c1abaShenning 	/* IPv6 address? */
11572a6c1abaShenning 	if (cont && (h = host_v6(ps, v6mask)) != NULL)
11582a6c1abaShenning 		cont = 0;
11592a6c1abaShenning 
11602a6c1abaShenning 	/* dns lookup */
11612a6c1abaShenning 	if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL)
11622a6c1abaShenning 		cont = 0;
11632a6c1abaShenning 	free(ps);
11642a6c1abaShenning 
11652a6c1abaShenning 	if (h == NULL || cont == 1) {
11662a6c1abaShenning 		fprintf(stderr, "no IP address found for %s\n", s);
11672a6c1abaShenning 		return (NULL);
11682a6c1abaShenning 	}
11692a6c1abaShenning 	return (h);
11702a6c1abaShenning }
11712a6c1abaShenning 
11722a6c1abaShenning struct node_host *
1173f2370d27Shenning host_if(const char *s, int mask)
11742a6c1abaShenning {
11752a6c1abaShenning 	struct node_host	*n, *h = NULL;
11764a36d485Shenning 	char			*p, *ps;
11774a36d485Shenning 	int			 mode = PFCTL_IFLOOKUP_HOST;
11782a6c1abaShenning 
11794a36d485Shenning 	if ((p = strrchr(s, ':')) != NULL &&
11804a36d485Shenning 	    (!strcmp(p+1, "network") || !strcmp(p+1, "broadcast"))) {
11814a36d485Shenning 		if (!strcmp(p+1, "network"))
11824a36d485Shenning 			mode = PFCTL_IFLOOKUP_NET;
11834a36d485Shenning 		if (!strcmp(p+1, "broadcast"))
11844a36d485Shenning 			mode = PFCTL_IFLOOKUP_BCAST;
11854a36d485Shenning 		if (mask > -1) {
11864a36d485Shenning 			fprintf(stderr, "network or broadcast lookup, but "
11874a36d485Shenning 			    "extra netmask given\n");
11884a36d485Shenning 			return (NULL);
11894a36d485Shenning 		}
11904a36d485Shenning 		if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
11914a36d485Shenning 			err(1, "host: malloc");
11924a36d485Shenning 		strlcpy(ps, s, strlen(s) - strlen(p) + 1);
11934a36d485Shenning 	} else
11944a36d485Shenning 		if ((ps = strdup(s)) == NULL)
11954a36d485Shenning 			err(1, "host_if: strdup");
11964a36d485Shenning 
11974a36d485Shenning 	if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) {
11982a6c1abaShenning 		/* interface with this name exists */
11994a36d485Shenning 		h = ifa_lookup(ps, mode);
12002a6c1abaShenning 		for (n = h; n != NULL && mask > -1; n = n->next)
12012a6c1abaShenning 			set_ipmask(n, mask);
12022a6c1abaShenning 	}
12034a36d485Shenning 
12044a36d485Shenning 	free(ps);
12052a6c1abaShenning 	return (h);
12062a6c1abaShenning }
12072a6c1abaShenning 
12082a6c1abaShenning struct node_host *
1209383ebbbfShenning host_v4(const char *s, int mask)
12102a6c1abaShenning {
12112a6c1abaShenning 	struct node_host	*h = NULL;
12122a6c1abaShenning 	struct in_addr		 ina;
12132a6c1abaShenning 	int			 bits;
12142a6c1abaShenning 
121594e9410bShenning 	memset(&ina, 0, sizeof(struct in_addr));
12163c58a40aScedric 	if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) > -1) {
121794e9410bShenning 		h = calloc(1, sizeof(struct node_host));
121894e9410bShenning 		if (h == NULL)
121994e9410bShenning 			err(1, "address: calloc");
122094e9410bShenning 		h->ifname = NULL;
122194e9410bShenning 		h->af = AF_INET;
122294e9410bShenning 		h->addr.v.a.addr.addr32[0] = ina.s_addr;
1223383ebbbfShenning 		/* inet_net_pton acts strange w/ multicast addresses, RFC1112 */
1224383ebbbfShenning 		if (mask == -1 && h->addr.v.a.addr.addr8[0] >= 224 &&
1225383ebbbfShenning 		    h->addr.v.a.addr.addr8[0] < 240)
1226383ebbbfShenning 			bits = 32;
122794e9410bShenning 		set_ipmask(h, bits);
122894e9410bShenning 		h->next = NULL;
122994e9410bShenning 		h->tail = h;
123094e9410bShenning 	}
12312a6c1abaShenning 
123294e9410bShenning 	return (h);
123394e9410bShenning }
12342a6c1abaShenning 
12352a6c1abaShenning struct node_host *
1236f2370d27Shenning host_v6(const char *s, int mask)
12372a6c1abaShenning {
12382a6c1abaShenning 	struct addrinfo		 hints, *res;
12392a6c1abaShenning 	struct node_host	*h = NULL;
124094e9410bShenning 
124194e9410bShenning 	memset(&hints, 0, sizeof(hints));
124294e9410bShenning 	hints.ai_family = AF_INET6;
124394e9410bShenning 	hints.ai_socktype = SOCK_DGRAM; /*dummy*/
124494e9410bShenning 	hints.ai_flags = AI_NUMERICHOST;
12452a6c1abaShenning 	if (getaddrinfo(s, "0", &hints, &res) == 0) {
12462a6c1abaShenning 		h = calloc(1, sizeof(struct node_host));
12472a6c1abaShenning 		if (h == NULL)
124894e9410bShenning 			err(1, "address: calloc");
12492a6c1abaShenning 		h->ifname = NULL;
12502a6c1abaShenning 		h->af = AF_INET6;
12512a6c1abaShenning 		memcpy(&h->addr.v.a.addr,
125294e9410bShenning 		    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
12532a6c1abaShenning 		    sizeof(h->addr.v.a.addr));
12542a6c1abaShenning 		h->ifindex =
12552a6c1abaShenning 		    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
12562a6c1abaShenning 		set_ipmask(h, mask);
125794e9410bShenning 		freeaddrinfo(res);
12582a6c1abaShenning 		h->next = NULL;
12592a6c1abaShenning 		h->tail = h;
126094e9410bShenning 	}
126194e9410bShenning 
12622a6c1abaShenning 	return (h);
12632a6c1abaShenning }
12642a6c1abaShenning 
12652a6c1abaShenning struct node_host *
1266f2370d27Shenning host_dns(const char *s, int v4mask, int v6mask)
12672a6c1abaShenning {
12682a6c1abaShenning 	struct addrinfo		 hints, *res0, *res;
12692a6c1abaShenning 	struct node_host	*n, *h = NULL;
12702a6c1abaShenning 	int			 error;
12712a6c1abaShenning 
127294e9410bShenning 	memset(&hints, 0, sizeof(hints));
127394e9410bShenning 	hints.ai_family = PF_UNSPEC;
127494e9410bShenning 	hints.ai_socktype = SOCK_STREAM; /* DUMMY */
12752a6c1abaShenning 	error = getaddrinfo(s, NULL, &hints, &res0);
12762a6c1abaShenning 	if (error)
12772a6c1abaShenning 		return (h);
12782a6c1abaShenning 
127994e9410bShenning 	for (res = res0; res; res = res->ai_next) {
128094e9410bShenning 		if (res->ai_family != AF_INET &&
128194e9410bShenning 		    res->ai_family != AF_INET6)
128294e9410bShenning 			continue;
128394e9410bShenning 		n = calloc(1, sizeof(struct node_host));
128494e9410bShenning 		if (n == NULL)
12852a6c1abaShenning 			err(1, "host_dns: calloc");
128694e9410bShenning 		n->ifname = NULL;
128794e9410bShenning 		n->af = res->ai_family;
128894e9410bShenning 		if (res->ai_family == AF_INET) {
128994e9410bShenning 			memcpy(&n->addr.v.a.addr,
12902a6c1abaShenning 			    &((struct sockaddr_in *)
12912a6c1abaShenning 			    res->ai_addr)->sin_addr.s_addr,
129294e9410bShenning 			    sizeof(struct in_addr));
129394e9410bShenning 			set_ipmask(n, v4mask);
129494e9410bShenning 		} else {
129594e9410bShenning 			memcpy(&n->addr.v.a.addr,
12962a6c1abaShenning 			    &((struct sockaddr_in6 *)
12972a6c1abaShenning 			    res->ai_addr)->sin6_addr.s6_addr,
129894e9410bShenning 			    sizeof(struct in6_addr));
129994e9410bShenning 			n->ifindex =
13002a6c1abaShenning 			    ((struct sockaddr_in6 *)
13012a6c1abaShenning 			    res->ai_addr)->sin6_scope_id;
130294e9410bShenning 			set_ipmask(n, v6mask);
130394e9410bShenning 		}
130494e9410bShenning 		n->next = NULL;
130594e9410bShenning 		n->tail = n;
130694e9410bShenning 		if (h == NULL)
130794e9410bShenning 			h = n;
130894e9410bShenning 		else {
130994e9410bShenning 			h->tail->next = n;
131094e9410bShenning 			h->tail = n;
131194e9410bShenning 		}
131294e9410bShenning 	}
131394e9410bShenning 	freeaddrinfo(res0);
131494e9410bShenning 
131594e9410bShenning 	return (h);
131694e9410bShenning }
1317