parse.y revision 1.186
1/*	$OpenBSD: parse.y,v 1.186 2002/11/13 22:44:11 henning Exp $	*/
2
3/*
4 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
5 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27%{
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <sys/ioctl.h>
31#include <net/if.h>
32#include <netinet/in.h>
33#include <netinet/in_systm.h>
34#include <netinet/ip.h>
35#include <netinet/ip_icmp.h>
36#include <netinet/icmp6.h>
37#include <net/pfvar.h>
38#include <arpa/inet.h>
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <ifaddrs.h>
43#include <netdb.h>
44#include <stdarg.h>
45#include <errno.h>
46#include <string.h>
47#include <ctype.h>
48#include <err.h>
49#include <pwd.h>
50#include <grp.h>
51
52#include "pfctl_parser.h"
53
54static struct pfctl *pf = NULL;
55static FILE *fin = NULL;
56static int debug = 0;
57static int lineno = 1;
58static int errors = 0;
59static int rulestate = 0;
60static u_int16_t returnicmpdefault =  (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
61static u_int16_t returnicmp6default = (ICMP6_DST_UNREACH << 8) |
62    ICMP6_DST_UNREACH_NOPORT;
63static int blockpolicy = PFRULE_DROP;
64static int require_order = 1;
65
66enum {
67	PFCTL_STATE_NONE = 0,
68	PFCTL_STATE_OPTION = 1,
69	PFCTL_STATE_SCRUB = 2,
70	PFCTL_STATE_NAT = 3,
71	PFCTL_STATE_FILTER = 4
72};
73
74enum pfctl_iflookup_mode {
75	PFCTL_IFLOOKUP_HOST = 0,
76	PFCTL_IFLOOKUP_NET = 1,
77	PFCTL_IFLOOKUP_BCAST = 2
78};
79
80struct node_if {
81	char			 ifname[IFNAMSIZ];
82	u_int8_t		 not;
83	u_int			 ifa_flags;
84	struct node_if		*next;
85	struct node_if		*tail;
86};
87
88struct node_proto {
89	u_int8_t		 proto;
90	struct node_proto	*next;
91	struct node_proto	*tail;
92};
93
94struct node_host {
95	struct pf_addr_wrap	 addr;
96	struct pf_addr		 mask;
97	struct pf_addr		 bcast;
98	sa_family_t		 af;
99	u_int8_t		 not;
100	u_int8_t		 noroute;
101	u_int32_t		 ifindex;	/* link-local IPv6 addrs */
102	char			*ifname;
103	u_int			 ifa_flags;
104	struct node_host	*next;
105	struct node_host	*tail;
106};
107
108struct node_port {
109	u_int16_t		 port[2];
110	u_int8_t		 op;
111	struct node_port	*next;
112	struct node_port	*tail;
113};
114
115struct node_uid {
116	uid_t			 uid[2];
117	u_int8_t		 op;
118	struct node_uid		*next;
119	struct node_uid		*tail;
120};
121
122struct node_gid {
123	gid_t			 gid[2];
124	u_int8_t		 op;
125	struct node_gid		*next;
126	struct node_gid		*tail;
127};
128
129struct node_icmp {
130	u_int8_t		 code;
131	u_int8_t		 type;
132	u_int8_t		 proto;
133	struct node_icmp	*next;
134	struct node_icmp	*tail;
135};
136
137enum	{ PF_STATE_OPT_MAX=0, PF_STATE_OPT_TIMEOUT=1 };
138struct node_state_opt {
139	int			 type;
140	union {
141		u_int32_t	 max_states;
142		struct {
143			int		number;
144			u_int32_t	seconds;
145		}		 timeout;
146	}			 data;
147	struct node_state_opt	*next;
148	struct node_state_opt	*tail;
149};
150
151struct peer {
152	struct node_host	*host;
153	struct node_port	*port;
154};
155
156int	yyerror(char *, ...);
157int	rule_consistent(struct pf_rule *);
158int	nat_consistent(struct pf_nat *);
159int	rdr_consistent(struct pf_rdr *);
160int	yyparse(void);
161void	set_ipmask(struct node_host *, u_int8_t);
162void	expand_rdr(struct pf_rdr *, struct node_if *, struct node_proto *,
163	    struct node_host *, struct node_host *);
164void	expand_nat(struct pf_nat *, struct node_if *, struct node_proto *,
165	    struct node_host *, struct node_port *,
166	    struct node_host *, struct node_port *);
167void	expand_label_if(const char *, char *, const char *);
168void	expand_label_addr(const char *, char *, u_int8_t, struct node_host *);
169void	expand_label_port(const char *, char *, struct node_port *);
170void	expand_label_proto(const char *, char *, u_int8_t);
171void	expand_label_nr(const char *, char *);
172void	expand_label(char *, const char *, u_int8_t, struct node_host *,
173	    struct node_port *, struct node_host *, struct node_port *,
174	    u_int8_t);
175void	expand_rule(struct pf_rule *, struct node_if *, struct node_proto *,
176	    struct node_host *, struct node_port *, struct node_host *,
177	    struct node_port *, struct node_uid *, struct node_gid *,
178	    struct node_icmp *);
179int	check_rulestate(int);
180int	kw_cmp(const void *, const void *);
181int	lookup(char *);
182int	lgetc(FILE *);
183int	lungetc(int, FILE *);
184int	findeol(void);
185int	yylex(void);
186struct	node_host *host(char *, int);
187int	atoul(char *, u_long *);
188int	getservice(char *);
189
190
191struct sym {
192	struct sym *next;
193	int used;
194	char *nam;
195	char *val;
196};
197struct sym *symhead = NULL;
198
199int	symset(const char *, const char *);
200char *	symget(const char *);
201
202void	ifa_load(void);
203struct	node_host *ifa_exists(char *);
204struct	node_host *ifa_lookup(char *, enum pfctl_iflookup_mode);
205struct	node_host *ifa_pick_ip(struct node_host *, u_int8_t);
206u_int16_t	parseicmpspec(char *, u_int8_t);
207
208typedef struct {
209	union {
210		u_int32_t		number;
211		int			i;
212		char			*string;
213		struct {
214			u_int8_t	b1;
215			u_int8_t	b2;
216			u_int16_t	w;
217			u_int16_t	w2;
218		}			b;
219		struct range {
220			int		a;
221			int		b;
222			int		t;
223		}			range;
224		struct node_if		*interface;
225		struct node_proto	*proto;
226		struct node_icmp	*icmp;
227		struct node_host	*host;
228		struct node_port	*port;
229		struct node_uid		*uid;
230		struct node_gid		*gid;
231		struct node_state_opt	*state_opt;
232		struct peer		peer;
233		struct {
234			struct peer	src, dst;
235		}			fromto;
236		struct {
237			char		*string;
238			struct pf_addr	*addr;
239			u_int8_t	rt;
240			sa_family_t	af;
241		}			route;
242		struct redirection {
243			struct node_host	*address;
244			struct range		 rport;
245		}			*redirection;
246		struct {
247			int			 action;
248			struct node_state_opt	*options;
249		}			keep_state;
250		struct {
251			u_int8_t	log;
252			u_int8_t	quick;
253		}			logquick;
254	} v;
255	int lineno;
256} YYSTYPE;
257
258%}
259
260%token	PASS BLOCK SCRUB RETURN IN OUT LOG LOGALL QUICK ON FROM TO FLAGS
261%token	RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
262%token	ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
263%token	MINTTL ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO REPLYTO NO LABEL
264%token	NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP
265%token	FRAGNORM FRAGDROP FRAGCROP
266%token	SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY
267%token	REQUIREORDER YES
268%token	ANTISPOOF FOR
269%token	<v.string> STRING
270%token	<v.i>	PORTUNARY PORTBINARY
271%type	<v.interface>	interface if_list if_item_not if_item
272%type	<v.number>	number port icmptype icmp6type minttl uid gid maxmss
273%type	<v.number>	tos
274%type	<v.i>	no dir log af nodf allowopts fragment fragcache
275%type	<v.b>	action flag flags blockspec
276%type	<v.range>	dport rport
277%type	<v.proto>	proto proto_list proto_item
278%type	<v.icmp>	icmpspec icmp_list icmp6_list icmp_item icmp6_item
279%type	<v.fromto>	fromto
280%type	<v.peer>	ipportspec
281%type	<v.host>	ipspec xhost host address host_list
282%type	<v.port>	portspec port_list port_item
283%type	<v.uid>		uids uid_list uid_item
284%type	<v.gid>		gids gid_list gid_item
285%type	<v.route>	route
286%type	<v.redirection>	redirection
287%type	<v.string>	label string
288%type	<v.keep_state>	keep
289%type	<v.state_opt>	state_opt_spec state_opt_list state_opt_item
290%type	<v.logquick>	logquick
291%type	<v.interface>	antispoof_ifspc antispoof_iflst
292%%
293
294ruleset		: /* empty */
295		| ruleset '\n'
296		| ruleset option '\n'
297		| ruleset scrubrule '\n'
298		| ruleset natrule '\n'
299		| ruleset binatrule '\n'
300		| ruleset rdrrule '\n'
301		| ruleset pfrule '\n'
302		| ruleset varset '\n'
303		| ruleset antispoof '\n'
304		| ruleset error '\n'		{ errors++; }
305		;
306
307option		: SET OPTIMIZATION STRING		{
308			if (pf->opts & PF_OPT_VERBOSE)
309				printf("set optimization %s\n", $3);
310			if (check_rulestate(PFCTL_STATE_OPTION))
311				YYERROR;
312			if (pfctl_set_optimization(pf, $3) != 0) {
313				yyerror("unknown optimization %s", $3);
314				YYERROR;
315			}
316		}
317		| SET TIMEOUT timeout_spec
318		| SET TIMEOUT '{' timeout_list '}'
319		| SET LIMIT limit_spec
320		| SET LIMIT '{' limit_list '}'
321		| SET LOGINTERFACE STRING		{
322			if (pf->opts & PF_OPT_VERBOSE)
323				printf("set loginterface %s\n", $3);
324			if (check_rulestate(PFCTL_STATE_OPTION))
325				YYERROR;
326			if (pfctl_set_logif(pf, $3) != 0) {
327				yyerror("error setting loginterface %s", $3);
328				YYERROR;
329			}
330		}
331		| SET BLOCKPOLICY DROP	{
332			if (pf->opts & PF_OPT_VERBOSE)
333				printf("set block-policy drop\n");
334			if (check_rulestate(PFCTL_STATE_OPTION))
335				YYERROR;
336			blockpolicy = PFRULE_DROP;
337		}
338		| SET BLOCKPOLICY RETURN {
339			if (pf->opts & PF_OPT_VERBOSE)
340				printf("set block-policy return\n");
341			if (check_rulestate(PFCTL_STATE_OPTION))
342				YYERROR;
343			blockpolicy = PFRULE_RETURN;
344		}
345		| SET REQUIREORDER YES {
346			if (pf->opts & PF_OPT_VERBOSE)
347				printf("set require-order yes\n");
348			require_order = 1;
349		}
350		| SET REQUIREORDER NO {
351			if (pf->opts & PF_OPT_VERBOSE)
352				printf("set require-order no\n");
353			require_order = 0;
354		}
355		;
356
357string		: string STRING				{
358			if (asprintf(&$$, "%s %s", $1, $2) == -1) {
359				yyerror("malloc failed");
360				YYERROR;
361			}
362			free($1);
363			free($2);
364		}
365		| STRING
366		;
367
368varset		: STRING PORTUNARY string		{
369			if (pf->opts & PF_OPT_VERBOSE)
370				printf("%s = %s\n", $1, $3);
371			if (symset($1, $3) == -1) {
372				yyerror("cannot store variable %s", $1);
373				YYERROR;
374			}
375		}
376		;
377
378scrubrule	: SCRUB dir interface af fromto nodf minttl maxmss fragcache
379		{
380			struct pf_rule r;
381
382			if (check_rulestate(PFCTL_STATE_SCRUB))
383				YYERROR;
384
385			memset(&r, 0, sizeof(r));
386
387			r.action = PF_SCRUB;
388			r.direction = $2;
389
390			if ($3) {
391				if ($3->not) {
392					yyerror("scrub rules don't support "
393					    "'! <if>'");
394					YYERROR;
395				}
396			}
397			r.af = $4;
398			if ($6)
399				r.rule_flag |= PFRULE_NODF;
400			if ($7)
401				r.min_ttl = $7;
402			if ($8)
403				r.max_mss = $8;
404			if ($9)
405				r.rule_flag |= $9;
406
407			expand_rule(&r, $3, NULL, $5.src.host, $5.src.port,
408			    $5.dst.host, $5.dst.port, NULL, NULL, NULL);
409		}
410		;
411
412antispoof	: ANTISPOOF logquick antispoof_ifspc af {
413			struct pf_rule r;
414			struct node_host *h = NULL;
415			struct node_if *i, *j;
416
417			if (check_rulestate(PFCTL_STATE_FILTER))
418				YYERROR;
419
420			for (i = $3; i; i = i->next) {
421				memset(&r, 0, sizeof(r));
422
423				r.action = PF_DROP;
424				r.direction = PF_IN;
425				r.log = $2.log;
426				r.quick = $2.quick;
427				r.af = $4;
428
429				j = calloc(1, sizeof(struct node_if));
430				if (j == NULL)
431					errx(1, "antispoof: calloc");
432				strlcpy(j->ifname, i->ifname, IFNAMSIZ);
433				j->not = 1;
434				h = ifa_lookup(j->ifname, PFCTL_IFLOOKUP_NET);
435
436				expand_rule(&r, j, NULL, h, NULL, NULL, NULL,
437				    NULL, NULL, NULL);
438
439				if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
440					memset(&r, 0, sizeof(r));
441
442					r.action = PF_DROP;
443					r.direction = PF_IN;
444					r.log = $2.log;
445					r.quick = $2.quick;
446					r.af = $4;
447
448					h = ifa_lookup(i->ifname,
449					    PFCTL_IFLOOKUP_HOST);
450
451					expand_rule(&r, NULL, NULL, h, NULL,
452					    NULL, NULL, NULL, NULL, NULL);
453				}
454			}
455		}
456		;
457
458antispoof_ifspc	: FOR if_item			{ $$ = $2; }
459		| FOR '{' antispoof_iflst '}'	{ $$ = $3; }
460		;
461
462antispoof_iflst	: if_item			{ $$ = $1; }
463		| antispoof_iflst comma if_item	{
464			$1->tail->next = $3;
465			$1->tail = $3;
466			$$ = $1;
467		}
468		;
469
470pfrule		: action dir logquick interface route af proto fromto
471		  uids gids flags icmpspec tos keep fragment allowopts label
472		{
473			struct pf_rule r;
474			struct node_state_opt *o;
475			struct node_proto *proto;
476
477			if (check_rulestate(PFCTL_STATE_FILTER))
478				YYERROR;
479
480			memset(&r, 0, sizeof(r));
481
482			r.action = $1.b1;
483			switch ($1.b2) {
484			case PFRULE_RETURNRST:
485				r.rule_flag |= PFRULE_RETURNRST;
486				r.return_ttl = $1.w;
487				break;
488			case PFRULE_RETURNICMP:
489				r.rule_flag |= PFRULE_RETURNICMP;
490				r.return_icmp = $1.w;
491				r.return_icmp6 = $1.w2;
492				break;
493			case PFRULE_RETURN:
494				r.rule_flag |= PFRULE_RETURN;
495				r.return_icmp = $1.w;
496				r.return_icmp6 = $1.w2;
497				break;
498			}
499			r.direction = $2;
500			r.log = $3.log;
501			r.quick = $3.quick;
502
503			r.af = $6;
504			r.flags = $11.b1;
505			r.flagset = $11.b2;
506
507			if ($11.b1 || $11.b2) {
508				for (proto = $7; proto != NULL &&
509				    proto->proto != IPPROTO_TCP;
510				    proto = proto->next)
511					;	/* nothing */
512				if (proto == NULL && $7 != NULL) {
513					yyerror("flags only apply to tcp");
514					YYERROR;
515				}
516			}
517
518			r.tos = $13;
519			r.keep_state = $14.action;
520			o = $14.options;
521			while (o) {
522				struct node_state_opt *p = o;
523
524				switch (o->type) {
525				case PF_STATE_OPT_MAX:
526					if (r.max_states) {
527						yyerror("state option 'max' "
528						    "multiple definitions");
529						YYERROR;
530					}
531					r.max_states = o->data.max_states;
532					break;
533				case PF_STATE_OPT_TIMEOUT:
534					if (r.timeout[o->data.timeout.number]) {
535						yyerror("state timeout %s "
536						    "multiple definitions",
537						    pf_timeouts[o->data.
538						    timeout.number].name);
539						YYERROR;
540					}
541					r.timeout[o->data.timeout.number] =
542					    o->data.timeout.seconds;
543				}
544				o = o->next;
545				free(p);
546			}
547
548			if ($15)
549				r.rule_flag |= PFRULE_FRAGMENT;
550			r.allow_opts = $16;
551
552			if ($5.rt) {
553				r.rt = $5.rt;
554				if ($5.string) {
555					strlcpy(r.rt_ifname, $5.string,
556					    IFNAMSIZ);
557					if (ifa_exists(r.rt_ifname) == NULL) {
558						yyerror("unknown interface %s",
559						    r.rt_ifname);
560						YYERROR;
561					}
562					free($5.string);
563				}
564				if ($5.addr) {
565					if (!r.af)
566						r.af = $5.af;
567					else if (r.af != $5.af) {
568						yyerror("address family"
569						    " mismatch");
570						YYERROR;
571					}
572					memcpy(&r.rt_addr, $5.addr,
573					    sizeof(r.rt_addr));
574					free($5.addr);
575				}
576			}
577
578			if ($17) {
579				if (strlen($17) >= PF_RULE_LABEL_SIZE) {
580					yyerror("rule label too long (max "
581					    "%d chars)", PF_RULE_LABEL_SIZE-1);
582					YYERROR;
583				}
584				strlcpy(r.label, $17, sizeof(r.label));
585				free($17);
586			}
587
588			expand_rule(&r, $4, $7, $8.src.host, $8.src.port,
589			    $8.dst.host, $8.dst.port, $9, $10, $12);
590		}
591		;
592
593action		: PASS			{ $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
594		| BLOCK blockspec	{ $$ = $2; $$.b1 = PF_DROP; }
595		;
596
597blockspec	: /* empty */		{
598			$$.b2 = blockpolicy;
599			$$.w = returnicmpdefault;
600			$$.w2 = returnicmp6default;
601		}
602		| DROP			{
603			$$.b2 = PFRULE_DROP;
604			$$.w = 0;
605			$$.w2 = 0;
606		}
607		| RETURNRST		{
608			$$.b2 = PFRULE_RETURNRST;
609			$$.w = 0;
610			$$.w2 = 0;
611		}
612		| RETURNRST '(' TTL number ')'	{
613			$$.b2 = PFRULE_RETURNRST;
614			$$.w = $4;
615			$$.w2 = 0;
616		}
617		| RETURNICMP		{
618			$$.b2 = PFRULE_RETURNICMP;
619			$$.w = returnicmpdefault;
620			$$.w2 = returnicmp6default;
621		}
622		| RETURNICMP6		{
623			$$.b2 = PFRULE_RETURNICMP;
624			$$.w = returnicmpdefault;
625			$$.w2 = returnicmp6default;
626		}
627		| RETURNICMP '(' STRING ')'	{
628			$$.b2 = PFRULE_RETURNICMP;
629			if (!($$.w = parseicmpspec($3, AF_INET)))
630				YYERROR;
631			$$.w2 = returnicmp6default;
632		}
633		| RETURNICMP6 '(' STRING ')'	{
634			$$.b2 = PFRULE_RETURNICMP;
635			$$.w = returnicmpdefault;
636			if (!($$.w2 = parseicmpspec($3, AF_INET6)))
637				YYERROR;
638		}
639		| RETURNICMP '(' STRING comma STRING ')' {
640			$$.b2 = PFRULE_RETURNICMP;
641			if (!($$.w = parseicmpspec($3, AF_INET)))
642				YYERROR;
643			if (!($$.w2 = parseicmpspec($5, AF_INET6)));
644		}
645		| RETURN {
646			$$.b2 = PFRULE_RETURN;
647			$$.w = returnicmpdefault;
648			$$.w2 = returnicmp6default;
649		}
650		;
651
652fragcache	: /* empty */		{ $$ = 0; }
653		| fragment FRAGNORM	{ $$ = 0; /* default */ }
654		| fragment FRAGCROP	{ $$ = PFRULE_FRAGCROP; }
655		| fragment FRAGDROP	{ $$ = PFRULE_FRAGDROP; }
656		;
657
658
659dir		: IN				{ $$ = PF_IN; }
660		| OUT				{ $$ = PF_OUT; }
661		;
662
663logquick	: /* empty */			{ $$.log = 0; $$.quick = 0; }
664		| log				{ $$.log = $1; $$.quick = 0; }
665		| QUICK				{ $$.log = 0; $$.quick = 1; }
666		| log QUICK			{ $$.log = $1; $$.quick = 1; }
667		| QUICK log			{ $$.log = $2; $$.quick = 1; }
668		;
669
670log		: LOG				{ $$ = 1; }
671		| LOGALL			{ $$ = 2; }
672		;
673
674interface	: /* empty */			{ $$ = NULL; }
675		| ON if_item_not		{ $$ = $2; }
676		| ON '{' if_list '}'		{ $$ = $3; }
677		;
678
679if_list		: if_item_not			{ $$ = $1; }
680		| if_list comma if_item_not	{
681			$1->tail->next = $3;
682			$1->tail = $3;
683			$$ = $1;
684		}
685		;
686
687if_item_not	: '!' if_item			{ $$ = $2; $$->not = 1; }
688		| if_item			{ $$ = $1; }
689
690if_item		: STRING			{
691			struct node_host *n;
692
693			if ((n = ifa_exists($1)) == NULL) {
694				yyerror("unknown interface %s", $1);
695				YYERROR;
696			}
697			$$ = malloc(sizeof(struct node_if));
698			if ($$ == NULL)
699				err(1, "if_item: malloc");
700			strlcpy($$->ifname, $1, IFNAMSIZ);
701			$$->ifa_flags = n->ifa_flags;
702			$$->not = 0;
703			$$->next = NULL;
704			$$->tail = $$;
705		}
706		;
707
708af		: /* empty */			{ $$ = 0; }
709		| INET				{ $$ = AF_INET; }
710		| INET6				{ $$ = AF_INET6; }
711
712proto		: /* empty */			{ $$ = NULL; }
713		| PROTO proto_item		{ $$ = $2; }
714		| PROTO '{' proto_list '}'	{ $$ = $3; }
715		;
716
717proto_list	: proto_item			{ $$ = $1; }
718		| proto_list comma proto_item	{
719			$1->tail->next = $3;
720			$1->tail = $3;
721			$$ = $1;
722		}
723		;
724
725proto_item	: STRING			{
726			u_int8_t pr;
727			u_long ulval;
728
729			if (atoul($1, &ulval) == 0) {
730				if (ulval > 255) {
731					yyerror("protocol outside range");
732					YYERROR;
733				}
734				pr = (u_int8_t)ulval;
735			} else {
736				struct protoent *p;
737
738				p = getprotobyname($1);
739				if (p == NULL) {
740					yyerror("unknown protocol %s", $1);
741					YYERROR;
742				}
743				pr = p->p_proto;
744			}
745			if (pr == 0) {
746				yyerror("proto 0 cannot be used");
747				YYERROR;
748			}
749			$$ = malloc(sizeof(struct node_proto));
750			if ($$ == NULL)
751				err(1, "proto_item: malloc");
752			$$->proto = pr;
753			$$->next = NULL;
754			$$->tail = $$;
755		}
756		;
757
758fromto		: ALL				{
759			$$.src.host = NULL;
760			$$.src.port = NULL;
761			$$.dst.host = NULL;
762			$$.dst.port = NULL;
763		}
764		| FROM ipportspec TO ipportspec	{
765			$$.src = $2;
766			$$.dst = $4;
767		}
768		;
769
770ipportspec	: ipspec			{ $$.host = $1; $$.port = NULL; }
771		| ipspec PORT portspec		{
772			$$.host = $1;
773			$$.port = $3;
774		}
775		;
776
777ipspec		: ANY				{ $$ = NULL; }
778		| xhost				{ $$ = $1; }
779		| '{' host_list '}'		{ $$ = $2; }
780		;
781
782host_list	: xhost				{ $$ = $1; }
783		| host_list comma xhost		{
784			/* $3 may be a list, so use its tail pointer */
785			$1->tail->next = $3->tail;
786			$1->tail = $3->tail;
787			$$ = $1;
788		}
789		;
790
791xhost		: '!' host			{
792			struct node_host *h;
793			for (h = $2; h; h = h->next)
794				h->not = 1;
795			$$ = $2;
796		}
797		| host				{ $$ = $1; }
798		| NOROUTE			{
799			$$ = calloc(1, sizeof(struct node_host));
800			if ($$ == NULL)
801				err(1, "xhost: calloc");
802			$$->noroute = 1;
803			$$->next = NULL;
804			$$->tail = $$;
805		}
806		;
807
808host		: address
809		| STRING '/' number		{ $$ = host($1, $3); }
810		;
811
812number		: STRING			{
813			u_long ulval;
814
815			if (atoul($1, &ulval) == -1) {
816				yyerror("%s is not a number", $1);
817				YYERROR;
818			} else
819				$$ = ulval;
820		}
821		;
822
823address		: '(' STRING ')'		{
824			$$ = calloc(1, sizeof(struct node_host));
825			if ($$ == NULL)
826				err(1, "address: calloc");
827			$$->af = 0;
828			set_ipmask($$, 128);
829			$$->addr.addr_dyn = (struct pf_addr_dyn *)1;
830			strncpy($$->addr.addr.pfa.ifname, $2,
831			    sizeof($$->addr.addr.pfa.ifname));
832			$$->next = NULL;
833			$$->tail = $$;
834		}
835		| STRING			{ $$ = host($1, -1); }
836		;
837
838portspec	: port_item			{ $$ = $1; }
839		| '{' port_list '}'		{ $$ = $2; }
840		;
841
842port_list	: port_item			{ $$ = $1; }
843		| port_list comma port_item	{
844			$1->tail->next = $3;
845			$1->tail = $3;
846			$$ = $1;
847		}
848		;
849
850port_item	: port				{
851			$$ = malloc(sizeof(struct node_port));
852			if ($$ == NULL)
853				err(1, "port_item: malloc");
854			$$->port[0] = $1;
855			$$->port[1] = $1;
856			$$->op = PF_OP_EQ;
857			$$->next = NULL;
858			$$->tail = $$;
859		}
860		| PORTUNARY port		{
861			$$ = malloc(sizeof(struct node_port));
862			if ($$ == NULL)
863				err(1, "port_item: malloc");
864			$$->port[0] = $2;
865			$$->port[1] = $2;
866			$$->op = $1;
867			$$->next = NULL;
868			$$->tail = $$;
869		}
870		| port PORTBINARY port		{
871			$$ = malloc(sizeof(struct node_port));
872			if ($$ == NULL)
873				err(1, "port_item: malloc");
874			$$->port[0] = $1;
875			$$->port[1] = $3;
876			$$->op = $2;
877			$$->next = NULL;
878			$$->tail = $$;
879		}
880		;
881
882port		: STRING			{
883			struct servent *s = NULL;
884			u_long ulval;
885
886			if (atoul($1, &ulval) == 0) {
887				if (ulval > 65535) {
888					yyerror("illegal port value %d", ulval);
889					YYERROR;
890				}
891				$$ = htons(ulval);
892			} else {
893				s = getservbyname($1, "tcp");
894				if (s == NULL)
895					s = getservbyname($1, "udp");
896				if (s == NULL) {
897					yyerror("unknown port %s", $1);
898					YYERROR;
899				}
900				$$ = s->s_port;
901			}
902		}
903		;
904
905uids		: /* empty */			{ $$ = NULL; }
906		| USER uid_item			{ $$ = $2; }
907		| USER '{' uid_list '}'		{ $$ = $3; }
908		;
909
910uid_list	: uid_item			{ $$ = $1; }
911		| uid_list comma uid_item	{
912			$1->tail->next = $3;
913			$1->tail = $3;
914			$$ = $1;
915		}
916		;
917
918uid_item	: uid				{
919			$$ = malloc(sizeof(struct node_uid));
920			if ($$ == NULL)
921				err(1, "uid_item: malloc");
922			$$->uid[0] = $1;
923			$$->uid[1] = $1;
924			$$->op = PF_OP_EQ;
925			$$->next = NULL;
926			$$->tail = $$;
927		}
928		| PORTUNARY uid			{
929			if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
930				yyerror("user unknown requires operator = or !=");
931				YYERROR;
932			}
933			$$ = malloc(sizeof(struct node_uid));
934			if ($$ == NULL)
935				err(1, "uid_item: malloc");
936			$$->uid[0] = $2;
937			$$->uid[1] = $2;
938			$$->op = $1;
939			$$->next = NULL;
940			$$->tail = $$;
941		}
942		| uid PORTBINARY uid		{
943			if ($1 == UID_MAX || $3 == UID_MAX) {
944				yyerror("user unknown requires operator = or !=");
945				YYERROR;
946			}
947			$$ = malloc(sizeof(struct node_uid));
948			if ($$ == NULL)
949				err(1, "uid_item: malloc");
950			$$->uid[0] = $1;
951			$$->uid[1] = $3;
952			$$->op = $2;
953			$$->next = NULL;
954			$$->tail = $$;
955		}
956		;
957
958uid		: STRING			{
959			u_long ulval;
960
961			if (atoul($1, &ulval) == -1) {
962				if (!strcmp($1, "unknown"))
963					$$ = UID_MAX;
964				else {
965					struct passwd *pw;
966
967					if ((pw = getpwnam($1)) == NULL) {
968						yyerror("unknown user %s", $1);
969						YYERROR;
970					}
971					$$ = pw->pw_uid;
972				}
973			} else {
974				if (ulval >= UID_MAX) {
975					yyerror("illegal uid value %lu", ulval);
976					YYERROR;
977				}
978				$$ = ulval;
979			}
980		}
981		;
982
983gids		: /* empty */			{ $$ = NULL; }
984		| GROUP gid_item		{ $$ = $2; }
985		| GROUP '{' gid_list '}'	{ $$ = $3; }
986		;
987
988gid_list	: gid_item			{ $$ = $1; }
989		| gid_list comma gid_item	{
990			$1->tail->next = $3;
991			$1->tail = $3;
992			$$ = $1;
993		}
994		;
995
996gid_item	: gid				{
997			$$ = malloc(sizeof(struct node_gid));
998			if ($$ == NULL)
999				err(1, "gid_item: malloc");
1000			$$->gid[0] = $1;
1001			$$->gid[1] = $1;
1002			$$->op = PF_OP_EQ;
1003			$$->next = NULL;
1004			$$->tail = $$;
1005		}
1006		| PORTUNARY gid			{
1007			if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
1008				yyerror("group unknown requires operator = or !=");
1009				YYERROR;
1010			}
1011			$$ = malloc(sizeof(struct node_gid));
1012			if ($$ == NULL)
1013				err(1, "gid_item: malloc");
1014			$$->gid[0] = $2;
1015			$$->gid[1] = $2;
1016			$$->op = $1;
1017			$$->next = NULL;
1018			$$->tail = $$;
1019		}
1020		| gid PORTBINARY gid		{
1021			if ($1 == GID_MAX || $3 == GID_MAX) {
1022				yyerror("group unknown requires operator = or !=");
1023				YYERROR;
1024			}
1025			$$ = malloc(sizeof(struct node_gid));
1026			if ($$ == NULL)
1027				err(1, "gid_item: malloc");
1028			$$->gid[0] = $1;
1029			$$->gid[1] = $3;
1030			$$->op = $2;
1031			$$->next = NULL;
1032			$$->tail = $$;
1033		}
1034		;
1035
1036gid		: STRING			{
1037			u_long ulval;
1038
1039			if (atoul($1, &ulval) == -1) {
1040				if (!strcmp($1, "unknown"))
1041					$$ = GID_MAX;
1042				else {
1043					struct group *grp;
1044
1045					if ((grp = getgrnam($1)) == NULL) {
1046						yyerror("unknown group %s", $1);
1047						YYERROR;
1048					}
1049					$$ = grp->gr_gid;
1050				}
1051			} else {
1052				if (ulval >= GID_MAX) {
1053					yyerror("illegal gid value %lu", ulval);
1054					YYERROR;
1055				}
1056				$$ = ulval;
1057			}
1058		}
1059		;
1060
1061flag		: STRING			{
1062			int f;
1063
1064			if ((f = parse_flags($1)) < 0) {
1065				yyerror("bad flags %s", $1);
1066				YYERROR;
1067			}
1068			$$.b1 = f;
1069		}
1070		;
1071
1072flags		: /* empty */			{ $$.b1 = 0; $$.b2 = 0; }
1073		| FLAGS flag "/" flag		{ $$.b1 = $2.b1; $$.b2 = $4.b1; }
1074		| FLAGS "/" flag		{ $$.b1 = 0; $$.b2 = $3.b1; }
1075		;
1076
1077icmpspec	: /* empty */			{ $$ = NULL; }
1078		| ICMPTYPE icmp_item		{ $$ = $2; }
1079		| ICMPTYPE '{' icmp_list '}'	{ $$ = $3; }
1080		| ICMP6TYPE icmp6_item		{ $$ = $2; }
1081		| ICMP6TYPE '{' icmp6_list '}'	{ $$ = $3; }
1082		;
1083
1084icmp_list	: icmp_item			{ $$ = $1; }
1085		| icmp_list comma icmp_item	{
1086			$1->tail->next = $3;
1087			$1->tail = $3;
1088			$$ = $1;
1089		}
1090		;
1091
1092icmp6_list	: icmp6_item			{ $$ = $1; }
1093		| icmp6_list comma icmp6_item	{
1094			$1->tail->next = $3;
1095			$1->tail = $3;
1096			$$ = $1;
1097		}
1098		;
1099
1100icmp_item	: icmptype		{
1101			$$ = malloc(sizeof(struct node_icmp));
1102			if ($$ == NULL)
1103				err(1, "icmp_item: malloc");
1104			$$->type = $1;
1105			$$->code = 0;
1106			$$->proto = IPPROTO_ICMP;
1107			$$->next = NULL;
1108			$$->tail = $$;
1109		}
1110		| icmptype CODE STRING	{
1111			const struct icmpcodeent *p;
1112			u_long ulval;
1113
1114			if (atoul($3, &ulval) == 0) {
1115				if (ulval > 255) {
1116					yyerror("illegal icmp-code %d", ulval);
1117					YYERROR;
1118				}
1119			} else {
1120				if ((p = geticmpcodebyname($1, $3,
1121				    AF_INET)) == NULL) {
1122					yyerror("unknown icmp-code %s", $3);
1123					YYERROR;
1124				}
1125				ulval = p->code;
1126			}
1127			$$ = malloc(sizeof(struct node_icmp));
1128			if ($$ == NULL)
1129				err(1, "icmp_item: malloc");
1130			$$->type = $1;
1131			$$->code = ulval + 1;
1132			$$->proto = IPPROTO_ICMP;
1133			$$->next = NULL;
1134			$$->tail = $$;
1135		}
1136		;
1137
1138icmp6_item	: icmp6type		{
1139			$$ = malloc(sizeof(struct node_icmp));
1140			if ($$ == NULL)
1141				err(1, "icmp_item: malloc");
1142			$$->type = $1;
1143			$$->code = 0;
1144			$$->proto = IPPROTO_ICMPV6;
1145			$$->next = NULL;
1146			$$->tail = $$;
1147		}
1148		| icmp6type CODE STRING	{
1149			const struct icmpcodeent *p;
1150			u_long ulval;
1151
1152			if (atoul($3, &ulval) == 0) {
1153				if (ulval > 255) {
1154					yyerror("illegal icmp6-code %ld", ulval);
1155					YYERROR;
1156				}
1157			} else {
1158				if ((p = geticmpcodebyname($1, $3,
1159				    AF_INET6)) == NULL) {
1160					yyerror("unknown icmp6-code %s", $3);
1161					YYERROR;
1162				}
1163				ulval = p->code;
1164			}
1165			$$ = malloc(sizeof(struct node_icmp));
1166			if ($$ == NULL)
1167				err(1, "icmp_item: malloc");
1168			$$->type = $1;
1169			$$->code = ulval + 1;
1170			$$->proto = IPPROTO_ICMPV6;
1171			$$->next = NULL;
1172			$$->tail = $$;
1173		}
1174		;
1175
1176icmptype	: STRING			{
1177			const struct icmptypeent *p;
1178			u_long ulval;
1179
1180			if (atoul($1, &ulval) == 0) {
1181				if (ulval > 255) {
1182					yyerror("illegal icmp-type %d", ulval);
1183					YYERROR;
1184				}
1185				$$ = ulval + 1;
1186			} else {
1187				if ((p = geticmptypebyname($1, AF_INET)) == NULL) {
1188					yyerror("unknown icmp-type %s", $1);
1189					YYERROR;
1190				}
1191				$$ = p->type + 1;
1192			}
1193		}
1194		;
1195
1196icmp6type	: STRING			{
1197			const struct icmptypeent *p;
1198			u_long ulval;
1199
1200			if (atoul($1, &ulval) == 0) {
1201				if (ulval > 255) {
1202					yyerror("illegal icmp6-type %d", ulval);
1203					YYERROR;
1204				}
1205				$$ = ulval + 1;
1206			} else {
1207				if ((p = geticmptypebyname($1, AF_INET6)) == NULL) {
1208					yyerror("unknown ipv6-icmp-type %s", $1);
1209					YYERROR;
1210				}
1211				$$ = p->type + 1;
1212			}
1213		}
1214		;
1215
1216tos		: /* empty */			{ $$ = 0; }
1217		| TOS STRING			{
1218			if (!strcmp($2, "lowdelay"))
1219				$$ = IPTOS_LOWDELAY;
1220			else if (!strcmp($2, "throughput"))
1221				$$ = IPTOS_THROUGHPUT;
1222			else if (!strcmp($2, "reliability"))
1223				$$ = IPTOS_RELIABILITY;
1224			else if ($2[0] == '0' && $2[1] == 'x')
1225				$$ = strtoul($2, NULL, 16);
1226			else
1227				$$ = strtoul($2, NULL, 10);
1228			if (!$$ || $$ > 255) {
1229				yyerror("illegal tos value %s", $2);
1230				YYERROR;
1231			}
1232		}
1233		;
1234
1235keep		: /* empty */			{
1236			$$.action = 0;
1237			$$.options = NULL;
1238		}
1239		| KEEP STATE state_opt_spec	{
1240			$$.action = PF_STATE_NORMAL;
1241			$$.options = $3;
1242		}
1243		| MODULATE STATE state_opt_spec	{
1244			$$.action = PF_STATE_MODULATE;
1245			$$.options = $3;
1246		}
1247		;
1248
1249state_opt_spec	: /* empty */			{ $$ = NULL; }
1250		| '(' state_opt_list ')'	{ $$ = $2; }
1251		;
1252
1253state_opt_list	: state_opt_item		{ $$ = $1; }
1254		| state_opt_list comma state_opt_item {
1255			$1->tail->next = $3;
1256			$1->tail = $3;
1257			$$ = $1;
1258		}
1259		;
1260
1261state_opt_item	: MAXIMUM number		{
1262			if ($2 <= 0) {
1263				yyerror("illegal states max value %d", $2);
1264				YYERROR;
1265			}
1266			$$ = calloc(1, sizeof(struct node_state_opt));
1267			if ($$ == NULL)
1268				err(1, "state_opt_item: calloc");
1269			$$->type = PF_STATE_OPT_MAX;
1270			$$->data.max_states = $2;
1271			$$->next = NULL;
1272			$$->tail = $$;
1273		}
1274		| STRING number			{
1275			int i;
1276
1277			for (i = 0; pf_timeouts[i].name &&
1278			    strcmp(pf_timeouts[i].name, $1); ++i)
1279				;	/* nothing */
1280			if (!pf_timeouts[i].name) {
1281				yyerror("illegal timeout name %s", $1);
1282				YYERROR;
1283			}
1284			if (strchr(pf_timeouts[i].name, '.') == NULL) {
1285				yyerror("illegal state timeout %s", $1);
1286				YYERROR;
1287			}
1288			$$ = calloc(1, sizeof(struct node_state_opt));
1289			if ($$ == NULL)
1290				err(1, "state_opt_item: calloc");
1291			$$->type = PF_STATE_OPT_TIMEOUT;
1292			$$->data.timeout.number = pf_timeouts[i].timeout;
1293			$$->data.timeout.seconds = $2;
1294			$$->next = NULL;
1295			$$->tail = $$;
1296		}
1297		;
1298
1299fragment	: /* empty */			{ $$ = 0; }
1300		| FRAGMENT			{ $$ = 1; }
1301
1302minttl		: /* empty */			{ $$ = 0; }
1303		| MINTTL number			{
1304			if ($2 > 255) {
1305				yyerror("illegal min-ttl value %d", $2);
1306				YYERROR;
1307			}
1308			$$ = $2;
1309		}
1310		;
1311
1312nodf		: /* empty */			{ $$ = 0; }
1313		| NODF				{ $$ = 1; }
1314		;
1315
1316maxmss		: /* empty */			{ $$ = 0; }
1317		| MAXMSS number			{ $$ = $2; }
1318		;
1319
1320allowopts	: /* empty */			{ $$ = 0; }
1321		| ALLOWOPTS			{ $$ = 1; }
1322
1323label		: /* empty */			{ $$ = NULL; }
1324		| LABEL STRING			{
1325			if (($$ = strdup($2)) == NULL) {
1326				yyerror("rule label strdup() failed");
1327				YYERROR;
1328			}
1329		}
1330		;
1331
1332no		: /* empty */			{ $$ = 0; }
1333		| NO				{ $$ = 1; }
1334		;
1335
1336rport		: STRING			{
1337			char *p = strchr($1, ':');
1338
1339			if (p == NULL) {
1340				if (($$.a = getservice($1)) == -1)
1341					YYERROR;
1342				$$.b = $$.t = 0;
1343			} else if (!strcmp(p+1, "*")) {
1344				*p = 0;
1345				if (($$.a = getservice($1)) == -1)
1346					YYERROR;
1347				$$.b = 0;
1348				$$.t = PF_RPORT_RANGE;
1349			} else {
1350				*p++ = 0;
1351				if (($$.a = getservice($1)) == -1 ||
1352				    ($$.b = getservice(p)) == -1)
1353					YYERROR;
1354				$$.t = PF_RPORT_RANGE;
1355			}
1356		}
1357		;
1358
1359redirection	: /* empty */			{ $$ = NULL; }
1360		| ARROW host			{
1361			$$ = malloc(sizeof(struct redirection));
1362			if ($$ == NULL)
1363				err(1, "redirection: malloc");
1364			$$->address = $2;
1365			$$->rport.a = $$->rport.b = $$->rport.t = 0;
1366		}
1367		| ARROW host PORT rport	{
1368			$$ = malloc(sizeof(struct redirection));
1369			if ($$ == NULL)
1370				err(1, "redirection: malloc");
1371			$$->address = $2;
1372			$$->rport = $4;
1373		}
1374		;
1375
1376natrule		: no NAT interface af proto fromto redirection
1377		{
1378			struct pf_nat nat;
1379
1380			if (check_rulestate(PFCTL_STATE_NAT))
1381				YYERROR;
1382
1383			memset(&nat, 0, sizeof(nat));
1384
1385			nat.no = $1;
1386			nat.af = $4;
1387
1388			if (!nat.af) {
1389				if ($6.src.host && $6.src.host->af
1390				    && !$6.src.host->ifindex)
1391					nat.af = $6.src.host->af;
1392				else if ($6.dst.host && $6.dst.host->af
1393				    && !$6.dst.host->ifindex)
1394					nat.af = $6.dst.host->af;
1395			}
1396
1397			if (nat.no) {
1398				if ($7 != NULL) {
1399					yyerror("'no nat' rule does not need "
1400					    "'->'");
1401					YYERROR;
1402				}
1403			} else {
1404				struct node_host *n;
1405
1406				if ($7 == NULL || $7->address == NULL) {
1407					yyerror("'nat' rule requires '-> "
1408					    "address'");
1409					YYERROR;
1410				}
1411				if (!nat.af && !$7->address->ifindex)
1412					nat.af = $7->address->af;
1413				n = ifa_pick_ip($7->address, nat.af);
1414				if (n == NULL)
1415					YYERROR;
1416				if (!nat.af)
1417					nat.af = n->af;
1418				memcpy(&nat.raddr, &n->addr,
1419				    sizeof(nat.raddr));
1420				nat.proxy_port[0] = ntohs($7->rport.a);
1421				nat.proxy_port[1] = ntohs($7->rport.b);
1422				if (!nat.proxy_port[0] && !nat.proxy_port[1]) {
1423					nat.proxy_port[0] =
1424					    PF_NAT_PROXY_PORT_LOW;
1425					nat.proxy_port[1] =
1426					    PF_NAT_PROXY_PORT_HIGH;
1427				} else if (!nat.proxy_port[1])
1428					nat.proxy_port[1] = nat.proxy_port[0];
1429				free($7->address);
1430				free($7);
1431			}
1432
1433			expand_nat(&nat, $3, $5, $6.src.host, $6.src.port,
1434			    $6.dst.host, $6.dst.port);
1435		}
1436		;
1437
1438binatrule	: no BINAT interface af proto FROM host TO ipspec redirection
1439		{
1440			struct pf_binat binat;
1441
1442			if (check_rulestate(PFCTL_STATE_NAT))
1443				YYERROR;
1444
1445			memset(&binat, 0, sizeof(binat));
1446
1447			binat.no = $1;
1448			if ($3 != NULL) {
1449				memcpy(binat.ifname, $3->ifname,
1450				    sizeof(binat.ifname));
1451				free($3);
1452			}
1453			binat.af = $4;
1454			if ($5 != NULL) {
1455				binat.proto = $5->proto;
1456				free($5);
1457			}
1458			if ($7 != NULL && $9 != NULL && $7->af != $9->af) {
1459				yyerror("binat ip versions must match");
1460				YYERROR;
1461			}
1462			if ($7 != NULL) {
1463				if ($7->next) {
1464					yyerror("multiple binat ip addresses");
1465					YYERROR;
1466				}
1467				if ($7->addr.addr_dyn != NULL) {
1468					if (!binat.af) {
1469						yyerror("address family (inet/"
1470						    "inet6) undefined");
1471						YYERROR;
1472					}
1473					$7->af = binat.af;
1474				}
1475				if (binat.af && $7->af != binat.af) {
1476					yyerror("binat ip versions must match");
1477					YYERROR;
1478				}
1479				binat.af = $7->af;
1480				memcpy(&binat.saddr.addr, &$7->addr.addr,
1481				    sizeof(binat.saddr.addr));
1482				memcpy(&binat.smask, &$7->mask,
1483				    sizeof(binat.smask));
1484				free($7);
1485			}
1486			if ($9 != NULL) {
1487				if ($9->next) {
1488					yyerror("multiple binat ip addresses");
1489					YYERROR;
1490				}
1491				if ($9->addr.addr_dyn != NULL) {
1492					if (!binat.af) {
1493						yyerror("address family (inet/"
1494						    "inet6) undefined");
1495						YYERROR;
1496					}
1497					$9->af = binat.af;
1498				}
1499				if (binat.af && $9->af != binat.af) {
1500					yyerror("binat ip versions must match");
1501					YYERROR;
1502				}
1503				binat.af = $9->af;
1504				memcpy(&binat.daddr.addr, &$9->addr.addr,
1505				    sizeof(binat.daddr.addr));
1506				memcpy(&binat.dmask, &$9->mask,
1507				    sizeof(binat.dmask));
1508				binat.dnot  = $9->not;
1509				free($9);
1510			}
1511
1512			if (binat.no) {
1513				if ($10 != NULL) {
1514					yyerror("'no binat' rule does not need"
1515					    " '->'");
1516					YYERROR;
1517				}
1518			} else {
1519				struct node_host *n;
1520
1521				if ($10 == NULL || $10->address == NULL) {
1522					yyerror("'binat' rule requires"
1523					    " '-> address'");
1524					YYERROR;
1525				}
1526				n = ifa_pick_ip($10->address, binat.af);
1527				if (n == NULL)
1528					YYERROR;
1529				if (n->addr.addr_dyn != NULL) {
1530					if (!binat.af) {
1531						yyerror("address family (inet/"
1532						    "inet6) undefined");
1533						YYERROR;
1534					}
1535					n->af = binat.af;
1536				}
1537				if (binat.af && n->af != binat.af) {
1538					yyerror("binat ip versions must match");
1539					YYERROR;
1540				}
1541				binat.af = n->af;
1542				memcpy(&binat.raddr.addr, &n->addr.addr,
1543				    sizeof(binat.raddr.addr));
1544				memcpy(&binat.rmask, &n->mask,
1545				    sizeof(binat.rmask));
1546				if (PF_ANEQ(&binat.smask, &binat.rmask, binat.af)) {
1547					yyerror("'binat' source mask and "
1548					    "redirect mask must be the same");
1549					YYERROR;
1550				}
1551				free($10->address);
1552				free($10);
1553			}
1554
1555			pfctl_add_binat(pf, &binat);
1556		}
1557
1558rdrrule		: no RDR interface af proto FROM ipspec TO ipspec dport redirection
1559		{
1560			struct pf_rdr rdr;
1561
1562			if (check_rulestate(PFCTL_STATE_NAT))
1563				YYERROR;
1564
1565			memset(&rdr, 0, sizeof(rdr));
1566
1567			rdr.no = $1;
1568			rdr.af = $4;
1569			if ($7 != NULL) {
1570				memcpy(&rdr.saddr, &$7->addr,
1571				    sizeof(rdr.saddr));
1572				memcpy(&rdr.smask, &$7->mask,
1573				    sizeof(rdr.smask));
1574				rdr.snot  = $7->not;
1575				if (!rdr.af && !$7->ifindex)
1576					rdr.af = $7->af;
1577			}
1578			if ($9 != NULL) {
1579				memcpy(&rdr.daddr, &$9->addr,
1580				    sizeof(rdr.daddr));
1581				memcpy(&rdr.dmask, &$9->mask,
1582				    sizeof(rdr.dmask));
1583				rdr.dnot  = $9->not;
1584				if (!rdr.af && !$9->ifindex)
1585					rdr.af = $9->af;
1586			}
1587
1588			rdr.dport  = $10.a;
1589			rdr.dport2 = $10.b;
1590			rdr.opts  |= $10.t;
1591
1592			if (rdr.no) {
1593				if ($11 != NULL) {
1594					yyerror("'no rdr' rule does not need '->'");
1595					YYERROR;
1596				}
1597			} else {
1598				struct node_host *n;
1599
1600				if ($11 == NULL || $11->address == NULL) {
1601					yyerror("'rdr' rule requires '-> "
1602					    "address'");
1603					YYERROR;
1604				}
1605				if (!rdr.af && !$11->address->ifindex)
1606					rdr.af = $11->address->af;
1607				n = ifa_pick_ip($11->address, rdr.af);
1608				if (n == NULL)
1609					YYERROR;
1610				if (!rdr.af)
1611					rdr.af = n->af;
1612				memcpy(&rdr.raddr, &n->addr,
1613				    sizeof(rdr.raddr));
1614				free($11->address);
1615				rdr.rport  = $11->rport.a;
1616				rdr.opts  |= $11->rport.t;
1617				free($11);
1618			}
1619
1620			expand_rdr(&rdr, $3, $5, $7, $9);
1621		}
1622		;
1623
1624dport		: /* empty */			{
1625			$$.a = $$.b = $$.t = 0;
1626		}
1627		| PORT STRING			{
1628			char *p = strchr($2, ':');
1629
1630			if (p == NULL) {
1631				if (($$.a = getservice($2)) == -1)
1632					YYERROR;
1633				$$.b = $$.t = 0;
1634			} else {
1635				*p++ = 0;
1636				if (($$.a = getservice($2)) == -1 ||
1637				    ($$.b = getservice(p)) == -1)
1638					YYERROR;
1639				$$.t = PF_DPORT_RANGE;
1640			}
1641		}
1642		;
1643
1644route		: /* empty */			{
1645			$$.string = NULL;
1646			$$.rt = 0;
1647			$$.addr = NULL;
1648			$$.af = 0;
1649		}
1650		| FASTROUTE {
1651			$$.string = NULL;
1652			$$.rt = PF_FASTROUTE;
1653			$$.addr = NULL;
1654		}
1655		| ROUTETO '(' STRING address ')' {
1656			if (($$.string = strdup($3)) == NULL) {
1657				yyerror("routeto: strdup");
1658				YYERROR;
1659			}
1660			$$.rt = PF_ROUTETO;
1661			if ($4->addr.addr_dyn != NULL) {
1662				yyerror("route-to does not support"
1663				    " dynamic addresses");
1664				YYERROR;
1665			}
1666			if ($4->next) {
1667				yyerror("multiple route-to ip addresses");
1668				YYERROR;
1669			}
1670			$$.addr = &$4->addr.addr;
1671			$$.af = $4->af;
1672		}
1673		| ROUTETO STRING {
1674			if (($$.string = strdup($2)) == NULL) {
1675				yyerror("routeto: strdup");
1676				YYERROR;
1677			}
1678			$$.rt = PF_ROUTETO;
1679			$$.addr = NULL;
1680		}
1681		| REPLYTO '(' STRING address ')' {
1682			if (($$.string = strdup($3)) == NULL) {
1683				yyerror("reply-to: strdup");
1684				YYERROR;
1685			}
1686			$$.rt = PF_REPLYTO;
1687			if ($4->addr.addr_dyn != NULL) {
1688				yyerror("reply-to does not support"
1689				    " dynamic addresses");
1690				YYERROR;
1691			}
1692			if ($4->next) {
1693				yyerror("multiple reply-to ip addresses");
1694				YYERROR;
1695			}
1696			$$.addr = &$4->addr.addr;
1697			$$.af = $4->af;
1698		}
1699		| REPLYTO STRING {
1700			if (($$.string = strdup($2)) == NULL) {
1701				yyerror("reply-to: strdup");
1702				YYERROR;
1703			}
1704			$$.rt = PF_REPLYTO;
1705			$$.addr = NULL;
1706		}
1707		| DUPTO '(' STRING address ')' {
1708			if (($$.string = strdup($3)) == NULL) {
1709				yyerror("dupto: strdup");
1710				YYERROR;
1711			}
1712			$$.rt = PF_DUPTO;
1713			if ($4->addr.addr_dyn != NULL) {
1714				yyerror("dup-to does not support"
1715				    " dynamic addresses");
1716				YYERROR;
1717			}
1718			if ($4->next) {
1719				yyerror("multiple dup-to ip addresses");
1720				YYERROR;
1721			}
1722			$$.addr = &$4->addr.addr;
1723			$$.af = $4->af;
1724		}
1725		| DUPTO STRING {
1726			if (($$.string = strdup($2)) == NULL) {
1727				yyerror("dupto: strdup");
1728				YYERROR;
1729			}
1730			$$.rt = PF_DUPTO;
1731			$$.addr = NULL;
1732		}
1733		;
1734
1735timeout_spec	: STRING number
1736		{
1737			if (pf->opts & PF_OPT_VERBOSE)
1738				printf("set timeout %s %us\n", $1, $2);
1739			if (check_rulestate(PFCTL_STATE_OPTION))
1740				YYERROR;
1741			if (pfctl_set_timeout(pf, $1, $2) != 0) {
1742				yyerror("unknown timeout %s", $1);
1743				YYERROR;
1744			}
1745		}
1746		;
1747
1748timeout_list	: timeout_list comma timeout_spec
1749		| timeout_spec
1750		;
1751
1752limit_spec	: STRING number
1753		{
1754			if (pf->opts & PF_OPT_VERBOSE)
1755				printf("set limit %s %u\n", $1, $2);
1756			if (check_rulestate(PFCTL_STATE_OPTION))
1757				YYERROR;
1758			if (pfctl_set_limit(pf, $1, $2) != 0) {
1759				yyerror("unable to set limit %s %u", $1, $2);
1760				YYERROR;
1761			}
1762		}
1763
1764limit_list	: limit_list comma limit_spec
1765		| limit_spec
1766		;
1767
1768comma		: ','
1769		| /* empty */
1770		;
1771
1772%%
1773
1774int
1775yyerror(char *fmt, ...)
1776{
1777	va_list ap;
1778	extern char *infile;
1779	errors = 1;
1780
1781	va_start(ap, fmt);
1782	fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
1783	vfprintf(stderr, fmt, ap);
1784	fprintf(stderr, "\n");
1785	va_end(ap);
1786	return (0);
1787}
1788
1789int
1790rule_consistent(struct pf_rule *r)
1791{
1792	int problems = 0;
1793
1794	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
1795	    (r->src.port_op || r->dst.port_op)) {
1796		yyerror("port only applies to tcp/udp");
1797		problems++;
1798	}
1799	if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
1800	    (r->type || r->code)) {
1801		yyerror("icmp-type/code only applies to icmp");
1802		problems++;
1803	}
1804	if (!r->af && (r->type || r->code)) {
1805		yyerror("must indicate address family with icmp-type/code");
1806		problems++;
1807	}
1808	if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
1809	    (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
1810		yyerror("icmp version does not match address family");
1811		problems++;
1812	}
1813	if (r->keep_state == PF_STATE_MODULATE && r->proto &&
1814	    r->proto != IPPROTO_TCP) {
1815		yyerror("modulate state can only be applied to TCP rules");
1816		problems++;
1817	}
1818	if (r->allow_opts && r->action != PF_PASS) {
1819		yyerror("allow-opts can only be specified for pass rules");
1820		problems++;
1821	}
1822	if (!r->af && (r->src.addr.addr_dyn != NULL ||
1823	    r->dst.addr.addr_dyn != NULL)) {
1824		yyerror("dynamic addresses require address family (inet/inet6)");
1825		problems++;
1826	}
1827	if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
1828	    r->dst.port_op || r->flagset || r->type || r->code)) {
1829		yyerror("fragments can be filtered only on IP header fields");
1830		problems++;
1831	}
1832	if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) {
1833		yyerror("return-rst can only be applied to TCP rules");
1834		problems++;
1835	}
1836	if (r->action == PF_DROP && r->keep_state) {
1837		yyerror("keep state on block rules doesn't make sense");
1838		problems++;
1839	}
1840	return (-problems);
1841}
1842
1843int
1844nat_consistent(struct pf_nat *r)
1845{
1846	int problems = 0;
1847
1848	if (!r->af && (r->raddr.addr_dyn != NULL)) {
1849		yyerror("dynamic addresses require address family (inet/inet6)");
1850		problems++;
1851	}
1852	return (-problems);
1853}
1854
1855int
1856rdr_consistent(struct pf_rdr *r)
1857{
1858	int problems = 0;
1859
1860	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
1861	    (r->dport || r->dport2 || r->rport)) {
1862		yyerror("port only applies to tcp/udp");
1863		problems++;
1864	}
1865	if (!r->af && (r->saddr.addr_dyn != NULL ||
1866	    r->daddr.addr_dyn != NULL || r->raddr.addr_dyn != NULL)) {
1867		yyerror("dynamic addresses require address family (inet/inet6)");
1868		problems++;
1869	}
1870	return (-problems);
1871}
1872
1873struct keywords {
1874	const char	*k_name;
1875	int	 k_val;
1876};
1877
1878/* macro gore, but you should've seen the prior indentation nightmare... */
1879
1880#define FREE_LIST(T,r) \
1881	do { \
1882		T *p, *n = r; \
1883		while (n != NULL) { \
1884			p = n; \
1885			n = n->next; \
1886			free(p); \
1887		} \
1888	} while (0)
1889
1890#define LOOP_THROUGH(T,n,r,C) \
1891	do { \
1892		T *n; \
1893		if (r == NULL) { \
1894			r = calloc(1, sizeof(T)); \
1895			if (r == NULL) \
1896				err(1, "LOOP: calloc"); \
1897			r->next = NULL; \
1898		} \
1899		n = r; \
1900		while (n != NULL) { \
1901			do { \
1902				C; \
1903			} while (0); \
1904			n = n->next; \
1905		} \
1906	} while (0)
1907
1908void
1909expand_label_if(const char *name, char *label, const char *ifname)
1910{
1911	char tmp[PF_RULE_LABEL_SIZE];
1912	char *p;
1913
1914	while ((p = strstr(label, name)) != NULL) {
1915		tmp[0] = 0;
1916		strlcat(tmp, label, p-label+1);
1917		if (!*ifname)
1918			strlcat(tmp, "any", PF_RULE_LABEL_SIZE);
1919		else
1920			strlcat(tmp, ifname, PF_RULE_LABEL_SIZE);
1921		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
1922		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
1923	}
1924}
1925
1926void
1927expand_label_addr(const char *name, char *label, sa_family_t af,
1928    struct node_host *host)
1929{
1930	char tmp[PF_RULE_LABEL_SIZE];
1931	char *p;
1932
1933	while ((p = strstr(label, name)) != NULL) {
1934		tmp[0] = 0;
1935
1936		strlcat(tmp, label, p-label+1);
1937
1938		if (host->not)
1939			strlcat(tmp, "! ", PF_RULE_LABEL_SIZE);
1940		if (host->addr.addr_dyn != NULL) {
1941			strlcat(tmp, "(", PF_RULE_LABEL_SIZE);
1942			strlcat(tmp, host->addr.addr.pfa.ifname,
1943			    PF_RULE_LABEL_SIZE);
1944			strlcat(tmp, ")", PF_RULE_LABEL_SIZE);
1945		} else if (!af || (PF_AZERO(&host->addr.addr, af) &&
1946		    PF_AZERO(&host->mask, af)))
1947			strlcat(tmp, "any", PF_RULE_LABEL_SIZE);
1948		else {
1949			char a[48];
1950			int bits;
1951
1952			if (inet_ntop(af, &host->addr.addr, a,
1953			    sizeof(a)) == NULL)
1954				strlcat(a, "?", sizeof(a));
1955			strlcat(tmp, a, PF_RULE_LABEL_SIZE);
1956			bits = unmask(&host->mask, af);
1957			a[0] = 0;
1958			if ((af == AF_INET && bits < 32) ||
1959			    (af == AF_INET6 && bits < 128))
1960				snprintf(a, sizeof(a), "/%d", bits);
1961			strlcat(tmp, a, PF_RULE_LABEL_SIZE);
1962		}
1963		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
1964		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
1965	}
1966}
1967
1968void
1969expand_label_port(const char *name, char *label, struct node_port *port)
1970{
1971	char tmp[PF_RULE_LABEL_SIZE];
1972	char *p;
1973	char a1[6], a2[6], op[13];
1974
1975	while ((p = strstr(label, name)) != NULL) {
1976		tmp[0] = 0;
1977
1978		strlcat(tmp, label, p-label+1);
1979
1980		snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0]));
1981		snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1]));
1982		if (!port->op)
1983			op[0] = 0;
1984		else if (port->op == PF_OP_IRG)
1985			snprintf(op, sizeof(op), "%s><%s", a1, a2);
1986		else if (port->op == PF_OP_XRG)
1987			snprintf(op, sizeof(op), "%s<>%s", a1, a2);
1988		else if (port->op == PF_OP_EQ)
1989			snprintf(op, sizeof(op), "%s", a1);
1990		else if (port->op == PF_OP_NE)
1991			snprintf(op, sizeof(op), "!=%s", a1);
1992		else if (port->op == PF_OP_LT)
1993			snprintf(op, sizeof(op), "<%s", a1);
1994		else if (port->op == PF_OP_LE)
1995			snprintf(op, sizeof(op), "<=%s", a1);
1996		else if (port->op == PF_OP_GT)
1997			snprintf(op, sizeof(op), ">%s", a1);
1998		else if (port->op == PF_OP_GE)
1999			snprintf(op, sizeof(op), ">=%s", a1);
2000		strlcat(tmp, op, PF_RULE_LABEL_SIZE);
2001		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
2002		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
2003	}
2004}
2005
2006void
2007expand_label_proto(const char *name, char *label, u_int8_t proto)
2008{
2009	char tmp[PF_RULE_LABEL_SIZE];
2010	char *p;
2011	struct protoent *pe;
2012
2013	while ((p = strstr(label, name)) != NULL) {
2014		tmp[0] = 0;
2015		strlcat(tmp, label, p-label+1);
2016		pe = getprotobynumber(proto);
2017		if (pe != NULL)
2018		    strlcat(tmp, pe->p_name, PF_RULE_LABEL_SIZE);
2019		else
2020		    snprintf(tmp+strlen(tmp), PF_RULE_LABEL_SIZE-strlen(tmp),
2021			"%u", proto);
2022		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
2023		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
2024	}
2025}
2026
2027void
2028expand_label_nr(const char *name, char *label)
2029{
2030	char tmp[PF_RULE_LABEL_SIZE];
2031	char *p;
2032
2033	while ((p = strstr(label, name)) != NULL) {
2034		tmp[0] = 0;
2035		strlcat(tmp, label, p-label+1);
2036		snprintf(tmp+strlen(tmp), PF_RULE_LABEL_SIZE-strlen(tmp),
2037		    "%u", pf->rule_nr);
2038		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
2039		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
2040	}
2041}
2042
2043void
2044expand_label(char *label, const char *ifname, sa_family_t af,
2045    struct node_host *src_host, struct node_port *src_port,
2046    struct node_host *dst_host, struct node_port *dst_port,
2047    u_int8_t proto)
2048{
2049	expand_label_if("$if", label, ifname);
2050	expand_label_addr("$srcaddr", label, af, src_host);
2051	expand_label_addr("$dstaddr", label, af, dst_host);
2052	expand_label_port("$srcport", label, src_port);
2053	expand_label_port("$dstport", label, dst_port);
2054	expand_label_proto("$proto", label, proto);
2055	expand_label_nr("$nr", label);
2056}
2057
2058void
2059expand_rule(struct pf_rule *r,
2060    struct node_if *interfaces, struct node_proto *protos,
2061    struct node_host *src_hosts, struct node_port *src_ports,
2062    struct node_host *dst_hosts, struct node_port *dst_ports,
2063    struct node_uid *uids, struct node_gid *gids,
2064    struct node_icmp *icmp_types)
2065{
2066	sa_family_t	af = r->af;
2067	int nomatch = 0, added = 0;
2068	char	ifname[IF_NAMESIZE];
2069	char	label[PF_RULE_LABEL_SIZE];
2070	u_int8_t 	flags, flagset;
2071
2072	strlcpy(label, r->label, sizeof(label));
2073	flags = r->flags;
2074	flagset = r->flagset;
2075
2076	LOOP_THROUGH(struct node_if, interface, interfaces,
2077	LOOP_THROUGH(struct node_proto, proto, protos,
2078	LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
2079	LOOP_THROUGH(struct node_host, src_host, src_hosts,
2080	LOOP_THROUGH(struct node_port, src_port, src_ports,
2081	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
2082	LOOP_THROUGH(struct node_port, dst_port, dst_ports,
2083	LOOP_THROUGH(struct node_uid, uid, uids,
2084	LOOP_THROUGH(struct node_gid, gid, gids,
2085
2086		r->af = af;
2087		/* for link-local IPv6 address, interface must match up */
2088		if ((r->af && src_host->af && r->af != src_host->af) ||
2089		    (r->af && dst_host->af && r->af != dst_host->af) ||
2090		    (src_host->af && dst_host->af &&
2091		    src_host->af != dst_host->af) ||
2092		    (src_host->ifindex && dst_host->ifindex &&
2093		    src_host->ifindex != dst_host->ifindex) ||
2094		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
2095		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
2096		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
2097		    dst_host->ifindex != if_nametoindex(interface->ifname)))
2098			continue;
2099		if (!r->af && src_host->af)
2100			r->af = src_host->af;
2101		else if (!r->af && dst_host->af)
2102			r->af = dst_host->af;
2103
2104		if (if_indextoname(src_host->ifindex, ifname))
2105			memcpy(r->ifname, ifname, sizeof(r->ifname));
2106		else if (if_indextoname(dst_host->ifindex, ifname))
2107			memcpy(r->ifname, ifname, sizeof(r->ifname));
2108		else
2109			memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
2110
2111		strlcpy(r->label, label, PF_RULE_LABEL_SIZE);
2112		expand_label(r->label, r->ifname, r->af, src_host, src_port,
2113		    dst_host, dst_port, proto->proto);
2114		r->ifnot = interface->not;
2115		r->proto = proto->proto;
2116		r->src.addr = src_host->addr;
2117		r->src.mask = src_host->mask;
2118		r->src.noroute = src_host->noroute;
2119		r->src.not = src_host->not;
2120		r->src.port[0] = src_port->port[0];
2121		r->src.port[1] = src_port->port[1];
2122		r->src.port_op = src_port->op;
2123		r->dst.addr = dst_host->addr;
2124		r->dst.mask = dst_host->mask;
2125		r->dst.noroute = dst_host->noroute;
2126		r->dst.not = dst_host->not;
2127		r->dst.port[0] = dst_port->port[0];
2128		r->dst.port[1] = dst_port->port[1];
2129		r->dst.port_op = dst_port->op;
2130		r->uid.op = uid->op;
2131		r->uid.uid[0] = uid->uid[0];
2132		r->uid.uid[1] = uid->uid[1];
2133		r->gid.op = gid->op;
2134		r->gid.gid[0] = gid->gid[0];
2135		r->gid.gid[1] = gid->gid[1];
2136		r->type = icmp_type->type;
2137		r->code = icmp_type->code;
2138
2139		if (r->proto && r->proto != IPPROTO_TCP) {
2140			r->flags = 0;
2141			r->flagset = 0;
2142		} else {
2143			r->flags = flags;
2144			r->flagset = flagset;
2145		}
2146		if (icmp_type->proto && r->proto != icmp_type->proto) {
2147			yyerror("icmp-type mismatch");
2148			nomatch++;
2149		}
2150
2151		if (rule_consistent(r) < 0 || nomatch)
2152			yyerror("skipping filter rule due to errors");
2153		else {
2154			r->nr = pf->rule_nr++;
2155			pfctl_add_rule(pf, r);
2156			added++;
2157		}
2158
2159	)))))))));
2160
2161	FREE_LIST(struct node_if, interfaces);
2162	FREE_LIST(struct node_proto, protos);
2163	FREE_LIST(struct node_host, src_hosts);
2164	FREE_LIST(struct node_port, src_ports);
2165	FREE_LIST(struct node_host, dst_hosts);
2166	FREE_LIST(struct node_port, dst_ports);
2167	FREE_LIST(struct node_uid, uids);
2168	FREE_LIST(struct node_gid, gids);
2169	FREE_LIST(struct node_icmp, icmp_types);
2170
2171	if (!added)
2172		yyerror("rule expands to no valid combination");
2173}
2174
2175void
2176expand_nat(struct pf_nat *n,
2177    struct node_if *interfaces, struct node_proto *protos,
2178    struct node_host *src_hosts, struct node_port *src_ports,
2179    struct node_host *dst_hosts, struct node_port *dst_ports)
2180{
2181	char ifname[IF_NAMESIZE];
2182	sa_family_t af = n->af;
2183	int added = 0;
2184
2185	LOOP_THROUGH(struct node_if, interface, interfaces,
2186	LOOP_THROUGH(struct node_proto, proto, protos,
2187	LOOP_THROUGH(struct node_host, src_host, src_hosts,
2188	LOOP_THROUGH(struct node_port, src_port, src_ports,
2189	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
2190	LOOP_THROUGH(struct node_port, dst_port, dst_ports,
2191
2192		n->af = af;
2193		/* for link-local IPv6 address, interface must match up */
2194		if ((n->af && src_host->af && n->af != src_host->af) ||
2195		    (n->af && dst_host->af && n->af != dst_host->af) ||
2196		    (src_host->af && dst_host->af &&
2197		    src_host->af != dst_host->af) ||
2198		    (src_host->ifindex && dst_host->ifindex &&
2199		    src_host->ifindex != dst_host->ifindex) ||
2200		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
2201		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
2202		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
2203		    dst_host->ifindex != if_nametoindex(interface->ifname)))
2204			continue;
2205		if (!n->af && src_host->af)
2206			n->af = src_host->af;
2207		else if (!n->af && dst_host->af)
2208			n->af = dst_host->af;
2209
2210		if (if_indextoname(src_host->ifindex, ifname))
2211			memcpy(n->ifname, ifname, sizeof(n->ifname));
2212		else if (if_indextoname(dst_host->ifindex, ifname))
2213			memcpy(n->ifname, ifname, sizeof(n->ifname));
2214		else
2215			memcpy(n->ifname, interface->ifname, sizeof(n->ifname));
2216
2217		n->ifnot = interface->not;
2218		n->proto = proto->proto;
2219		n->src.addr = src_host->addr;
2220		n->src.mask = src_host->mask;
2221		n->src.noroute = src_host->noroute;
2222		n->src.not = src_host->not;
2223		n->src.port[0] = src_port->port[0];
2224		n->src.port[1] = src_port->port[1];
2225		n->src.port_op = src_port->op;
2226		n->dst.addr = dst_host->addr;
2227		n->dst.mask = dst_host->mask;
2228		n->dst.noroute = dst_host->noroute;
2229		n->dst.not = dst_host->not;
2230		n->dst.port[0] = dst_port->port[0];
2231		n->dst.port[1] = dst_port->port[1];
2232		n->dst.port_op = dst_port->op;
2233
2234		if (nat_consistent(n) < 0)
2235			yyerror("skipping nat rule due to errors");
2236		else {
2237			pfctl_add_nat(pf, n);
2238			added++;
2239		}
2240
2241	))))));
2242
2243	FREE_LIST(struct node_if, interfaces);
2244	FREE_LIST(struct node_proto, protos);
2245	FREE_LIST(struct node_host, src_hosts);
2246	FREE_LIST(struct node_port, src_ports);
2247	FREE_LIST(struct node_host, dst_hosts);
2248	FREE_LIST(struct node_port, dst_ports);
2249
2250	if (!added)
2251		yyerror("nat rule expands to no valid combinations");
2252}
2253
2254void
2255expand_rdr(struct pf_rdr *r, struct node_if *interfaces,
2256    struct node_proto *protos, struct node_host *src_hosts,
2257    struct node_host *dst_hosts)
2258{
2259	sa_family_t af = r->af;
2260	int added = 0;
2261	char ifname[IF_NAMESIZE];
2262
2263	LOOP_THROUGH(struct node_if, interface, interfaces,
2264	LOOP_THROUGH(struct node_proto, proto, protos,
2265	LOOP_THROUGH(struct node_host, src_host, src_hosts,
2266	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
2267
2268		r->af = af;
2269		if ((r->af && src_host->af && r->af != src_host->af) ||
2270		    (r->af && dst_host->af && r->af != dst_host->af) ||
2271		    (src_host->af && dst_host->af &&
2272		    src_host->af != dst_host->af) ||
2273		    (src_host->ifindex && dst_host->ifindex &&
2274		    src_host->ifindex != dst_host->ifindex) ||
2275		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
2276		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
2277		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
2278		    dst_host->ifindex != if_nametoindex(interface->ifname)))
2279			continue;
2280
2281		if (!r->af && src_host->af)
2282			r->af = src_host->af;
2283		else if (!r->af && dst_host->af)
2284			r->af = dst_host->af;
2285
2286		if (if_indextoname(src_host->ifindex, ifname))
2287			memcpy(r->ifname, ifname, sizeof(r->ifname));
2288		else if (if_indextoname(dst_host->ifindex, ifname))
2289			memcpy(r->ifname, ifname, sizeof(r->ifname));
2290		else
2291			memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
2292
2293		r->proto = proto->proto;
2294		r->ifnot = interface->not;
2295		r->saddr = src_host->addr;
2296		r->smask = src_host->mask;
2297		r->daddr = dst_host->addr;
2298		r->dmask = dst_host->mask;
2299
2300		if (rdr_consistent(r) < 0)
2301			yyerror("skipping rdr rule due to errors");
2302		else {
2303			pfctl_add_rdr(pf, r);
2304			added++;
2305		}
2306
2307	))));
2308
2309	FREE_LIST(struct node_if, interfaces);
2310	FREE_LIST(struct node_proto, protos);
2311	FREE_LIST(struct node_host, src_hosts);
2312	FREE_LIST(struct node_host, dst_hosts);
2313
2314	if (!added)
2315		yyerror("rdr rule expands to no valid combination");
2316}
2317
2318#undef FREE_LIST
2319#undef LOOP_THROUGH
2320
2321int
2322check_rulestate(int desired_state)
2323{
2324	if (require_order && (rulestate > desired_state)) {
2325		yyerror("Rules must be in order: options, normalization, "
2326		    "translation, filter");
2327		return (1);
2328	}
2329	rulestate = desired_state;
2330	return (0);
2331}
2332
2333int
2334kw_cmp(const void *k, const void *e)
2335{
2336	return (strcmp(k, ((const struct keywords *)e)->k_name));
2337}
2338
2339int
2340lookup(char *s)
2341{
2342	/* this has to be sorted always */
2343	static const struct keywords keywords[] = {
2344		{ "all",	ALL},
2345		{ "allow-opts",	ALLOWOPTS},
2346		{ "antispoof",	ANTISPOOF},
2347		{ "any",	ANY},
2348		{ "binat",	BINAT},
2349		{ "block",	BLOCK},
2350		{ "block-policy", BLOCKPOLICY},
2351		{ "code",	CODE},
2352		{ "crop",	FRAGCROP},
2353		{ "drop",	DROP},
2354		{ "drop-ovl",	FRAGDROP},
2355		{ "dup-to",	DUPTO},
2356		{ "fastroute",	FASTROUTE},
2357		{ "flags",	FLAGS},
2358		{ "for", 	FOR},
2359		{ "fragment",	FRAGMENT},
2360		{ "from",	FROM},
2361		{ "group",	GROUP},
2362		{ "icmp-type",	ICMPTYPE},
2363		{ "in",		IN},
2364		{ "inet",	INET},
2365		{ "inet6",	INET6},
2366		{ "ipv6-icmp-type", ICMP6TYPE},
2367		{ "keep",	KEEP},
2368		{ "label",	LABEL},
2369		{ "limit",	LIMIT},
2370		{ "log",	LOG},
2371		{ "log-all",	LOGALL},
2372		{ "loginterface", LOGINTERFACE},
2373		{ "max",	MAXIMUM},
2374		{ "max-mss",	MAXMSS},
2375		{ "min-ttl",	MINTTL},
2376		{ "modulate",	MODULATE},
2377		{ "nat",	NAT},
2378		{ "no",		NO},
2379		{ "no-df",	NODF},
2380		{ "no-route",	NOROUTE},
2381		{ "on",		ON},
2382		{ "optimization", OPTIMIZATION},
2383		{ "out",	OUT},
2384		{ "pass",	PASS},
2385		{ "port",	PORT},
2386		{ "proto",	PROTO},
2387		{ "quick",	QUICK},
2388		{ "rdr",	RDR},
2389		{ "reassemble",	FRAGNORM},
2390		{ "reply-to",	REPLYTO},
2391		{ "require-order", REQUIREORDER},
2392		{ "return",	RETURN},
2393		{ "return-icmp",RETURNICMP},
2394		{ "return-icmp6",RETURNICMP6},
2395		{ "return-rst",	RETURNRST},
2396		{ "route-to",	ROUTETO},
2397		{ "scrub",	SCRUB},
2398		{ "set",	SET},
2399		{ "state",	STATE},
2400		{ "timeout",	TIMEOUT},
2401		{ "to",		TO},
2402		{ "tos",	TOS},
2403		{ "ttl",	TTL},
2404		{ "user",	USER},
2405		{ "yes",	YES},
2406	};
2407	const struct keywords *p;
2408
2409	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
2410	    sizeof(keywords[0]), kw_cmp);
2411
2412	if (p) {
2413		if (debug > 1)
2414			fprintf(stderr, "%s: %d\n", s, p->k_val);
2415		return (p->k_val);
2416	} else {
2417		if (debug > 1)
2418			fprintf(stderr, "string: %s\n", s);
2419		return (STRING);
2420	}
2421}
2422
2423#define MAXPUSHBACK	128
2424
2425char	*parsebuf;
2426int	parseindex;
2427char	pushback_buffer[MAXPUSHBACK];
2428int	pushback_index = 0;
2429
2430int
2431lgetc(FILE *fin)
2432{
2433	int c, next;
2434
2435	if (parsebuf) {
2436		/* Read character from the parsebuffer instead of input. */
2437		if (parseindex >= 0) {
2438			c = parsebuf[parseindex++];
2439			if (c != '\0')
2440				return (c);
2441			parsebuf = NULL;
2442		} else
2443			parseindex++;
2444	}
2445
2446	if (pushback_index)
2447		return (pushback_buffer[--pushback_index]);
2448
2449	while ((c = getc(fin)) == '\\') {
2450		next = getc(fin);
2451		if (next != '\n') {
2452			if (isspace(next))
2453				yyerror("whitespace after \\");
2454			ungetc(next, fin);
2455			break;
2456		}
2457		yylval.lineno = lineno;
2458		lineno++;
2459	}
2460	if (c == '\t' || c == ' ') {
2461		/* Compress blanks to a single space. */
2462		do {
2463			c = getc(fin);
2464		} while (c == '\t' || c == ' ');
2465		ungetc(c, fin);
2466		c = ' ';
2467	}
2468
2469	return (c);
2470}
2471
2472int
2473lungetc(int c, FILE *fin)
2474{
2475	if (c == EOF)
2476		return (EOF);
2477	if (parsebuf) {
2478		parseindex--;
2479		if (parseindex >= 0)
2480			return (c);
2481	}
2482	if (pushback_index < MAXPUSHBACK-1)
2483		return (pushback_buffer[pushback_index++] = c);
2484	else
2485		return (EOF);
2486}
2487
2488int
2489findeol(void)
2490{
2491	int c;
2492
2493	parsebuf = NULL;
2494	pushback_index = 0;
2495
2496	/* skip to either EOF or the first real EOL */
2497	while (1) {
2498		c = lgetc(fin);
2499		if (c == '\n') {
2500			lineno++;
2501			break;
2502		}
2503		if (c == EOF)
2504			break;
2505	}
2506	return (ERROR);
2507}
2508
2509int
2510yylex(void)
2511{
2512	char buf[8096], *p, *val;
2513	int endc, c, next;
2514	int token;
2515
2516top:
2517	p = buf;
2518	while ((c = lgetc(fin)) == ' ')
2519		;
2520
2521	yylval.lineno = lineno;
2522	if (c == '#')
2523		while ((c = lgetc(fin)) != '\n' && c != EOF)
2524			;
2525	if (c == '$' && parsebuf == NULL) {
2526		while (1) {
2527			if ((c = lgetc(fin)) == EOF)
2528				return (0);
2529			if (p + 1 >= buf + sizeof(buf) - 1) {
2530				yyerror("string too long");
2531				return (findeol());
2532			}
2533			if (isalnum(c) || c == '_') {
2534				*p++ = (char)c;
2535				continue;
2536			}
2537			*p = '\0';
2538			lungetc(c, fin);
2539			break;
2540		}
2541		val = symget(buf);
2542		if (val == NULL) {
2543			yyerror("macro '%s' not defined", buf);
2544			return (findeol());
2545		}
2546		parsebuf = val;
2547		parseindex = 0;
2548		goto top;
2549	}
2550
2551	switch (c) {
2552	case '\'':
2553	case '"':
2554		endc = c;
2555		while (1) {
2556			if ((c = lgetc(fin)) == EOF)
2557				return (0);
2558			if (c == endc) {
2559				*p = '\0';
2560				break;
2561			}
2562			if (c == '\n') {
2563				lineno++;
2564				continue;
2565			}
2566			if (p + 1 >= buf + sizeof(buf) - 1) {
2567				yyerror("string too long");
2568				return (findeol());
2569			}
2570			*p++ = (char)c;
2571		}
2572		yylval.v.string = strdup(buf);
2573		if (yylval.v.string == NULL)
2574			err(1, "yylex: strdup");
2575		return (STRING);
2576	case '=':
2577		yylval.v.i = PF_OP_EQ;
2578		return (PORTUNARY);
2579	case '!':
2580		next = lgetc(fin);
2581		if (next == '=') {
2582			yylval.v.i = PF_OP_NE;
2583			return (PORTUNARY);
2584		}
2585		lungetc(next, fin);
2586		break;
2587	case '<':
2588		next = lgetc(fin);
2589		if (next == '>') {
2590			yylval.v.i = PF_OP_XRG;
2591			return (PORTBINARY);
2592		} else  if (next == '=') {
2593			yylval.v.i = PF_OP_LE;
2594		} else {
2595			yylval.v.i = PF_OP_LT;
2596			lungetc(next, fin);
2597		}
2598		return (PORTUNARY);
2599		break;
2600	case '>':
2601		next = lgetc(fin);
2602		if (next == '<') {
2603			yylval.v.i = PF_OP_IRG;
2604			return (PORTBINARY);
2605		} else  if (next == '=') {
2606			yylval.v.i = PF_OP_GE;
2607		} else {
2608			yylval.v.i = PF_OP_GT;
2609			lungetc(next, fin);
2610		}
2611		return (PORTUNARY);
2612		break;
2613	case '-':
2614		next = lgetc(fin);
2615		if (next == '>')
2616			return (ARROW);
2617		lungetc(next, fin);
2618		break;
2619	}
2620
2621#define allowed_in_string(x) \
2622	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
2623	x != '{' && x != '}' && x != '<' && x != '>' && \
2624	x != '!' && x != '=' && x != '/' && x != '#' && \
2625	x != ','))
2626
2627	if (isalnum(c) || c == ':') {
2628		do {
2629			*p++ = c;
2630			if ((unsigned)(p-buf) >= sizeof(buf)) {
2631				yyerror("string too long");
2632				return (findeol());
2633			}
2634		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
2635		lungetc(c, fin);
2636		*p = '\0';
2637		token = lookup(buf);
2638		yylval.v.string = strdup(buf);
2639		if (yylval.v.string == NULL)
2640			err(1, "yylex: strdup");
2641		return (token);
2642	}
2643	if (c == '\n') {
2644		yylval.lineno = lineno;
2645		lineno++;
2646	}
2647	if (c == EOF)
2648		return (0);
2649	return (c);
2650}
2651
2652int
2653parse_rules(FILE *input, struct pfctl *xpf)
2654{
2655	struct sym *sym;
2656
2657	fin = input;
2658	pf = xpf;
2659	lineno = 1;
2660	errors = 0;
2661	rulestate = PFCTL_STATE_NONE;
2662	yyparse();
2663
2664	/* Check which macros have not been used. */
2665	for (sym = symhead; sym; sym = sym->next)
2666		if (!sym->used)
2667			fprintf(stderr, "warning: macro '%s' not used\n",
2668			    sym->nam);
2669
2670	return (errors ? -1 : 0);
2671}
2672
2673void
2674set_ipmask(struct node_host *h, u_int8_t b)
2675{
2676	struct pf_addr *m, *n;
2677	int i, j = 0;
2678
2679	m = &h->mask;
2680
2681	for (i = 0; i < 4; i++)
2682		m->addr32[i] = 0;
2683
2684	while (b >= 32) {
2685		m->addr32[j++] = 0xffffffff;
2686		b -= 32;
2687	}
2688	for (i = 31; i > 31-b; --i)
2689		m->addr32[j] |= (1 << i);
2690	if (b)
2691		m->addr32[j] = htonl(m->addr32[j]);
2692
2693	/* Mask off bits of the address that will never be used. */
2694	n = &h->addr.addr;
2695	for (i = 0; i < 4; i++)
2696		n->addr32[i] = n->addr32[i] & m->addr32[i];
2697}
2698
2699/*
2700 * Over-designed efficiency is a French and German concept, so how about
2701 * we wait until they discover this ugliness and make it all fancy.
2702 */
2703int
2704symset(const char *nam, const char *val)
2705{
2706	struct sym *sym;
2707
2708	sym = calloc(1, sizeof(*sym));
2709	if (sym == NULL)
2710		return (-1);
2711	sym->nam = strdup(nam);
2712	if (sym->nam == NULL) {
2713		free(sym);
2714		return (-1);
2715	}
2716	sym->val = strdup(val);
2717	if (sym->val == NULL) {
2718		free(sym->nam);
2719		free(sym);
2720		return (-1);
2721	}
2722	sym->next = symhead;
2723	sym->used = 0;
2724	symhead = sym;
2725	return (0);
2726}
2727
2728char *
2729symget(const char *nam)
2730{
2731	struct sym *sym;
2732
2733	for (sym = symhead; sym; sym = sym->next)
2734		if (strcmp(nam, sym->nam) == 0) {
2735			sym->used = 1;
2736			return (sym->val);
2737		}
2738	return (NULL);
2739}
2740
2741/* interface lookup routines */
2742
2743struct node_host *iftab;
2744
2745void
2746ifa_load(void)
2747{
2748	struct ifaddrs *ifap, *ifa;
2749	struct node_host *n = NULL, *h = NULL;
2750
2751	if (getifaddrs(&ifap) < 0)
2752		err(1, "getifaddrs");
2753
2754	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2755		if (!(ifa->ifa_addr->sa_family == AF_INET ||
2756		    ifa->ifa_addr->sa_family == AF_INET6 ||
2757		    ifa->ifa_addr->sa_family == AF_LINK))
2758				continue;
2759		n = calloc(1, sizeof(struct node_host));
2760		if (n == NULL)
2761			err(1, "address: calloc");
2762		n->af = ifa->ifa_addr->sa_family;
2763		n->addr.addr_dyn = NULL;
2764		n->ifa_flags = ifa->ifa_flags;
2765#ifdef __KAME__
2766		if (n->af == AF_INET6 &&
2767		    IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr) &&
2768		    ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 0) {
2769			struct sockaddr_in6 *sin6;
2770
2771			sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
2772			sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 |
2773			    sin6->sin6_addr.s6_addr[3];
2774			sin6->sin6_addr.s6_addr[2] = 0;
2775			sin6->sin6_addr.s6_addr[3] = 0;
2776		}
2777#endif
2778		n->ifindex = 0;
2779		if (n->af == AF_INET) {
2780			memcpy(&n->addr.addr, &((struct sockaddr_in *)
2781			    ifa->ifa_addr)->sin_addr.s_addr,
2782			    sizeof(struct in_addr));
2783			memcpy(&n->mask, &((struct sockaddr_in *)
2784			    ifa->ifa_netmask)->sin_addr.s_addr,
2785			    sizeof(struct in_addr));
2786			if (ifa->ifa_broadaddr != NULL)
2787				memcpy(&n->bcast, &((struct sockaddr_in *)
2788				    ifa->ifa_broadaddr)->sin_addr.s_addr,
2789				    sizeof(struct in_addr));
2790		} else if (n->af == AF_INET6) {
2791			memcpy(&n->addr.addr, &((struct sockaddr_in6 *)
2792			    ifa->ifa_addr)->sin6_addr.s6_addr,
2793			    sizeof(struct in6_addr));
2794			memcpy(&n->mask, &((struct sockaddr_in6 *)
2795			    ifa->ifa_netmask)->sin6_addr.s6_addr,
2796			    sizeof(struct in6_addr));
2797			if (ifa->ifa_broadaddr != NULL)
2798				memcpy(&n->bcast, &((struct sockaddr_in6 *)
2799				    ifa->ifa_broadaddr)->sin6_addr.s6_addr,
2800				    sizeof(struct in6_addr));
2801			n->ifindex = ((struct sockaddr_in6 *)
2802			    ifa->ifa_addr)->sin6_scope_id;
2803		}
2804		if ((n->ifname = strdup(ifa->ifa_name)) == NULL) {
2805			yyerror("malloc failed");
2806			exit(1);
2807		}
2808		n->next = NULL;
2809		n->tail = n;
2810		if (h == NULL)
2811			h = n;
2812		else {
2813			h->tail->next = n;
2814			h->tail = n;
2815		}
2816	}
2817	iftab = h;
2818	freeifaddrs(ifap);
2819}
2820
2821struct node_host *
2822ifa_exists(char *ifa_name)
2823{
2824	struct node_host *n;
2825
2826	if (iftab == NULL)
2827		ifa_load();
2828
2829	for (n = iftab; n; n = n->next) {
2830		if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
2831			return (n);
2832	}
2833	return (NULL);
2834}
2835
2836struct node_host *
2837ifa_lookup(char *ifa_name, enum pfctl_iflookup_mode mode)
2838{
2839	struct node_host *p = NULL, *h = NULL, *n = NULL;
2840	int return_all = 0;
2841
2842	if (!strncmp(ifa_name, "self", IFNAMSIZ))
2843		return_all = 1;
2844
2845	if (iftab == NULL)
2846		ifa_load();
2847
2848	for (p = iftab; p; p = p->next) {
2849		if (!((p->af == AF_INET || p->af == AF_INET6)
2850		    && (!strncmp(p->ifname, ifa_name, IFNAMSIZ) || return_all)))
2851			continue;
2852		if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET)
2853			continue;
2854		if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0)
2855			continue;
2856		n = calloc(1, sizeof(struct node_host));
2857		if (n == NULL)
2858			err(1, "address: calloc");
2859		n->af = p->af;
2860		n->addr.addr_dyn = NULL;
2861		if (mode == PFCTL_IFLOOKUP_BCAST) {
2862				memcpy(&n->addr.addr, &p->bcast,
2863				    sizeof(struct pf_addr));
2864		} else
2865			memcpy(&n->addr.addr, &p->addr.addr,
2866			    sizeof(struct pf_addr));
2867		if (mode == PFCTL_IFLOOKUP_NET)
2868			memcpy(&n->mask, &p->mask, sizeof(struct pf_addr));
2869		else {
2870			if (n->af == AF_INET)
2871				set_ipmask(n, 32);
2872			else
2873				set_ipmask(n, 128);
2874		}
2875		n->ifindex = p->ifindex;
2876
2877		n->next = NULL;
2878		n->tail = n;
2879		if (h == NULL)
2880			h = n;
2881		else {
2882			h->tail->next = n;
2883			h->tail = n;
2884		}
2885	}
2886	if (h == NULL && mode == PFCTL_IFLOOKUP_HOST) {
2887		yyerror("no IP address found for %s", ifa_name);
2888	}
2889	return (h);
2890}
2891
2892struct node_host *
2893ifa_pick_ip(struct node_host *nh, sa_family_t af)
2894{
2895	struct node_host *h, *n = NULL;
2896
2897	if (af == 0 && nh && nh->next) {
2898		yyerror("address family not given and translation address "
2899		    "expands to multiple IPs");
2900		return (NULL);
2901	}
2902	for (h = nh; h; h = h->next) {
2903		if (h->af == af || h->af == 0 || af == 0) {
2904			if (n != NULL) {
2905				yyerror("translation address expands to "
2906				    "multiple IPs of this address family");
2907				return (NULL);
2908			}
2909			n = h;
2910		}
2911	}
2912	if (n == NULL)
2913		yyerror("no translation address with matching address family "
2914		    "found.");
2915	else {
2916		n->next = NULL;
2917		n->tail = n;
2918	}
2919
2920	return (n);
2921}
2922
2923struct node_host *
2924host(char *s, int mask)
2925{
2926	struct node_host *h = NULL, *n;
2927	struct in_addr ina;
2928	struct addrinfo hints, *res0, *res;
2929	int bits, error, v4mask, v6mask;
2930	char *buf = NULL;
2931
2932	if (ifa_exists(s) || !strncmp(s, "self", IFNAMSIZ)) {
2933		/* interface with this name exists */
2934		h = ifa_lookup(s, PFCTL_IFLOOKUP_HOST);
2935		if (h != NULL && mask > -1)
2936			set_ipmask(h, mask);
2937		return (h);
2938	}
2939
2940	if (mask == -1) {
2941		if (asprintf(&buf, "%s", s) == -1)
2942			err(1, "host: malloc");
2943		v4mask = 32;
2944		v6mask = 128;
2945	} else if (mask <= 128) {
2946		if (asprintf(&buf, "%s/%d", s, mask) == -1)
2947			err(1, "host: malloc");
2948		v4mask = v6mask = mask;
2949	} else {
2950		yyerror("illegal mask");
2951		return (NULL);
2952	}
2953
2954	memset(&ina, 0, sizeof(struct in_addr));
2955	if ((bits = inet_net_pton(AF_INET, buf, &ina, sizeof(&ina))) > -1) {
2956		h = calloc(1, sizeof(struct node_host));
2957		if (h == NULL)
2958			err(1, "address: calloc");
2959		h->af = AF_INET;
2960		h->addr.addr_dyn = NULL;
2961		h->addr.addr.addr32[0] = ina.s_addr;
2962		set_ipmask(h, bits);
2963		h->next = NULL;
2964		h->tail = h;
2965		free(buf);
2966		return (h);
2967	}
2968	free(buf);
2969
2970	memset(&hints, 0, sizeof(hints));
2971	hints.ai_family = AF_INET6;
2972	hints.ai_socktype = SOCK_DGRAM; /*dummy*/
2973	hints.ai_flags = AI_NUMERICHOST;
2974	if (getaddrinfo(s, "0", &hints, &res) == 0) {
2975		n = calloc(1, sizeof(struct node_host));
2976		if (n == NULL)
2977			err(1, "address: calloc");
2978		n->af = AF_INET6;
2979		n->addr.addr_dyn = NULL;
2980		memcpy(&n->addr.addr,
2981		    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
2982		    sizeof(n->addr.addr));
2983		n->ifindex = ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
2984		set_ipmask(n, v6mask);
2985		freeaddrinfo(res);
2986		n->next = NULL;
2987		n->tail = n;
2988		return (n);
2989	}
2990
2991	memset(&hints, 0, sizeof(hints));
2992	hints.ai_family = PF_UNSPEC;
2993	hints.ai_socktype = SOCK_STREAM; /* DUMMY */
2994	error = getaddrinfo(s, NULL, &hints, &res0);
2995	if (error) {
2996		yyerror("cannot resolve %s: %s",
2997		    s, gai_strerror(error));
2998		return (NULL);
2999	}
3000	for (res = res0; res; res = res->ai_next) {
3001		if (res->ai_family != AF_INET &&
3002		    res->ai_family != AF_INET6)
3003			continue;
3004		n = calloc(1, sizeof(struct node_host));
3005		if (n == NULL)
3006			err(1, "address: calloc");
3007		n->af = res->ai_family;
3008		n->addr.addr_dyn = NULL;
3009		if (res->ai_family == AF_INET) {
3010			memcpy(&n->addr.addr,
3011			    &((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr,
3012			    sizeof(struct in_addr));
3013			set_ipmask(n, v4mask);
3014		} else {
3015			memcpy(&n->addr.addr,
3016			    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr,
3017			    sizeof(struct in6_addr));
3018			n->ifindex =
3019			    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
3020			set_ipmask(n, v6mask);
3021		}
3022		n->next = NULL;
3023		n->tail = n;
3024		if (h == NULL)
3025			h = n;
3026		else {
3027			h->tail->next = n;
3028			h->tail = n;
3029		}
3030	}
3031	freeaddrinfo(res0);
3032	if (h == NULL) {
3033		yyerror("no IP address found for %s", s);
3034		return (NULL);
3035	}
3036	return (h);
3037}
3038
3039int
3040atoul(char *s, u_long *ulvalp)
3041{
3042	u_long ulval;
3043	char *ep;
3044
3045	errno = 0;
3046	ulval = strtoul(s, &ep, 0);
3047	if (s[0] == '\0' || *ep != '\0')
3048		return (-1);
3049	if (errno == ERANGE && ulval == ULONG_MAX)
3050		return (-1);
3051	*ulvalp = ulval;
3052	return (0);
3053}
3054
3055int
3056getservice(char *n)
3057{
3058	struct servent *s;
3059	u_long ulval;
3060
3061	if (atoul(n, &ulval) == 0) {
3062		if (ulval > 65535) {
3063			yyerror("illegal port value %d", ulval);
3064			return (-1);
3065		}
3066		return (htons(ulval));
3067	} else {
3068		s = getservbyname(n, "tcp");
3069		if (s == NULL)
3070			s = getservbyname(n, "udp");
3071		if (s == NULL) {
3072			yyerror("unknown port %s", n);
3073			return (-1);
3074		}
3075		return (s->s_port);
3076	}
3077}
3078
3079u_int16_t
3080parseicmpspec(char *w, sa_family_t af)
3081{
3082	const struct icmpcodeent *p;
3083	u_long ulval;
3084	u_int8_t icmptype;
3085
3086	if (af == AF_INET)
3087		icmptype = returnicmpdefault >> 8;
3088	else
3089		icmptype = returnicmp6default >> 8;
3090
3091	if (atoul(w, &ulval) == -1) {
3092		if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
3093			yyerror("unknown icmp code %s", w);
3094			return (0);
3095		}
3096		ulval = p->code;
3097	}
3098	return (icmptype << 8 | ulval);
3099}
3100