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