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