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