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