parse.y revision 1.85
1/*	$OpenBSD: parse.y,v 1.85 2002/06/08 20:59:52 itojun Exp $	*/
2
3/*
4 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
5 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27%{
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <sys/ioctl.h>
31#include <net/if.h>
32#include <netinet/in.h>
33#include <netinet/in_systm.h>
34#include <netinet/ip.h>
35#include <netinet/ip_icmp.h>
36#include <netinet/icmp6.h>
37#include <net/pfvar.h>
38#include <arpa/inet.h>
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <ifaddrs.h>
43#include <netdb.h>
44#include <stdarg.h>
45#include <errno.h>
46#include <string.h>
47#include <ctype.h>
48#include <err.h>
49#include <pwd.h>
50
51#include "pfctl_parser.h"
52
53static struct pfctl *pf = NULL;
54static FILE *fin = NULL;
55static int debug = 0;
56static int lineno = 1;
57static int errors = 0;
58static int natmode = 0;
59
60struct node_if {
61	char			 ifname[IFNAMSIZ];
62	u_int8_t		 not;
63	struct node_if		*next;
64};
65
66struct node_proto {
67	u_int8_t		 proto;
68	struct node_proto	*next;
69};
70
71struct node_host {
72	struct pf_addr_wrap	 addr;
73	struct pf_addr		 mask;
74	u_int8_t		 af;
75	u_int8_t		 not;
76	u_int8_t		 noroute;
77	struct node_host	*next;
78	u_int32_t		 ifindex;	/* link-local IPv6 addrs */
79};
80
81struct node_port {
82	u_int16_t		 port[2];
83	u_int8_t		 op;
84	struct node_port	*next;
85};
86
87struct node_uid {
88	uid_t			 uid[2];
89	u_int8_t		 op;
90	struct node_uid		*next;
91};
92
93struct node_gid {
94	gid_t			 gid[2];
95	u_int8_t		 op;
96	struct node_gid		*next;
97};
98
99struct node_icmp {
100	u_int8_t		 code;
101	u_int8_t		 type;
102	u_int8_t		 proto;
103	struct node_icmp	*next;
104};
105
106struct node_state_opt {
107        enum	{ PF_STATE_OPT_MAX=0, PF_STATE_OPT_TIMEOUT=1 };
108	int			 type;
109	union {
110		u_int32_t	 max_states;
111		struct {
112			int	 	number;
113			u_int32_t	seconds;
114		}		 timeout;
115	}			 data;
116	struct node_state_opt	*next;
117};
118
119struct peer {
120	struct node_host	*host;
121	struct node_port	*port;
122};
123
124int	rule_consistent(struct pf_rule *);
125int	yyparse(void);
126void	ipmask(struct pf_addr *, u_int8_t);
127void	expand_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		/* for link-local IPv6 address, interface must match up */
1868		if ((r->af && src_host->af && r->af != src_host->af) ||
1869		    (r->af && dst_host->af && r->af != dst_host->af) ||
1870		    (src_host->af && dst_host->af &&
1871		    src_host->af != dst_host->af) ||
1872		    (src_host->ifindex && dst_host->ifindex &&
1873		    src_host->ifindex != dst_host->ifindex) ||
1874		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
1875		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
1876		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
1877		    dst_host->ifindex != if_nametoindex(interface->ifname)))
1878			continue;
1879		if (!r->af && src_host->af)
1880			r->af = src_host->af;
1881		else if (!r->af && dst_host->af)
1882			r->af = dst_host->af;
1883
1884		if (if_indextoname(src_host->ifindex, ifname))
1885			memcpy(r->ifname, ifname, sizeof(r->ifname));
1886		else if (if_indextoname(dst_host->ifindex, ifname))
1887			memcpy(r->ifname, ifname, sizeof(r->ifname));
1888		else
1889			memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
1890
1891		strlcpy(r->label, label, PF_RULE_LABEL_SIZE);
1892		expand_label(r->label, r->af, src_host, src_port,
1893		    dst_host, dst_port, proto->proto);
1894		r->proto = proto->proto;
1895		r->src.addr = src_host->addr;
1896		r->src.mask = src_host->mask;
1897		r->src.noroute = src_host->noroute;
1898		r->src.not = src_host->not;
1899		r->src.port[0] = src_port->port[0];
1900		r->src.port[1] = src_port->port[1];
1901		r->src.port_op = src_port->op;
1902		r->dst.addr = dst_host->addr;
1903		r->dst.mask = dst_host->mask;
1904		r->dst.noroute = dst_host->noroute;
1905		r->dst.not = dst_host->not;
1906		r->dst.port[0] = dst_port->port[0];
1907		r->dst.port[1] = dst_port->port[1];
1908		r->dst.port_op = dst_port->op;
1909		r->uid.op = uid->op;
1910		r->uid.uid[0] = uid->uid[0];
1911		r->uid.uid[1] = uid->uid[1];
1912		r->gid.op = gid->op;
1913		r->gid.gid[0] = gid->gid[0];
1914		r->gid.gid[1] = gid->gid[1];
1915		r->type = icmp_type->type;
1916		r->code = icmp_type->code;
1917
1918		if (icmp_type->proto && r->proto != icmp_type->proto) {
1919			yyerror("icmp-type mismatch");
1920			nomatch++;
1921		}
1922
1923		if (rule_consistent(r) < 0 || nomatch)
1924			yyerror("skipping rule due to errors");
1925		else {
1926			r->nr = pf->rule_nr++;
1927			pfctl_add_rule(pf, r);
1928			added++;
1929		}
1930
1931	)))))))));
1932
1933	FREE_LIST(struct node_if, interfaces);
1934	FREE_LIST(struct node_proto, protos);
1935	FREE_LIST(struct node_host, src_hosts);
1936	FREE_LIST(struct node_port, src_ports);
1937	FREE_LIST(struct node_host, dst_hosts);
1938	FREE_LIST(struct node_port, dst_ports);
1939	FREE_LIST(struct node_uid, uids);
1940	FREE_LIST(struct node_gid, gids);
1941	FREE_LIST(struct node_icmp, icmp_types);
1942
1943	if (!added)
1944		yyerror("rule expands to no valid combination");
1945}
1946
1947void
1948expand_nat(struct pf_nat *n, struct node_host *src_hosts,
1949    struct node_host *dst_hosts)
1950{
1951	int af = n->af, added = 0;
1952
1953	CHECK_ROOT(struct node_host, src_hosts)
1954;	CHECK_ROOT(struct node_host, dst_hosts);
1955
1956	LOOP_THROUGH(struct node_host, src_host, src_hosts,
1957	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
1958
1959		n->af = af;
1960	    	if ((n->af && src_host->af && n->af != src_host->af) ||
1961		    (n->af && dst_host->af && n->af != dst_host->af) ||
1962		    (src_host->af && dst_host->af &&
1963		    src_host->af != dst_host->af))
1964			continue;
1965		if (!n->af && src_host->af)
1966			n->af = src_host->af;
1967		else if (!n->af && dst_host->af)
1968			n->af = dst_host->af;
1969
1970 	        n->saddr = src_host->addr;
1971		n->smask = src_host->mask;
1972 	        n->daddr = dst_host->addr;
1973		n->dmask = dst_host->mask;
1974
1975		pfctl_add_nat(pf, n);
1976		added++;
1977	));
1978
1979	FREE_LIST(struct node_host, src_hosts);
1980	FREE_LIST(struct node_host, dst_hosts);
1981
1982	if (!added)
1983		yyerror("nat rule expands to no valid AF combination");
1984}
1985
1986
1987#undef FREE_LIST
1988#undef CHECK_ROOT
1989#undef LOOP_THROUGH
1990
1991int
1992kw_cmp(k, e)
1993	const void *k, *e;
1994{
1995	return (strcmp(k, ((struct keywords *)e)->k_name));
1996}
1997
1998int
1999lookup(char *s)
2000{
2001	/* this has to be sorted always */
2002	static const struct keywords keywords[] = {
2003		{ "all",	ALL},
2004		{ "allow-opts",	ALLOWOPTS},
2005		{ "any",	ANY},
2006		{ "binat",	BINAT},
2007		{ "block",	BLOCK},
2008		{ "code",	CODE},
2009		{ "dup-to",	DUPTO},
2010		{ "fastroute",	FASTROUTE},
2011		{ "flags",	FLAGS},
2012		{ "fragment",	FRAGMENT},
2013		{ "from",	FROM},
2014		{ "group",	GROUP},
2015		{ "icmp-type",	ICMPTYPE},
2016		{ "in",		IN},
2017		{ "inet",	INET},
2018		{ "inet6",	INET6},
2019		{ "ipv6-icmp-type", ICMP6TYPE},
2020		{ "keep",	KEEP},
2021		{ "label",	LABEL},
2022		{ "log",	LOG},
2023		{ "log-all",	LOGALL},
2024		{ "max",	MAXIMUM},
2025		{ "max-mss",	MAXMSS},
2026		{ "min-ttl",	MINTTL},
2027		{ "modulate",	MODULATE},
2028		{ "nat",	NAT},
2029		{ "no",		NO},
2030		{ "no-df",	NODF},
2031		{ "no-route",	NOROUTE},
2032		{ "on",		ON},
2033		{ "out",	OUT},
2034		{ "pass",	PASS},
2035		{ "port",	PORT},
2036		{ "proto",	PROTO},
2037		{ "quick",	QUICK},
2038		{ "rdr",	RDR},
2039		{ "return",	RETURN},
2040		{ "return-icmp",RETURNICMP},
2041		{ "return-icmp6",RETURNICMP6},
2042		{ "return-rst",	RETURNRST},
2043		{ "route-to",	ROUTETO},
2044		{ "scrub",	SCRUB},
2045		{ "state",	STATE},
2046		{ "to",		TO},
2047		{ "ttl",	TTL},
2048		{ "user",	USER},
2049	};
2050	const struct keywords *p;
2051
2052	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
2053	    sizeof(keywords[0]), kw_cmp);
2054
2055	if (p) {
2056		if (debug > 1)
2057			fprintf(stderr, "%s: %d\n", s, p->k_val);
2058		return (p->k_val);
2059	} else {
2060		if (debug > 1)
2061			fprintf(stderr, "string: %s\n", s);
2062		return (STRING);
2063	}
2064}
2065
2066char	*parsebuf;
2067int	parseindex;
2068
2069int
2070lgetc(FILE *fin)
2071{
2072	int c, next;
2073
2074restart:
2075	if (parsebuf) {
2076		/* Reading characters from the parse buffer, instead of input */
2077		c = parsebuf[parseindex++];
2078		if (c != '\0')
2079			return (c);
2080		free(parsebuf);
2081		parsebuf = NULL;
2082		parseindex = 0;
2083		goto restart;
2084	}
2085
2086	c = getc(fin);
2087	if (c == '\\') {
2088		next = getc(fin);
2089		if (next != '\n') {
2090			ungetc(next, fin);
2091			return (c);
2092		}
2093		yylval.lineno = lineno;
2094		lineno++;
2095		goto restart;
2096	}
2097	return (c);
2098}
2099
2100int
2101lungetc(int c, FILE *fin)
2102{
2103	if (parsebuf && parseindex) {
2104		/* XXX breaks on index 0 */
2105		parseindex--;
2106		return (c);
2107	}
2108	return ungetc(c, fin);
2109}
2110
2111int
2112findeol()
2113{
2114	int c;
2115
2116	if (parsebuf) {
2117		free(parsebuf);
2118		parsebuf = NULL;
2119		parseindex = 0;
2120	}
2121
2122	/* skip to either EOF or the first real EOL */
2123	while (1) {
2124		c = lgetc(fin);
2125		if (c == '\\') {
2126			c = lgetc(fin);
2127			if (c == '\n')
2128				continue;
2129		}
2130		if (c == EOF || c == '\n')
2131			break;
2132	}
2133	return (ERROR);
2134}
2135
2136int
2137yylex(void)
2138{
2139	char buf[8096], *p, *val;
2140	int endc, c, next;
2141	int token;
2142
2143top:
2144	p = buf;
2145	while ((c = lgetc(fin)) == ' ' || c == '\t')
2146		;
2147
2148	yylval.lineno = lineno;
2149	if (c == '#')
2150		while ((c = lgetc(fin)) != '\n' && c != EOF)
2151			;
2152	if (c == '$' && parsebuf == NULL) {
2153		while (1) {
2154			if ((c = lgetc(fin)) == EOF)
2155				return (0);
2156			if (p + 1 >= buf + sizeof(buf) - 1) {
2157				yyerror("string too long");
2158				return (findeol());
2159			}
2160			if (isalnum(c) || c == '_') {
2161				*p++ = (char)c;
2162				continue;
2163			}
2164			*p = '\0';
2165			lungetc(c, fin);
2166			break;
2167		}
2168		val = symget(buf);
2169		if (val == NULL)
2170			return (ERROR);
2171		parsebuf = strdup(val);
2172		if (parsebuf == NULL)
2173			err(1, "parsebuf: strdup");
2174		parseindex = 0;
2175		goto top;
2176	}
2177
2178	switch (c) {
2179	case '\'':
2180	case '"':
2181		endc = c;
2182		while (1) {
2183			if ((c = lgetc(fin)) == EOF)
2184				return (0);
2185			if (c == endc) {
2186				*p = '\0';
2187				break;
2188			}
2189			if (c == '\n')
2190				continue;
2191			if (p + 1 >= buf + sizeof(buf) - 1) {
2192				yyerror("string too long");
2193				return (findeol());
2194			}
2195			*p++ = (char)c;
2196		}
2197		yylval.v.string = strdup(buf);
2198		if (yylval.v.string == NULL)
2199			err(1, "yylex: strdup");
2200		return (STRING);
2201	case '=':
2202		yylval.v.i = PF_OP_EQ;
2203		return (PORTUNARY);
2204	case '!':
2205		next = lgetc(fin);
2206		if (next == '=') {
2207			yylval.v.i = PF_OP_NE;
2208			return (PORTUNARY);
2209		}
2210		lungetc(next, fin);
2211		break;
2212	case '<':
2213		next = lgetc(fin);
2214		if (next == '>') {
2215			yylval.v.i = PF_OP_XRG;
2216			return (PORTBINARY);
2217		} else  if (next == '=') {
2218			yylval.v.i = PF_OP_LE;
2219		} else {
2220			yylval.v.i = PF_OP_LT;
2221			lungetc(next, fin);
2222		}
2223		return (PORTUNARY);
2224		break;
2225	case '>':
2226		next = lgetc(fin);
2227		if (next == '<') {
2228			yylval.v.i = PF_OP_IRG;
2229			return (PORTBINARY);
2230		} else  if (next == '=') {
2231			yylval.v.i = PF_OP_GE;
2232		} else {
2233			yylval.v.i = PF_OP_GT;
2234			lungetc(next, fin);
2235		}
2236		return (PORTUNARY);
2237		break;
2238	case '-':
2239		next = lgetc(fin);
2240		if (next == '>')
2241			return (ARROW);
2242		lungetc(next, fin);
2243		break;
2244	}
2245
2246	/* Need to parse v6 addresses before tokenizing numbers. ick */
2247	if (isxdigit(c) || c == ':') {
2248		struct node_host *node = NULL;
2249		u_int32_t addr[4];
2250		char lookahead[46];
2251		int i = 0;
2252		struct addrinfo hints, *res;
2253
2254		lookahead[i] = c;
2255
2256		while (i < sizeof(lookahead) &&
2257		    (isalnum(c) || c == ':' || c == '.' || c == '%')) {
2258			lookahead[++i] = c = lgetc(fin);
2259		}
2260
2261		/* quick check avoids calling inet_pton too often */
2262		lungetc(lookahead[i], fin);
2263		lookahead[i] = '\0';
2264
2265		memset(&hints, 0, sizeof(hints));
2266		hints.ai_family = AF_INET6;
2267		hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
2268		hints.ai_flags = AI_NUMERICHOST;
2269		if (getaddrinfo(lookahead, "0", &hints, &res) == 0) {
2270			node = calloc(1, sizeof(struct node_host));
2271			if (node == NULL)
2272				err(1, "yylex: calloc");
2273			node->af = AF_INET6;
2274			node->addr.addr_dyn = NULL;
2275			memcpy(&node->addr.addr,
2276			    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
2277			    sizeof(addr));
2278			node->ifindex = ((struct sockaddr_in6 *)res->ai_addr)
2279			    ->sin6_scope_id;
2280			yylval.v.host = node;
2281			return IPV6ADDR;
2282			freeaddrinfo(res);
2283		} else {
2284			free(node);
2285			while (i > 1)
2286				lungetc(lookahead[--i], fin);
2287			c = lookahead[--i];
2288		}
2289	}
2290
2291	if (isdigit(c)) {
2292		int index = 0, base = 10;
2293		u_int64_t n = 0;
2294
2295		yylval.v.number = 0;
2296		while (1) {
2297			if (base == 10) {
2298				if (!isdigit(c))
2299					break;
2300				c -= '0';
2301			} else if (base == 16) {
2302				if (isdigit(c))
2303					c -= '0';
2304				else if (c >= 'a' && c <= 'f')
2305					c -= 'a' - 10;
2306				else if (c >= 'A' && c <= 'F')
2307					c -= 'A' - 10;
2308				else
2309					break;
2310			}
2311			n = n * base + c;
2312
2313			if (n > UINT_MAX) {
2314				yyerror("number is too large");
2315				return (ERROR);
2316			}
2317			c = lgetc(fin);
2318			if (c == EOF)
2319				break;
2320			if (index++ == 0 && n == 0 && c == 'x') {
2321				base = 16;
2322				c = lgetc(fin);
2323				if (c == EOF)
2324					break;
2325			}
2326		}
2327		yylval.v.number = (u_int32_t)n;
2328
2329		if (c != EOF)
2330			lungetc(c, fin);
2331		if (debug > 1)
2332			fprintf(stderr, "number: %d\n", yylval.v.number);
2333		return (NUMBER);
2334	}
2335
2336#define allowed_in_string(x) \
2337	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
2338	x != '{' && x != '}' && x != '<' && x != '>' && \
2339	x != '!' && x != '=' && x != '/' && x != '#' && \
2340	x != ',' && x != ':' && x != '(' && x != ')'))
2341
2342	if (isalnum(c)) {
2343		do {
2344			*p++ = c;
2345			if (p-buf >= sizeof buf) {
2346				yyerror("string too long");
2347				return (ERROR);
2348			}
2349		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
2350		lungetc(c, fin);
2351		*p = '\0';
2352		token = lookup(buf);
2353		yylval.v.string = strdup(buf);
2354		if (yylval.v.string == NULL)
2355			err(1, "yylex: strdup");
2356		return (token);
2357	}
2358	if (c == '\n') {
2359		yylval.lineno = lineno;
2360		lineno++;
2361	}
2362	if (c == EOF)
2363		return (0);
2364	return (c);
2365}
2366
2367int
2368parse_rules(FILE *input, struct pfctl *xpf)
2369{
2370	natmode = 0;
2371	fin = input;
2372	pf = xpf;
2373	lineno = 1;
2374	errors = 0;
2375	yyparse();
2376	return (errors ? -1 : 0);
2377}
2378
2379int
2380parse_nat(FILE *input, struct pfctl *xpf)
2381{
2382	natmode = 1;
2383	fin = input;
2384	pf = xpf;
2385	lineno = 1;
2386	errors = 0;
2387	yyparse();
2388	return (errors ? -1 : 0);
2389}
2390
2391void
2392ipmask(struct pf_addr *m, u_int8_t b)
2393{
2394	int i, j = 0;
2395
2396	while (b >= 32) {
2397		m->addr32[j++] = 0xffffffff;
2398		b -= 32;
2399	}
2400	for (i = 31; i > 31-b; --i)
2401		m->addr32[j] |= (1 << i);
2402	if (b)
2403		m->addr32[j] = htonl(m->addr32[j]);
2404}
2405
2406/*
2407 * Over-designed efficiency is a French and German concept, so how about
2408 * we wait until they discover this ugliness and make it all fancy.
2409 */
2410int
2411symset(char *nam, char *val)
2412{
2413	struct sym *sym;
2414
2415	sym = calloc(1, sizeof(*sym));
2416	if (sym == NULL)
2417		return (-1);
2418	sym->nam = strdup(nam);
2419	if (sym->nam == NULL) {
2420		free(sym);
2421		return (-1);
2422	}
2423	sym->val = strdup(val);
2424	if (sym->val == NULL) {
2425		free(sym->nam);
2426		free(sym);
2427		return (-1);
2428	}
2429	sym->next = symhead;
2430	symhead = sym;
2431	return (0);
2432}
2433
2434char *
2435symget(char *nam)
2436{
2437	struct sym *sym;
2438
2439	for (sym = symhead; sym; sym = sym->next)
2440		if (strcmp(nam, sym->nam) == 0)
2441			return (sym->val);
2442	return (NULL);
2443}
2444
2445struct ifaddrs **ifa0tab, **ifa4tab, **ifa6tab;
2446int ifa0len, ifa4len, ifa6len;
2447
2448int
2449ifa_comp(const void *p1, const void *p2)
2450{
2451	struct ifaddrs *ifa1 = *(struct ifaddrs **)p1;
2452	struct ifaddrs *ifa2 = *(struct ifaddrs **)p2;
2453
2454	return strcmp(ifa1->ifa_name, ifa2->ifa_name);
2455}
2456
2457void
2458ifa_load(void)
2459{
2460	struct ifaddrs *ifap, *ifa;
2461	void *p;
2462	int ifalen = 0;
2463
2464	if (getifaddrs(&ifap) < 0)
2465		err(1, "getifaddrs");
2466	for (ifa = ifap; ifa; ifa = ifa->ifa_next)
2467		ifalen++;
2468	/* (over-)allocate tables */
2469	ifa0tab = malloc(ifalen * sizeof(void *));
2470	ifa4tab = malloc(ifalen * sizeof(void *));
2471	ifa6tab = malloc(ifalen * sizeof(void *));
2472	if (!ifa0tab || !ifa4tab || !ifa6tab)
2473		err(1, "malloc");
2474	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2475		if (ifa->ifa_addr->sa_family == AF_LINK) {
2476			if (bsearch(&ifa, ifa0tab, ifa0len, sizeof(void *),
2477			    ifa_comp))
2478				continue; /* take only the first LINK address */
2479			ifa0tab[ifa0len++] = ifa;
2480			qsort(ifa0tab, ifa0len, sizeof(void *), ifa_comp);
2481		}
2482		if (ifa->ifa_addr->sa_family == AF_INET) {
2483			if (bsearch(&ifa, ifa4tab, ifa4len, sizeof(void *),
2484			    ifa_comp))
2485				continue; /* take only the first IPv4 address */
2486			ifa4tab[ifa4len++] = ifa;
2487			qsort(ifa4tab, ifa4len, sizeof(void *), ifa_comp);
2488		}
2489		if (ifa->ifa_addr->sa_family == AF_INET6) {
2490			/* XXX - better address selection required! */
2491			if (bsearch(&ifa, ifa6tab, ifa6len, sizeof(void *),
2492			    ifa_comp))
2493				continue; /* take only the first IPv6 address */
2494			ifa6tab[ifa6len++] = ifa;
2495			qsort(ifa6tab, ifa6len, sizeof(void *), ifa_comp);
2496		}
2497	}
2498	/* shrink tables */
2499	if ((p = realloc(ifa0tab, ifa0len * sizeof(void *))) == NULL) {
2500		free(ifa0tab);
2501		ifa0tab = NULL;
2502	} else
2503		ifa0tab = p;
2504	if ((p = realloc(ifa4tab, ifa4len * sizeof(void *))) == NULL) {
2505		free(ifa4tab);
2506		ifa4tab = NULL;
2507	} else
2508		ifa4tab = p;
2509	if ((p = realloc(ifa6tab, ifa6len * sizeof(void *))) == NULL) {
2510		free(ifa6tab);
2511		ifa6tab = NULL;
2512	} else
2513		ifa6tab = p;
2514	if (!ifa0tab || !ifa4tab || !ifa6tab)
2515		err(1, "realloc");
2516}
2517
2518struct ifaddrs *
2519ifa0_lookup(char *ifa_name)
2520{
2521	struct ifaddrs ifa, *ifp = &ifa, **ifpp;
2522
2523	if (!ifa0tab)
2524		ifa_load();
2525	ifa.ifa_name = ifa_name;
2526	ifpp = bsearch(&ifp, ifa0tab, ifa0len, sizeof(void *), ifa_comp);
2527	return ifpp ? *ifpp : NULL;
2528}
2529
2530struct ifaddrs *
2531ifa4_lookup(char *ifa_name)
2532{
2533	struct ifaddrs ifa, *ifp = &ifa, **ifpp;
2534
2535	if (!ifa4tab)
2536		ifa_load();
2537	ifa.ifa_name = ifa_name;
2538	ifpp = bsearch(&ifp, ifa4tab, ifa4len, sizeof(void *), ifa_comp);
2539	return ifpp ? *ifpp : NULL;
2540}
2541
2542struct ifaddrs *
2543ifa6_lookup(char *ifa_name)
2544{
2545	struct ifaddrs ifa, *ifp = &ifa, **ifpp;
2546
2547	if (!ifa6tab)
2548		ifa_load();
2549	ifa.ifa_name = ifa_name;
2550	ifpp = bsearch(&ifp, ifa6tab, ifa6len, sizeof(void *), ifa_comp);
2551	return ifpp ? *ifpp : NULL;
2552}
2553
2554