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