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