xref: /openbsd/sbin/pfctl/pfctl_parser.c (revision ff45dfa8)
1*ff45dfa8Scamield /*	$OpenBSD: pfctl_parser.c,v 1.132 2003/01/19 09:31:34 camield 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 *);
5881a15e5dSderaadt void		 print_port (u_int8_t, u_int16_t, u_int16_t, 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 *,
6315e76891Sdhartmei 		    u_int8_t, u_int8_t);
6414a9b182Skjell 
652a6c1abaShenning struct node_host	*host_if(char *, int);
662a6c1abaShenning struct node_host	*host_v4(char *);
672a6c1abaShenning struct node_host	*host_v6(char *, int);
682a6c1abaShenning struct node_host	*host_dns(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);
3045d9ac2dcSdhartmei }
3055d9ac2dcSdhartmei 
3065d9ac2dcSdhartmei void
30714a9b182Skjell print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto)
30814a9b182Skjell {
309e31d21c9Sdhartmei 	char		 a1[6], a2[6];
310e4ebe044Shenning 	struct servent	*s;
31181a15e5dSderaadt 
312e4ebe044Shenning 	s = getservbyport(p1, proto);
31314a9b182Skjell 	p1 = ntohs(p1);
31414a9b182Skjell 	p2 = ntohs(p2);
3155d9ac2dcSdhartmei 	snprintf(a1, sizeof(a1), "%u", p1);
3165d9ac2dcSdhartmei 	snprintf(a2, sizeof(a2), "%u", p2);
31714a9b182Skjell 	printf("port ");
3185d9ac2dcSdhartmei 	if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE))
3195d9ac2dcSdhartmei 		print_op(op, s->s_name, a2);
32014a9b182Skjell 	else
3215d9ac2dcSdhartmei 		print_op(op, a1, a2);
3225d9ac2dcSdhartmei }
3235d9ac2dcSdhartmei 
3245d9ac2dcSdhartmei void
3255d9ac2dcSdhartmei print_uid(u_int8_t op, uid_t u1, uid_t u2, const char *t)
3265d9ac2dcSdhartmei {
327d8fcd2dfSdhartmei 	char	a1[11], a2[11];
3285d9ac2dcSdhartmei 
3295d9ac2dcSdhartmei 	snprintf(a1, sizeof(a1), "%u", u1);
3305d9ac2dcSdhartmei 	snprintf(a2, sizeof(a2), "%u", u2);
3315d9ac2dcSdhartmei 	printf("%s ", t);
3325d9ac2dcSdhartmei 	if (u1 == UID_MAX && (op == PF_OP_EQ || op == PF_OP_NE))
3335d9ac2dcSdhartmei 		print_op(op, "unknown", a2);
33414a9b182Skjell 	else
3355d9ac2dcSdhartmei 		print_op(op, a1, a2);
33614a9b182Skjell }
33714a9b182Skjell 
33881a15e5dSderaadt void
339c16ab608Sdhartmei print_gid(u_int8_t op, gid_t g1, gid_t g2, const char *t)
340c16ab608Sdhartmei {
341d8fcd2dfSdhartmei 	char	a1[11], a2[11];
342c16ab608Sdhartmei 
343c16ab608Sdhartmei 	snprintf(a1, sizeof(a1), "%u", g1);
344c16ab608Sdhartmei 	snprintf(a2, sizeof(a2), "%u", g2);
345c16ab608Sdhartmei 	printf("%s ", t);
346c16ab608Sdhartmei 	if (g1 == GID_MAX && (op == PF_OP_EQ || op == PF_OP_NE))
347c16ab608Sdhartmei 		print_op(op, "unknown", a2);
348c16ab608Sdhartmei 	else
349c16ab608Sdhartmei 		print_op(op, a1, a2);
350c16ab608Sdhartmei }
351c16ab608Sdhartmei 
352c16ab608Sdhartmei void
35314a9b182Skjell print_flags(u_int8_t f)
35414a9b182Skjell {
35514a9b182Skjell 	int	i;
35681a15e5dSderaadt 
357bc795af0Shugh 	for (i = 0; tcpflags[i]; ++i)
35814a9b182Skjell 		if (f & (1 << i))
35914a9b182Skjell 			printf("%c", tcpflags[i]);
36014a9b182Skjell }
36114a9b182Skjell 
36214a9b182Skjell void
36315e76891Sdhartmei print_fromto(struct pf_rule_addr *src, struct pf_rule_addr *dst,
364bb9f691eSmcbride     sa_family_t af, u_int8_t proto)
36515e76891Sdhartmei {
366d0b1df00Sdhartmei 	if (src->addr.type != PF_ADDR_NOROUTE &&
367d0b1df00Sdhartmei 	    dst->addr.type != PF_ADDR_NOROUTE &&
368bcf142a4Sdhartmei 	    PF_AZERO(&src->addr.v.a.addr, AF_INET6) &&
369bcf142a4Sdhartmei 	    PF_AZERO(&src->addr.v.a.mask, AF_INET6) &&
370bcf142a4Sdhartmei 	    !src->port_op && PF_AZERO(&dst->addr.v.a.addr, AF_INET6) &&
371bcf142a4Sdhartmei 	    PF_AZERO(&dst->addr.v.a.mask, AF_INET6) && !dst->port_op)
37215e76891Sdhartmei 		printf("all ");
37315e76891Sdhartmei 	else {
37415e76891Sdhartmei 		printf("from ");
375d0b1df00Sdhartmei 		if (src->addr.type == PF_ADDR_NOROUTE)
37615e76891Sdhartmei 			printf("no-route ");
377bcf142a4Sdhartmei 		else if (PF_AZERO(&src->addr.v.a.addr, AF_INET6) &&
378bcf142a4Sdhartmei 		    PF_AZERO(&src->addr.v.a.mask, AF_INET6))
37915e76891Sdhartmei 			printf("any ");
38015e76891Sdhartmei 		else {
38115e76891Sdhartmei 			if (src->not)
38215e76891Sdhartmei 				printf("! ");
3833a44df3cSmcbride 			print_addr(&src->addr, af);
38415e76891Sdhartmei 			printf(" ");
38515e76891Sdhartmei 		}
38615e76891Sdhartmei 		if (src->port_op)
38715e76891Sdhartmei 			print_port(src->port_op, src->port[0],
38815e76891Sdhartmei 			    src->port[1],
38915e76891Sdhartmei 			    proto == IPPROTO_TCP ? "tcp" : "udp");
39015e76891Sdhartmei 
39115e76891Sdhartmei 		printf("to ");
392d0b1df00Sdhartmei 		if (dst->addr.type == PF_ADDR_NOROUTE)
39315e76891Sdhartmei 			printf("no-route ");
394bcf142a4Sdhartmei 		else if (PF_AZERO(&dst->addr.v.a.addr, AF_INET6) &&
395bcf142a4Sdhartmei 		    PF_AZERO(&dst->addr.v.a.mask, AF_INET6))
39615e76891Sdhartmei 			printf("any ");
39715e76891Sdhartmei 		else {
39815e76891Sdhartmei 			if (dst->not)
39915e76891Sdhartmei 				printf("! ");
4003a44df3cSmcbride 			print_addr(&dst->addr, af);
40115e76891Sdhartmei 			printf(" ");
40215e76891Sdhartmei 		}
40315e76891Sdhartmei 		if (dst->port_op)
40415e76891Sdhartmei 			print_port(dst->port_op, dst->port[0],
40515e76891Sdhartmei 			    dst->port[1],
40615e76891Sdhartmei 			    proto == IPPROTO_TCP ? "tcp" : "udp");
40715e76891Sdhartmei 	}
40815e76891Sdhartmei }
40915e76891Sdhartmei 
41015e76891Sdhartmei void
411e8793aa9Smcbride print_rule(struct pf_rule *r, int verbose)
412e8793aa9Smcbride {
413e8793aa9Smcbride 	switch (r->action) {
414e8793aa9Smcbride 	case PF_NAT:
415e8793aa9Smcbride 	case PF_NONAT:
41660927d26Sdhartmei 		print_nat(r, verbose);
417e8793aa9Smcbride 		break;
418e8793aa9Smcbride 	case PF_BINAT:
419e8793aa9Smcbride 	case PF_NOBINAT:
42060927d26Sdhartmei 		print_binat(r, verbose);
421e8793aa9Smcbride 		break;
422e8793aa9Smcbride 	case PF_RDR:
423e8793aa9Smcbride 	case PF_NORDR:
42460927d26Sdhartmei 		print_rdr(r, verbose);
425e8793aa9Smcbride 		break;
426e8793aa9Smcbride 	default:
427e8793aa9Smcbride 	case PF_PASS:
428e8793aa9Smcbride 	case PF_DROP:
429e8793aa9Smcbride 	case PF_SCRUB:
430e8793aa9Smcbride 		print_filter(r, verbose);
431e8793aa9Smcbride 		break;
432e8793aa9Smcbride 	}
433e8793aa9Smcbride }
434e8793aa9Smcbride 
435e8793aa9Smcbride void
436e0c302d0Smcbride print_pool(struct pf_pool *pool, u_int16_t p1, u_int16_t p2,
437e0c302d0Smcbride     sa_family_t af, int id)
4383a44df3cSmcbride {
4393a44df3cSmcbride 	struct pf_pooladdr	*pooladdr;
4403a44df3cSmcbride 
4416c917913Smcbride 	if ((TAILQ_FIRST(&pool->list) != NULL) &&
4426c917913Smcbride 	    TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL)
4433a44df3cSmcbride 		printf("{ ");
4443a44df3cSmcbride 	TAILQ_FOREACH(pooladdr, &pool->list, entries){
4453a44df3cSmcbride 		switch (id) {
446e8793aa9Smcbride 		case PF_NAT:
447e8793aa9Smcbride 		case PF_RDR:
448e8793aa9Smcbride 		case PF_BINAT:
449e8793aa9Smcbride 			print_addr(&pooladdr->addr.addr, af);
4503a44df3cSmcbride 			break;
451e8793aa9Smcbride 		case PF_PASS:
452bcf142a4Sdhartmei 			if (PF_AZERO(&pooladdr->addr.addr.v.a.addr, af))
4533b9b234fSmcbride 				printf("%s", pooladdr->ifname);
454790504a6Sdhartmei 			else {
4553a44df3cSmcbride 				printf("(%s ", pooladdr->ifname);
456e8793aa9Smcbride 				print_addr(&pooladdr->addr.addr, af);
4573a44df3cSmcbride 				printf(")");
4583b9b234fSmcbride 			}
4593a44df3cSmcbride 			break;
460e8793aa9Smcbride 		default:
461e8793aa9Smcbride 			break;
4623a44df3cSmcbride 		}
4633a44df3cSmcbride 		if (TAILQ_NEXT(pooladdr, entries) != NULL)
4643a44df3cSmcbride 			printf(", ");
4653a44df3cSmcbride 		else if (TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL)
4663a44df3cSmcbride 			printf(" }");
4673a44df3cSmcbride 	}
468e0c302d0Smcbride 	switch (id) {
469e8793aa9Smcbride 	case PF_NAT:
470e0c302d0Smcbride 		if (p1 != PF_NAT_PROXY_PORT_LOW ||
471e0c302d0Smcbride 		    p2 != PF_NAT_PROXY_PORT_HIGH) {
472e0c302d0Smcbride 			if (p1 == p2)
473e0c302d0Smcbride 				printf(" port %u", p1);
474e0c302d0Smcbride 			else
475e0c302d0Smcbride 				printf(" port %u:%u", p1, p2);
476e0c302d0Smcbride 		}
477e0c302d0Smcbride 		break;
478e8793aa9Smcbride 	case PF_RDR:
479e0c302d0Smcbride 		if (p1) {
480e0c302d0Smcbride 			printf(" port %u", ntohs(p1));
481e8793aa9Smcbride 			if (p2 & PF_OP_RRG)
482e0c302d0Smcbride 				printf(":*");
483e0c302d0Smcbride 		}
484e0c302d0Smcbride 		break;
485e0c302d0Smcbride 	default:
486e0c302d0Smcbride 		break;
487e0c302d0Smcbride 	}
488e0c302d0Smcbride 	switch (pool->opts & PF_POOL_TYPEMASK) {
489e0c302d0Smcbride 	case PF_POOL_NONE:
490e0c302d0Smcbride 		break;
491e0c302d0Smcbride 	case PF_POOL_BITMASK:
492e0c302d0Smcbride 		printf(" bitmask");
493e0c302d0Smcbride 		break;
494e0c302d0Smcbride 	case PF_POOL_RANDOM:
495e0c302d0Smcbride 		printf(" random");
496e0c302d0Smcbride 		break;
497e0c302d0Smcbride 	case PF_POOL_SRCHASH:
4980436fa02Smcbride 		printf(" source-hash 0x%08x%08x%08x%08x",
499e0c302d0Smcbride 		    pool->key.key32[0], pool->key.key32[1],
500e0c302d0Smcbride 		    pool->key.key32[2], pool->key.key32[3]);
501e0c302d0Smcbride 		break;
502e0c302d0Smcbride 	case PF_POOL_ROUNDROBIN:
503e0c302d0Smcbride 		printf(" round-robin");
504e0c302d0Smcbride 		break;
505e0c302d0Smcbride 	}
506e0c302d0Smcbride 	if (pool->opts & PF_POOL_STATICPORT)
507e0c302d0Smcbride 		printf(" static-port");
5083a44df3cSmcbride }
5093a44df3cSmcbride 
5103a44df3cSmcbride void
51160927d26Sdhartmei print_nat(struct pf_rule *n, int verbose)
51214a9b182Skjell {
51360927d26Sdhartmei 	if (verbose)
51460927d26Sdhartmei 		printf("@%d ", n->nr);
5156ac94451Sdhartmei 	if (n->anchorname[0])
5166ac94451Sdhartmei 		printf("nat-anchor %s ", n->anchorname);
5176ac94451Sdhartmei 	else {
518e8793aa9Smcbride 		if (n->action == PF_NONAT)
519f27db9bcSdhartmei 			printf("no ");
520f27db9bcSdhartmei 		printf("nat ");
5216ac94451Sdhartmei 	}
52228964e80Sdhartmei 	if (n->ifname[0]) {
52328964e80Sdhartmei 		printf("on ");
524870b51d7Schris 		if (n->ifnot)
525870b51d7Schris 			printf("! ");
526870b51d7Schris 		printf("%s ", n->ifname);
52728964e80Sdhartmei 	}
528032e40b7Sdhartmei 	if (n->af) {
529032e40b7Sdhartmei 		if (n->af == AF_INET)
530032e40b7Sdhartmei 			printf("inet ");
531032e40b7Sdhartmei 		else
532032e40b7Sdhartmei 			printf("inet6 ");
533032e40b7Sdhartmei 	}
53480edb1f0Sdhartmei 	if (n->proto) {
535e4ebe044Shenning 		struct protoent	*p;
536ed99c291Sderaadt 
537e4ebe044Shenning 		if ((p = getprotobynumber(n->proto)) != NULL)
53880edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
53980edb1f0Sdhartmei 		else
54080edb1f0Sdhartmei 			printf("proto %u ", n->proto);
54180edb1f0Sdhartmei 	}
54215e76891Sdhartmei 	print_fromto(&n->src, &n->dst, n->af, n->proto);
543e8793aa9Smcbride 	if (!n->anchorname[0] && (n->action == PF_NAT)) {
54428964e80Sdhartmei 		printf("-> ");
545e8793aa9Smcbride 		print_pool(&n->rpool, n->rpool.proxy_port[0],
546e8793aa9Smcbride 		    n->rpool.proxy_port[1], n->af, PF_NAT);
547f27db9bcSdhartmei 	}
54814a9b182Skjell 	printf("\n");
54914a9b182Skjell }
55014a9b182Skjell 
55114a9b182Skjell void
55260927d26Sdhartmei print_binat(struct pf_rule *b, int verbose)
553a3e657d0Sjasoni {
55460927d26Sdhartmei 	if (verbose)
55560927d26Sdhartmei 		printf("@%d ", b->nr);
5566ac94451Sdhartmei 	if (b->anchorname[0])
5576ac94451Sdhartmei 		printf("binat-anchor %s ", b->anchorname);
5586ac94451Sdhartmei 	else {
559e8793aa9Smcbride 		if (b->action == PF_NOBINAT)
560f27db9bcSdhartmei 			printf("no ");
561f27db9bcSdhartmei 		printf("binat ");
5626ac94451Sdhartmei 	}
563a3e657d0Sjasoni 	if (b->ifname[0]) {
564a3e657d0Sjasoni 		printf("on ");
565a3e657d0Sjasoni 		printf("%s ", b->ifname);
566a3e657d0Sjasoni 	}
567032e40b7Sdhartmei 	if (b->af) {
568032e40b7Sdhartmei 		if (b->af == AF_INET)
569032e40b7Sdhartmei 			printf("inet ");
570032e40b7Sdhartmei 		else
571032e40b7Sdhartmei 			printf("inet6 ");
572032e40b7Sdhartmei 	}
57380edb1f0Sdhartmei 	if (b->proto) {
574e4ebe044Shenning 		struct protoent	*p;
575ed99c291Sderaadt 
576e4ebe044Shenning 		if ((p = getprotobynumber(b->proto)) != NULL)
57780edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
57880edb1f0Sdhartmei 		else
57980edb1f0Sdhartmei 			printf("proto %u ", b->proto);
580a3e657d0Sjasoni 	}
581a3e657d0Sjasoni 	printf("from ");
582bcf142a4Sdhartmei 	if (!PF_AZERO(&b->src.addr.v.a.addr, b->af) ||
583bcf142a4Sdhartmei 	    !PF_AZERO(&b->src.addr.v.a.mask, b->af)) {
584e8793aa9Smcbride 		print_addr(&b->src.addr, b->af);
585a3e657d0Sjasoni 		printf(" ");
5866ac94451Sdhartmei 	} else
5876ac94451Sdhartmei 		printf("any ");
588a3e657d0Sjasoni 	printf("to ");
589bcf142a4Sdhartmei 	if (!PF_AZERO(&b->dst.addr.v.a.addr, b->af) ||
590bcf142a4Sdhartmei 	    !PF_AZERO(&b->dst.addr.v.a.mask, b->af)) {
591e8793aa9Smcbride 		if (b->dst.not)
592a3e657d0Sjasoni 			printf("! ");
593e8793aa9Smcbride 		print_addr(&b->dst.addr, b->af);
594a3e657d0Sjasoni 		printf(" ");
595a3e657d0Sjasoni 	} else
596a3e657d0Sjasoni 		printf("any ");
597e8793aa9Smcbride 	if (!b->anchorname[0] && (b->action == PF_BINAT)) {
598a3e657d0Sjasoni 		printf("-> ");
599e8793aa9Smcbride 		print_pool(&b->rpool, 0, 0, b->af, PF_BINAT);
600f27db9bcSdhartmei 	}
601a3e657d0Sjasoni 	printf("\n");
602a3e657d0Sjasoni }
603a3e657d0Sjasoni 
604a3e657d0Sjasoni void
60560927d26Sdhartmei print_rdr(struct pf_rule *r, int verbose)
60614a9b182Skjell {
60760927d26Sdhartmei 	if (verbose)
60860927d26Sdhartmei 		printf("@%d ", r->nr);
6096ac94451Sdhartmei 	if (r->anchorname[0])
6106ac94451Sdhartmei 		printf("rdr-anchor %s ", r->anchorname);
6116ac94451Sdhartmei 	else {
612e8793aa9Smcbride 		if (r->action == PF_NORDR)
613f27db9bcSdhartmei 			printf("no ");
614f27db9bcSdhartmei 		printf("rdr ");
6156ac94451Sdhartmei 	}
61628964e80Sdhartmei 	if (r->ifname[0]) {
61728964e80Sdhartmei 		printf("on ");
618870b51d7Schris 		if (r->ifnot)
619870b51d7Schris 			printf("! ");
620870b51d7Schris 		printf("%s ", r->ifname);
62128964e80Sdhartmei 	}
622032e40b7Sdhartmei 	if (r->af) {
623032e40b7Sdhartmei 		if (r->af == AF_INET)
624032e40b7Sdhartmei 			printf("inet ");
625032e40b7Sdhartmei 		else
626032e40b7Sdhartmei 			printf("inet6 ");
627032e40b7Sdhartmei 	}
62880edb1f0Sdhartmei 	if (r->proto) {
629e4ebe044Shenning 		struct protoent	*p;
630ed99c291Sderaadt 
631e4ebe044Shenning 		if ((p = getprotobynumber(r->proto)) != NULL)
63280edb1f0Sdhartmei 			printf("proto %s ", p->p_name);
63380edb1f0Sdhartmei 		else
63480edb1f0Sdhartmei 			printf("proto %u ", r->proto);
635e3d52469Smillert 	}
63628964e80Sdhartmei 	printf("from ");
637bcf142a4Sdhartmei 	if (!PF_AZERO(&r->src.addr.v.a.addr, r->af) ||
638bcf142a4Sdhartmei 	    !PF_AZERO(&r->src.addr.v.a.mask, r->af)) {
639e8793aa9Smcbride 		if (r->src.not)
64028964e80Sdhartmei 			printf("! ");
641e8793aa9Smcbride 		print_addr(&r->src.addr, r->af);
64228964e80Sdhartmei 		printf(" ");
64328964e80Sdhartmei 	} else
64428964e80Sdhartmei 		printf("any ");
64528964e80Sdhartmei 	printf("to ");
646bcf142a4Sdhartmei 	if (!PF_AZERO(&r->dst.addr.v.a.addr, r->af) ||
647bcf142a4Sdhartmei 	    !PF_AZERO(&r->dst.addr.v.a.mask, r->af)) {
648e8793aa9Smcbride 		if (r->dst.not)
64914a9b182Skjell 			printf("! ");
650e8793aa9Smcbride 		print_addr(&r->dst.addr, r->af);
65128964e80Sdhartmei 		printf(" ");
65228964e80Sdhartmei 	} else
65328964e80Sdhartmei 		printf("any ");
654e8793aa9Smcbride 	if (r->dst.port[0]) {
655e8793aa9Smcbride 		printf("port %u", ntohs(r->dst.port[0]));
656e8793aa9Smcbride 		if (r->rpool.port_op & PF_OP_RRG)
657e8793aa9Smcbride 			printf(":%u", ntohs(r->dst.port[1]));
6580436fa02Smcbride 		printf(" ");
65980edb1f0Sdhartmei 	}
660e8793aa9Smcbride 	if (!r->anchorname[0] && (r->action == PF_RDR)) {
661cb07131dSkjell 		printf("-> ");
662e8793aa9Smcbride 		print_pool(&r->rpool, r->rpool.proxy_port[0],
663e8793aa9Smcbride 		    r->rpool.port_op, r->af, PF_RDR);
664f27db9bcSdhartmei 	}
66514a9b182Skjell 	printf("\n");
66614a9b182Skjell }
66714a9b182Skjell 
668bca2bf17Sdhartmei char	*pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
669bca2bf17Sdhartmei char	*pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
67099a73934Sderaadt 
67114a9b182Skjell void
67281a15e5dSderaadt print_status(struct pf_status *s)
67314a9b182Skjell {
674e4ebe044Shenning 	char	statline[80];
675c474e331Shenning 	time_t	runtime;
67699a73934Sderaadt 	int	i;
67799a73934Sderaadt 
678c474e331Shenning 	runtime = time(NULL) - s->since;
679c474e331Shenning 
680d85e4ad6Sdhartmei 	if (s->running) {
681d85e4ad6Sdhartmei 		unsigned	sec, min, hrs, day = runtime;
682d85e4ad6Sdhartmei 
683d85e4ad6Sdhartmei 		sec = day % 60;
684d85e4ad6Sdhartmei 		day /= 60;
685d85e4ad6Sdhartmei 		min = day % 60;
686d85e4ad6Sdhartmei 		day /= 60;
687d85e4ad6Sdhartmei 		hrs = day % 24;
688d85e4ad6Sdhartmei 		day /= 24;
689c474e331Shenning 		snprintf(statline, sizeof(statline),
690d85e4ad6Sdhartmei 		    "Status: Enabled for %u days %.2u:%.2u:%.2u",
691d85e4ad6Sdhartmei 		    day, hrs, min, sec);
692d85e4ad6Sdhartmei 	} else
693c474e331Shenning 		snprintf(statline, sizeof(statline), "Status: Disabled");
694c97b4ee1Shenning 	printf("%-44s", statline);
695ae58c8acSdhartmei 	switch (s->debug) {
696ae58c8acSdhartmei 	case 0:
697c97b4ee1Shenning 		printf("%15s\n\n", "Debug: None");
698ae58c8acSdhartmei 		break;
699ae58c8acSdhartmei 	case 1:
700c97b4ee1Shenning 		printf("%15s\n\n", "Debug: Urgent");
701ae58c8acSdhartmei 		break;
702ae58c8acSdhartmei 	case 2:
703c97b4ee1Shenning 		printf("%15s\n\n", "Debug: Misc");
704ae58c8acSdhartmei 		break;
705ae58c8acSdhartmei 	}
706c474e331Shenning 	if (s->ifname[0] != 0) {
707c474e331Shenning 		printf("Interface Stats for %-16s %5s %16s\n",
708c474e331Shenning 		    s->ifname, "IPv4", "IPv6");
709c474e331Shenning 		printf("  %-25s %14llu %16llu\n", "Bytes In",
7107189e280Sdhartmei 		    s->bcounters[0][0], s->bcounters[1][0]);
711c474e331Shenning 		printf("  %-25s %14llu %16llu\n", "Bytes Out",
7127189e280Sdhartmei 		    s->bcounters[0][1], s->bcounters[1][1]);
713c474e331Shenning 		printf("  Packets In\n");
714c474e331Shenning 		printf("    %-23s %14llu %16llu\n", "Passed",
7157189e280Sdhartmei 		    s->pcounters[0][0][PF_PASS],
7167189e280Sdhartmei 		    s->pcounters[1][0][PF_PASS]);
717c474e331Shenning 		printf("    %-23s %14llu %16llu\n", "Blocked",
7187189e280Sdhartmei 		    s->pcounters[0][0][PF_DROP],
7197189e280Sdhartmei 		    s->pcounters[1][0][PF_DROP]);
720c474e331Shenning 		printf("  Packets Out\n");
721c474e331Shenning 		printf("    %-23s %14llu %16llu\n", "Passed",
7227189e280Sdhartmei 		    s->pcounters[0][1][PF_PASS],
7237189e280Sdhartmei 		    s->pcounters[1][1][PF_PASS]);
724c474e331Shenning 		printf("    %-23s %14llu %16llu\n\n", "Blocked",
7257189e280Sdhartmei 		    s->pcounters[0][1][PF_DROP],
7267189e280Sdhartmei 		    s->pcounters[1][1][PF_DROP]);
727c474e331Shenning 	}
728c474e331Shenning 	printf("%-27s %14s %16s\n", "State Table", "Total", "Rate");
729c474e331Shenning 	printf("  %-25s %14u %14s\n", "current entries", s->states, "");
730c474e331Shenning 	for (i = 0; i < FCNT_MAX; i++) {
731c474e331Shenning 		printf("  %-25s %14lld ", pf_fcounters[i],
73284976600Sderaadt 			    s->fcounters[i]);
733c474e331Shenning 		if (runtime > 0)
734c474e331Shenning 			printf("%14.1f/s\n",
735c474e331Shenning 			    (double)s->fcounters[i] / (double)runtime);
736c474e331Shenning 		else
737c474e331Shenning 			printf("%14s\n", "");
738c474e331Shenning 	}
73999a73934Sderaadt 	printf("Counters\n");
740c474e331Shenning 	for (i = 0; i < PFRES_MAX; i++) {
741c474e331Shenning 		printf("  %-25s %14lld ", pf_reasons[i],
74299a73934Sderaadt 		    s->counters[i]);
743c474e331Shenning 		if (runtime > 0)
744c474e331Shenning 			printf("%14.1f/s\n",
745c474e331Shenning 			    (double)s->counters[i] / (double)runtime);
746c474e331Shenning 		else
747c474e331Shenning 			printf("%14s\n", "");
748c474e331Shenning 	}
74914a9b182Skjell }
75014a9b182Skjell 
75114a9b182Skjell void
752e8793aa9Smcbride print_filter(struct pf_rule *r, int verbose)
75314a9b182Skjell {
754cc5f0329Sdhartmei 	int	i, opts;
755cc5f0329Sdhartmei 
75674dc4fddShenning 	if (verbose)
75778baf774Sdhartmei 		printf("@%d ", r->nr);
7586ac94451Sdhartmei 	if (r->anchorname[0])
7596ac94451Sdhartmei 		printf("anchor %s ", r->anchorname);
7606ac94451Sdhartmei 	else if (r->action == PF_PASS)
76114a9b182Skjell 		printf("pass ");
762b996d042Sdhartmei 	else if (r->action == PF_DROP) {
76314a9b182Skjell 		printf("block ");
7648a87542aShenning 		if (r->rule_flag & PFRULE_RETURN)
7658a87542aShenning 			printf("return ");
7668a87542aShenning 		else if (r->rule_flag & PFRULE_RETURNRST) {
7671f77cc8aSpb 			if (!r->return_ttl)
76814a9b182Skjell 				printf("return-rst ");
7691f77cc8aSpb 			else
7701f77cc8aSpb 				printf("return-rst(ttl %d) ", r->return_ttl);
771328b2decShenning 		} else if (r->rule_flag & PFRULE_RETURNICMP) {
772328b2decShenning 			const struct icmpcodeent	*ic, *ic6;
773b996d042Sdhartmei 
774b996d042Sdhartmei 			ic = geticmpcodebynumber(r->return_icmp >> 8,
775328b2decShenning 			    r->return_icmp & 255, AF_INET);
776328b2decShenning 			ic6 = geticmpcodebynumber(r->return_icmp6 >> 8,
777328b2decShenning 			    r->return_icmp6 & 255, AF_INET6);
778d14c53d7Swilfried 
779328b2decShenning 			switch(r->af) {
780328b2decShenning 			case AF_INET:
781328b2decShenning 				printf("return-icmp");
782d14c53d7Swilfried 				if (ic == NULL)
783d14c53d7Swilfried 					printf("(%u) ", r->return_icmp & 255);
784b996d042Sdhartmei 				else
785328b2decShenning 					printf("(%s) ", ic->name);
786328b2decShenning 				break;
787328b2decShenning 			case AF_INET6:
788328b2decShenning 				printf("return-icmp6");
789328b2decShenning 				if (ic6 == NULL)
790328b2decShenning 					printf("(%u) ", r->return_icmp6 & 255);
791328b2decShenning 				else
792328b2decShenning 					printf("(%s) ", ic6->name);
793328b2decShenning 				break;
794328b2decShenning 			default:
795328b2decShenning 				printf("return-icmp");
796328b2decShenning 				if (ic == NULL)
797328b2decShenning 					printf("(%u, ", r->return_icmp & 255);
798328b2decShenning 				else
799328b2decShenning 					printf("(%s, ", ic->name);
800328b2decShenning 				if (ic6 == NULL)
801328b2decShenning 					printf("%u) ", r->return_icmp6 & 255);
802328b2decShenning 				else
803328b2decShenning 					printf("%s) ", ic6->name);
804328b2decShenning 				break;
805328b2decShenning 			}
806acf2444cShenning 		} else
807acf2444cShenning 			printf("drop ");
8086ac94451Sdhartmei 	} else
809b996d042Sdhartmei 		printf("scrub ");
8107189e280Sdhartmei 	if (r->direction == PF_IN)
81114a9b182Skjell 		printf("in ");
8127189e280Sdhartmei 	else if (r->direction == PF_OUT)
81314a9b182Skjell 		printf("out ");
8147242ce7aSdhartmei 	if (r->log == 1)
81514a9b182Skjell 		printf("log ");
8167242ce7aSdhartmei 	else if (r->log == 2)
8177242ce7aSdhartmei 		printf("log-all ");
81814a9b182Skjell 	if (r->quick)
81914a9b182Skjell 		printf("quick ");
8207d0c9138Shenning 	if (r->ifname[0]) {
8217d0c9138Shenning 		if (r->ifnot)
8227d0c9138Shenning 			printf("on ! %s ", r->ifname);
8237d0c9138Shenning 		else
82414a9b182Skjell 			printf("on %s ", r->ifname);
8257d0c9138Shenning 	}
826cb3a4e31Sjasoni 	if (r->rt) {
827cb3a4e31Sjasoni 		if (r->rt == PF_ROUTETO)
828cb3a4e31Sjasoni 			printf("route-to ");
829fa1cdd09Sdhartmei 		else if (r->rt == PF_REPLYTO)
830fa1cdd09Sdhartmei 			printf("reply-to ");
831cb3a4e31Sjasoni 		else if (r->rt == PF_DUPTO)
832cb3a4e31Sjasoni 			printf("dup-to ");
833cb3a4e31Sjasoni 		else if (r->rt == PF_FASTROUTE)
834cb3a4e31Sjasoni 			printf("fastroute ");
835790504a6Sdhartmei 		if (r->rt != PF_FASTROUTE) {
836e8793aa9Smcbride 			print_pool(&r->rpool, 0, 0, r->af, PF_PASS);
837790504a6Sdhartmei 			printf(" ");
838790504a6Sdhartmei 		}
839cb3a4e31Sjasoni 	}
84030620b12Sfrantzen 	if (r->af) {
84130620b12Sfrantzen 		if (r->af == AF_INET)
84230620b12Sfrantzen 			printf("inet ");
84330620b12Sfrantzen 		else
84430620b12Sfrantzen 			printf("inet6 ");
84530620b12Sfrantzen 	}
84614a9b182Skjell 	if (r->proto) {
847e4ebe044Shenning 		struct protoent	*p;
848ed99c291Sderaadt 
849e4ebe044Shenning 		if ((p = getprotobynumber(r->proto)) != NULL)
85014a9b182Skjell 			printf("proto %s ", p->p_name);
85114a9b182Skjell 		else
85214a9b182Skjell 			printf("proto %u ", r->proto);
85314a9b182Skjell 	}
85415e76891Sdhartmei 	print_fromto(&r->src, &r->dst, r->af, r->proto);
855c16ab608Sdhartmei 	if (r->uid.op)
856c16ab608Sdhartmei 		print_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user");
857c16ab608Sdhartmei 	if (r->gid.op)
858c16ab608Sdhartmei 		print_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group");
85914a9b182Skjell 	if (r->flags || r->flagset) {
86014a9b182Skjell 		printf("flags ");
86114a9b182Skjell 		print_flags(r->flags);
86214a9b182Skjell 		printf("/");
86314a9b182Skjell 		print_flags(r->flagset);
86414a9b182Skjell 		printf(" ");
86514a9b182Skjell 	}
866082ebc44Swilfried 	if (r->type) {
867b49ca6bbShenning 		const struct icmptypeent	*it;
868082ebc44Swilfried 
869b49ca6bbShenning 		it = geticmptypebynumber(r->type-1, r->af);
870d14c53d7Swilfried 		if (r->af != AF_INET6)
871d14c53d7Swilfried 			printf("icmp-type");
872082ebc44Swilfried 		else
873d0cb3502Smcbride 			printf("icmp6-type");
874b49ca6bbShenning 		if (it != NULL)
875b49ca6bbShenning 			printf(" %s ", it->name);
876d14c53d7Swilfried 		else
877d14c53d7Swilfried 			printf(" %u ", r->type-1);
878082ebc44Swilfried 		if (r->code) {
879b49ca6bbShenning 			const struct icmpcodeent	*ic;
880082ebc44Swilfried 
881b49ca6bbShenning 			ic = geticmpcodebynumber(r->type-1, r->code-1, r->af);
882b49ca6bbShenning 			if (ic != NULL)
883b49ca6bbShenning 				printf("code %s ", ic->name);
884082ebc44Swilfried 			else
88514a9b182Skjell 				printf("code %u ", r->code-1);
886082ebc44Swilfried 		}
887082ebc44Swilfried 	}
888e4cbe364Sdhartmei 	if (r->tos)
889e4cbe364Sdhartmei 		printf("tos 0x%2.2x ", r->tos);
890b96c47abSfrantzen 	if (r->keep_state == PF_STATE_NORMAL)
89114a9b182Skjell 		printf("keep state ");
892b96c47abSfrantzen 	else if (r->keep_state == PF_STATE_MODULATE)
893b96c47abSfrantzen 		printf("modulate state ");
894cc5f0329Sdhartmei 	opts = 0;
895b3c86969Sdhartmei 	if (r->max_states)
896cc5f0329Sdhartmei 		opts = 1;
897cc5f0329Sdhartmei 	for (i = 0; !opts && i < PFTM_MAX; ++i)
898cc5f0329Sdhartmei 		if (r->timeout[i])
899cc5f0329Sdhartmei 			opts = 1;
900cc5f0329Sdhartmei 	if (opts) {
901cc5f0329Sdhartmei 		printf("(");
902cc5f0329Sdhartmei 		if (r->max_states) {
903cc5f0329Sdhartmei 			printf("max %u", r->max_states);
904cc5f0329Sdhartmei 			opts = 0;
905cc5f0329Sdhartmei 		}
906cc5f0329Sdhartmei 		for (i = 0; i < PFTM_MAX; ++i)
907cc5f0329Sdhartmei 			if (r->timeout[i]) {
908cc5f0329Sdhartmei 				if (!opts)
909cc5f0329Sdhartmei 					printf(", ");
910cc5f0329Sdhartmei 				opts = 0;
911cc5f0329Sdhartmei 				printf("%s %u", pf_timeouts[i].name,
912cc5f0329Sdhartmei 				    r->timeout[i]);
913cc5f0329Sdhartmei 			}
914cc5f0329Sdhartmei 		printf(") ");
915cc5f0329Sdhartmei 	}
9166673dee2Sdhartmei 	if (r->rule_flag & PFRULE_FRAGMENT)
9176673dee2Sdhartmei 		printf("fragment ");
91867d2a440Sprovos 	if (r->rule_flag & PFRULE_NODF)
91967d2a440Sprovos 		printf("no-df ");
920e258bfd4Sprovos 	if (r->min_ttl)
92134c76dcbSprovos 		printf("min-ttl %d ", r->min_ttl);
922cfa91859Sjasoni 	if (r->max_mss)
923cfa91859Sjasoni 		printf("max-mss %d ", r->max_mss);
924f48d62b3Sdhartmei 	if (r->allow_opts)
925f48d62b3Sdhartmei 		printf("allow-opts ");
926b02af636Sfrantzen 	if (r->action == PF_SCRUB) {
927b02af636Sfrantzen 		if (r->rule_flag & PFRULE_FRAGDROP)
928b02af636Sfrantzen 			printf("fragment drop-ovl ");
929b02af636Sfrantzen 		else if (r->rule_flag & PFRULE_FRAGCROP)
930b02af636Sfrantzen 			printf("fragment crop ");
931b02af636Sfrantzen 		else
932b02af636Sfrantzen 			printf("fragment reassemble ");
933b02af636Sfrantzen 	}
934455ef0c1Sdhartmei 	if (r->label[0])
935*ff45dfa8Scamield 		printf("label \"%s\" ", r->label);
936f98324c6Shenning 	if (r->qname[0] && r->pqname[0])
937f98324c6Shenning 		printf("queue(%s, %s) ", r->qname, r->pqname);
938f98324c6Shenning 	else if (r->qname[0])
93978e1d2a6Shenning 		printf("queue %s ", r->qname);
94067d2a440Sprovos 
94114a9b182Skjell 	printf("\n");
94214a9b182Skjell }
94314a9b182Skjell 
9441f8f21bdSmillert int
945ff352a37Smarkus parse_flags(char *s)
94614a9b182Skjell {
947ff352a37Smarkus 	char		*p, *q;
94814a9b182Skjell 	u_int8_t	 f = 0;
94981a15e5dSderaadt 
950ff352a37Smarkus 	for (p = s; *p; p++) {
951ff352a37Smarkus 		if ((q = strchr(tcpflags, *p)) == NULL)
952ff352a37Smarkus 			return -1;
953ff352a37Smarkus 		else
954ff352a37Smarkus 			f |= 1 << (q - tcpflags);
95514a9b182Skjell 	}
956bc795af0Shugh 	return (f ? f : PF_TH_ALL);
95714a9b182Skjell }
95894e9410bShenning 
95994e9410bShenning void
96094e9410bShenning set_ipmask(struct node_host *h, u_int8_t b)
96194e9410bShenning {
96294e9410bShenning 	struct pf_addr	*m, *n;
96394e9410bShenning 	int		 i, j = 0;
96494e9410bShenning 
96594e9410bShenning 	m = &h->addr.v.a.mask;
96694e9410bShenning 
96794e9410bShenning 	for (i = 0; i < 4; i++)
96894e9410bShenning 		m->addr32[i] = 0;
96994e9410bShenning 
97094e9410bShenning 	while (b >= 32) {
97194e9410bShenning 		m->addr32[j++] = 0xffffffff;
97294e9410bShenning 		b -= 32;
97394e9410bShenning 	}
97494e9410bShenning 	for (i = 31; i > 31-b; --i)
97594e9410bShenning 		m->addr32[j] |= (1 << i);
97694e9410bShenning 	if (b)
97794e9410bShenning 		m->addr32[j] = htonl(m->addr32[j]);
97894e9410bShenning 
97994e9410bShenning 	/* Mask off bits of the address that will never be used. */
98094e9410bShenning 	n = &h->addr.v.a.addr;
98194e9410bShenning 	for (i = 0; i < 4; i++)
98294e9410bShenning 		n->addr32[i] = n->addr32[i] & m->addr32[i];
98394e9410bShenning }
98494e9410bShenning 
98594e9410bShenning /* interface lookup routines */
98694e9410bShenning 
98794e9410bShenning struct node_host	*iftab;
98894e9410bShenning 
98994e9410bShenning void
99094e9410bShenning ifa_load(void)
99194e9410bShenning {
99294e9410bShenning 	struct ifaddrs		*ifap, *ifa;
99394e9410bShenning 	struct node_host	*n = NULL, *h = NULL;
99494e9410bShenning 
99594e9410bShenning 	if (getifaddrs(&ifap) < 0)
99694e9410bShenning 		err(1, "getifaddrs");
99794e9410bShenning 
99894e9410bShenning 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
99994e9410bShenning 		if (!(ifa->ifa_addr->sa_family == AF_INET ||
100094e9410bShenning 		    ifa->ifa_addr->sa_family == AF_INET6 ||
100194e9410bShenning 		    ifa->ifa_addr->sa_family == AF_LINK))
100294e9410bShenning 				continue;
100394e9410bShenning 		n = calloc(1, sizeof(struct node_host));
100494e9410bShenning 		if (n == NULL)
100594e9410bShenning 			err(1, "address: calloc");
100694e9410bShenning 		n->af = ifa->ifa_addr->sa_family;
100794e9410bShenning 		n->ifa_flags = ifa->ifa_flags;
100894e9410bShenning #ifdef __KAME__
100994e9410bShenning 		if (n->af == AF_INET6 &&
101094e9410bShenning 		    IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)
101194e9410bShenning 		    ifa->ifa_addr)->sin6_addr) &&
101294e9410bShenning 		    ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 0) {
101394e9410bShenning 			struct sockaddr_in6	*sin6;
101494e9410bShenning 
101594e9410bShenning 			sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
101694e9410bShenning 			sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 |
101794e9410bShenning 			    sin6->sin6_addr.s6_addr[3];
101894e9410bShenning 			sin6->sin6_addr.s6_addr[2] = 0;
101994e9410bShenning 			sin6->sin6_addr.s6_addr[3] = 0;
102094e9410bShenning 		}
102194e9410bShenning #endif
102294e9410bShenning 		n->ifindex = 0;
102394e9410bShenning 		if (n->af == AF_INET) {
102494e9410bShenning 			memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *)
102594e9410bShenning 			    ifa->ifa_addr)->sin_addr.s_addr,
102694e9410bShenning 			    sizeof(struct in_addr));
102794e9410bShenning 			memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *)
102894e9410bShenning 			    ifa->ifa_netmask)->sin_addr.s_addr,
102994e9410bShenning 			    sizeof(struct in_addr));
103094e9410bShenning 			if (ifa->ifa_broadaddr != NULL)
103194e9410bShenning 				memcpy(&n->bcast, &((struct sockaddr_in *)
103294e9410bShenning 				    ifa->ifa_broadaddr)->sin_addr.s_addr,
103394e9410bShenning 				    sizeof(struct in_addr));
103494e9410bShenning 		} else if (n->af == AF_INET6) {
103594e9410bShenning 			memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *)
103694e9410bShenning 			    ifa->ifa_addr)->sin6_addr.s6_addr,
103794e9410bShenning 			    sizeof(struct in6_addr));
103894e9410bShenning 			memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *)
103994e9410bShenning 			    ifa->ifa_netmask)->sin6_addr.s6_addr,
104094e9410bShenning 			    sizeof(struct in6_addr));
104194e9410bShenning 			if (ifa->ifa_broadaddr != NULL)
104294e9410bShenning 				memcpy(&n->bcast, &((struct sockaddr_in6 *)
104394e9410bShenning 				    ifa->ifa_broadaddr)->sin6_addr.s6_addr,
104494e9410bShenning 				    sizeof(struct in6_addr));
104594e9410bShenning 			n->ifindex = ((struct sockaddr_in6 *)
104694e9410bShenning 			    ifa->ifa_addr)->sin6_scope_id;
104794e9410bShenning 		}
104894e9410bShenning 		if ((n->ifname = strdup(ifa->ifa_name)) == NULL)
104994e9410bShenning 			err(1, "ifa_load: strdup");
105094e9410bShenning 		n->next = NULL;
105194e9410bShenning 		n->tail = n;
105294e9410bShenning 		if (h == NULL)
105394e9410bShenning 			h = n;
105494e9410bShenning 		else {
105594e9410bShenning 			h->tail->next = n;
105694e9410bShenning 			h->tail = n;
105794e9410bShenning 		}
105894e9410bShenning 	}
105994e9410bShenning 	iftab = h;
106094e9410bShenning 	freeifaddrs(ifap);
106194e9410bShenning }
106294e9410bShenning 
106394e9410bShenning struct node_host *
106494e9410bShenning ifa_exists(char *ifa_name)
106594e9410bShenning {
106694e9410bShenning 	struct node_host	*n;
106794e9410bShenning 
106894e9410bShenning 	if (iftab == NULL)
106994e9410bShenning 		ifa_load();
107094e9410bShenning 
107194e9410bShenning 	for (n = iftab; n; n = n->next) {
107294e9410bShenning 		if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
107394e9410bShenning 			return (n);
107494e9410bShenning 	}
107594e9410bShenning 	return (NULL);
107694e9410bShenning }
107794e9410bShenning 
107894e9410bShenning struct node_host *
107994e9410bShenning ifa_lookup(char *ifa_name, enum pfctl_iflookup_mode mode)
108094e9410bShenning {
108194e9410bShenning 	struct node_host	*p = NULL, *h = NULL, *n = NULL;
108294e9410bShenning 	int			 return_all = 0;
108394e9410bShenning 
108494e9410bShenning 	if (!strncmp(ifa_name, "self", IFNAMSIZ))
108594e9410bShenning 		return_all = 1;
108694e9410bShenning 
108794e9410bShenning 	if (iftab == NULL)
108894e9410bShenning 		ifa_load();
108994e9410bShenning 
109094e9410bShenning 	for (p = iftab; p; p = p->next) {
109194e9410bShenning 		if (!((p->af == AF_INET || p->af == AF_INET6) &&
109294e9410bShenning 		    (!strncmp(p->ifname, ifa_name, IFNAMSIZ) || return_all)))
109394e9410bShenning 			continue;
109494e9410bShenning 		if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET)
109594e9410bShenning 			continue;
109694e9410bShenning 		if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0)
109794e9410bShenning 			continue;
109894e9410bShenning 		n = calloc(1, sizeof(struct node_host));
109994e9410bShenning 		if (n == NULL)
110094e9410bShenning 			err(1, "address: calloc");
110194e9410bShenning 		n->af = p->af;
110294e9410bShenning 		if (mode == PFCTL_IFLOOKUP_BCAST)
110394e9410bShenning 			memcpy(&n->addr.v.a.addr, &p->bcast,
110494e9410bShenning 			    sizeof(struct pf_addr));
110594e9410bShenning 		else
110694e9410bShenning 			memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr,
110794e9410bShenning 			    sizeof(struct pf_addr));
110894e9410bShenning 		if (mode == PFCTL_IFLOOKUP_NET)
110994e9410bShenning 			set_ipmask(n, unmask(&p->addr.v.a.mask, n->af));
111094e9410bShenning 		else {
111194e9410bShenning 			if (n->af == AF_INET) {
111294e9410bShenning 				if (p->ifa_flags & IFF_LOOPBACK &&
111394e9410bShenning 				    p->ifa_flags & IFF_LINK1)
111494e9410bShenning 					memcpy(&n->addr.v.a.mask,
111594e9410bShenning 					    &p->addr.v.a.mask,
111694e9410bShenning 					    sizeof(struct pf_addr));
111794e9410bShenning 				else
111894e9410bShenning 					set_ipmask(n, 32);
111994e9410bShenning 			} else
112094e9410bShenning 				set_ipmask(n, 128);
112194e9410bShenning 		}
112294e9410bShenning 		n->ifindex = p->ifindex;
112394e9410bShenning 
112494e9410bShenning 		n->next = NULL;
112594e9410bShenning 		n->tail = n;
112694e9410bShenning 		if (h == NULL)
112794e9410bShenning 			h = n;
112894e9410bShenning 		else {
112994e9410bShenning 			h->tail->next = n;
113094e9410bShenning 			h->tail = n;
113194e9410bShenning 		}
113294e9410bShenning 	}
113394e9410bShenning 	if (h == NULL && mode == PFCTL_IFLOOKUP_HOST) {
113494e9410bShenning 		fprintf(stderr, "no IP address found for %s\n", ifa_name);
113594e9410bShenning 	}
113694e9410bShenning 	return (h);
113794e9410bShenning }
113894e9410bShenning 
113994e9410bShenning struct node_host *
114094e9410bShenning host(char *s, int mask)
114194e9410bShenning {
11422a6c1abaShenning 	struct node_host	*h = NULL;
11432a6c1abaShenning 	int			 v4mask, v6mask, cont = 1;
114494e9410bShenning 	char			*buf = NULL, *p, *q, *ps;
114594e9410bShenning 
114694e9410bShenning 	if ((p = strrchr(s, '/')) != NULL) {
114794e9410bShenning 		if (mask != -1) {
114894e9410bShenning 			fprintf(stderr, "address with netmask specified"
114994e9410bShenning 			    "and extra netmask supplied\n");
115094e9410bShenning 			return (NULL);
115194e9410bShenning 		}
115294e9410bShenning 		mask = strtol(p+1, &q, 0);
115394e9410bShenning 		if (!q || *q) {
115494e9410bShenning 			fprintf(stderr, "invalid netmask\n");
115594e9410bShenning 			return (NULL);
115694e9410bShenning 		}
115794e9410bShenning 		if (asprintf(&buf, "%s", s) == -1)
115894e9410bShenning 			err(1, "host: asprintf");
115994e9410bShenning 		if ((ps = malloc(strlen(s) + 1)) == NULL)
116094e9410bShenning 			err(1, "host: malloc");
116194e9410bShenning 		strlcpy(ps, s, strlen(s) - strlen(p) + 1);
116294e9410bShenning 		v4mask = v6mask = mask;
116394e9410bShenning 	} else {
116494e9410bShenning 		if (asprintf(&ps, "%s", s) == -1)
116594e9410bShenning 			err(1, "host: asprintf");
116694e9410bShenning 		if (mask == -1) {
116794e9410bShenning 			if (asprintf(&buf, "%s", s) == -1)
116894e9410bShenning 				err(1, "host: asprintf");
116994e9410bShenning 			v4mask = 32;
117094e9410bShenning 			v6mask = 128;
117194e9410bShenning 		} else if (mask <= 128) {
117294e9410bShenning 			if (asprintf(&buf, "%s/%d", s, mask) == -1)
117394e9410bShenning 				err(1, "host: asprintf");
117494e9410bShenning 			v4mask = v6mask = mask;
117594e9410bShenning 		} else {
117694e9410bShenning 			fprintf(stderr, "illegal mask\n");
117794e9410bShenning 			return (NULL);
117894e9410bShenning 		}
117994e9410bShenning 	}
118094e9410bShenning 
11812a6c1abaShenning 	/* interface with this name exists? */
11822a6c1abaShenning 	if (cont && (h = host_if(ps, mask)) != NULL)
11832a6c1abaShenning 		cont = 0;
11842a6c1abaShenning 
11852a6c1abaShenning 	/* IPv4 address? */
11862a6c1abaShenning 	if (cont && (h = host_v4(buf)) != NULL)
11872a6c1abaShenning 		cont = 0;
11882a6c1abaShenning 	free(buf);
11892a6c1abaShenning 
11902a6c1abaShenning 	/* IPv6 address? */
11912a6c1abaShenning 	if (cont && (h = host_v6(ps, v6mask)) != NULL)
11922a6c1abaShenning 		cont = 0;
11932a6c1abaShenning 
11942a6c1abaShenning 	/* dns lookup */
11952a6c1abaShenning 	if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL)
11962a6c1abaShenning 		cont = 0;
11972a6c1abaShenning 	free(ps);
11982a6c1abaShenning 
11992a6c1abaShenning 	if (h == NULL || cont == 1) {
12002a6c1abaShenning 		fprintf(stderr, "no IP address found for %s\n", s);
12012a6c1abaShenning 		return (NULL);
12022a6c1abaShenning 	}
12032a6c1abaShenning 	return (h);
12042a6c1abaShenning }
12052a6c1abaShenning 
12062a6c1abaShenning struct node_host *
12072a6c1abaShenning host_if(char *s, int mask)
12082a6c1abaShenning {
12092a6c1abaShenning 	struct node_host	*n, *h = NULL;
12102a6c1abaShenning 
12112a6c1abaShenning 	if (ifa_exists(s) || !strncmp(s, "self", IFNAMSIZ)) {
12122a6c1abaShenning 		/* interface with this name exists */
12132a6c1abaShenning 		h = ifa_lookup(s, PFCTL_IFLOOKUP_HOST);
12142a6c1abaShenning 		for (n = h; n != NULL && mask > -1; n = n->next)
12152a6c1abaShenning 			set_ipmask(n, mask);
12162a6c1abaShenning 	}
12172a6c1abaShenning 	return (h);
12182a6c1abaShenning }
12192a6c1abaShenning 
12202a6c1abaShenning struct node_host *
12212a6c1abaShenning host_v4(char *s)
12222a6c1abaShenning {
12232a6c1abaShenning 	struct node_host	*h = NULL;
12242a6c1abaShenning 	struct in_addr		 ina;
12252a6c1abaShenning 	int			 bits;
12262a6c1abaShenning 
122794e9410bShenning 	memset(&ina, 0, sizeof(struct in_addr));
12282a6c1abaShenning 	if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(&ina))) > -1) {
122994e9410bShenning 		h = calloc(1, sizeof(struct node_host));
123094e9410bShenning 		if (h == NULL)
123194e9410bShenning 			err(1, "address: calloc");
123294e9410bShenning 		h->ifname = NULL;
123394e9410bShenning 		h->af = AF_INET;
123494e9410bShenning 		h->addr.v.a.addr.addr32[0] = ina.s_addr;
123594e9410bShenning 		set_ipmask(h, bits);
123694e9410bShenning 		h->next = NULL;
123794e9410bShenning 		h->tail = h;
123894e9410bShenning 	}
12392a6c1abaShenning 
124094e9410bShenning 	return (h);
124194e9410bShenning }
12422a6c1abaShenning 
12432a6c1abaShenning struct node_host *
12442a6c1abaShenning host_v6(char *s, int mask)
12452a6c1abaShenning {
12462a6c1abaShenning 	struct addrinfo		 hints, *res;
12472a6c1abaShenning 	struct node_host	*h = NULL;
124894e9410bShenning 
124994e9410bShenning 	memset(&hints, 0, sizeof(hints));
125094e9410bShenning 	hints.ai_family = AF_INET6;
125194e9410bShenning 	hints.ai_socktype = SOCK_DGRAM; /*dummy*/
125294e9410bShenning 	hints.ai_flags = AI_NUMERICHOST;
12532a6c1abaShenning 	if (getaddrinfo(s, "0", &hints, &res) == 0) {
12542a6c1abaShenning 		h = calloc(1, sizeof(struct node_host));
12552a6c1abaShenning 		if (h == NULL)
125694e9410bShenning 			err(1, "address: calloc");
12572a6c1abaShenning 		h->ifname = NULL;
12582a6c1abaShenning 		h->af = AF_INET6;
12592a6c1abaShenning 		memcpy(&h->addr.v.a.addr,
126094e9410bShenning 		    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
12612a6c1abaShenning 		    sizeof(h->addr.v.a.addr));
12622a6c1abaShenning 		h->ifindex =
12632a6c1abaShenning 		    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
12642a6c1abaShenning 		set_ipmask(h, mask);
126594e9410bShenning 		freeaddrinfo(res);
12662a6c1abaShenning 		h->next = NULL;
12672a6c1abaShenning 		h->tail = h;
126894e9410bShenning 	}
126994e9410bShenning 
12702a6c1abaShenning 	return (h);
12712a6c1abaShenning }
12722a6c1abaShenning 
12732a6c1abaShenning struct node_host *
12742a6c1abaShenning host_dns(char *s, int v4mask, int v6mask)
12752a6c1abaShenning {
12762a6c1abaShenning 	struct addrinfo		 hints, *res0, *res;
12772a6c1abaShenning 	struct node_host	*n, *h = NULL;
12782a6c1abaShenning 	int			 error;
12792a6c1abaShenning 
128094e9410bShenning 	memset(&hints, 0, sizeof(hints));
128194e9410bShenning 	hints.ai_family = PF_UNSPEC;
128294e9410bShenning 	hints.ai_socktype = SOCK_STREAM; /* DUMMY */
12832a6c1abaShenning 	error = getaddrinfo(s, NULL, &hints, &res0);
12842a6c1abaShenning 	if (error)
12852a6c1abaShenning 		return (h);
12862a6c1abaShenning 
128794e9410bShenning 	for (res = res0; res; res = res->ai_next) {
128894e9410bShenning 		if (res->ai_family != AF_INET &&
128994e9410bShenning 		    res->ai_family != AF_INET6)
129094e9410bShenning 			continue;
129194e9410bShenning 		n = calloc(1, sizeof(struct node_host));
129294e9410bShenning 		if (n == NULL)
12932a6c1abaShenning 			err(1, "host_dns: calloc");
129494e9410bShenning 		n->ifname = NULL;
129594e9410bShenning 		n->af = res->ai_family;
129694e9410bShenning 		if (res->ai_family == AF_INET) {
129794e9410bShenning 			memcpy(&n->addr.v.a.addr,
12982a6c1abaShenning 			    &((struct sockaddr_in *)
12992a6c1abaShenning 			    res->ai_addr)->sin_addr.s_addr,
130094e9410bShenning 			    sizeof(struct in_addr));
130194e9410bShenning 			set_ipmask(n, v4mask);
130294e9410bShenning 		} else {
130394e9410bShenning 			memcpy(&n->addr.v.a.addr,
13042a6c1abaShenning 			    &((struct sockaddr_in6 *)
13052a6c1abaShenning 			    res->ai_addr)->sin6_addr.s6_addr,
130694e9410bShenning 			    sizeof(struct in6_addr));
130794e9410bShenning 			n->ifindex =
13082a6c1abaShenning 			    ((struct sockaddr_in6 *)
13092a6c1abaShenning 			    res->ai_addr)->sin6_scope_id;
131094e9410bShenning 			set_ipmask(n, v6mask);
131194e9410bShenning 		}
131294e9410bShenning 		n->next = NULL;
131394e9410bShenning 		n->tail = n;
131494e9410bShenning 		if (h == NULL)
131594e9410bShenning 			h = n;
131694e9410bShenning 		else {
131794e9410bShenning 			h->tail->next = n;
131894e9410bShenning 			h->tail = n;
131994e9410bShenning 		}
132094e9410bShenning 	}
132194e9410bShenning 	freeaddrinfo(res0);
132294e9410bShenning 
132394e9410bShenning 	return (h);
132494e9410bShenning }
1325