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