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