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