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