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