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