parse.y revision 1.193
1/*	$OpenBSD: parse.y,v 1.193 2002/11/19 11:25:45 wilfried 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#include "pfctl_altq.h"
54
55static struct pfctl *pf = NULL;
56static FILE *fin = NULL;
57static int debug = 0;
58static int lineno = 1;
59static int errors = 0;
60static int rulestate = 0;
61static u_int16_t returnicmpdefault =  (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
62static u_int16_t returnicmp6default = (ICMP6_DST_UNREACH << 8) |
63    ICMP6_DST_UNREACH_NOPORT;
64static int blockpolicy = PFRULE_DROP;
65static int require_order = 1;
66
67enum {
68	PFCTL_STATE_NONE = 0,
69	PFCTL_STATE_OPTION = 1,
70	PFCTL_STATE_SCRUB = 2,
71	PFCTL_STATE_NAT = 3,
72	PFCTL_STATE_FILTER = 4
73};
74
75enum pfctl_iflookup_mode {
76	PFCTL_IFLOOKUP_HOST = 0,
77	PFCTL_IFLOOKUP_NET = 1,
78	PFCTL_IFLOOKUP_BCAST = 2
79};
80
81struct node_if {
82	char			 ifname[IFNAMSIZ];
83	u_int8_t		 not;
84	u_int			 ifa_flags;
85	struct node_if		*next;
86	struct node_if		*tail;
87};
88
89struct node_proto {
90	u_int8_t		 proto;
91	struct node_proto	*next;
92	struct node_proto	*tail;
93};
94
95struct node_host {
96	struct pf_addr_wrap	 addr;
97	struct pf_addr		 mask;
98	struct pf_addr		 bcast;
99	sa_family_t		 af;
100	u_int8_t		 not;
101	u_int8_t		 noroute;
102	u_int32_t		 ifindex;	/* link-local IPv6 addrs */
103	char			*ifname;
104	u_int			 ifa_flags;
105	struct node_host	*next;
106	struct node_host	*tail;
107};
108
109struct node_port {
110	u_int16_t		 port[2];
111	u_int8_t		 op;
112	struct node_port	*next;
113	struct node_port	*tail;
114};
115
116struct node_uid {
117	uid_t			 uid[2];
118	u_int8_t		 op;
119	struct node_uid		*next;
120	struct node_uid		*tail;
121};
122
123struct node_gid {
124	gid_t			 gid[2];
125	u_int8_t		 op;
126	struct node_gid		*next;
127	struct node_gid		*tail;
128};
129
130struct node_icmp {
131	u_int8_t		 code;
132	u_int8_t		 type;
133	u_int8_t		 proto;
134	struct node_icmp	*next;
135	struct node_icmp	*tail;
136};
137
138enum	{ PF_STATE_OPT_MAX=0, PF_STATE_OPT_TIMEOUT=1 };
139struct node_state_opt {
140	int			 type;
141	union {
142		u_int32_t	 max_states;
143		struct {
144			int		number;
145			u_int32_t	seconds;
146		}		 timeout;
147	}			 data;
148	struct node_state_opt	*next;
149	struct node_state_opt	*tail;
150};
151
152struct peer {
153	struct node_host	*host;
154	struct node_port	*port;
155};
156
157struct node_queue {
158	char			 queue[PF_QNAME_SIZE];
159	char			 parent[PF_QNAME_SIZE];
160	char			 ifname[IFNAMSIZ];
161	struct node_queue	*next;
162	struct node_queue	*tail;
163}	*queues = NULL;
164
165struct node_queue_opt {
166	int			 qtype;
167	union {	/* options for other schedulers will follow */
168		struct cbq_opts		 cbq_opts;
169	}			 data;
170};
171
172struct node_queue_bw {
173	u_int32_t	bw_absolute;
174	u_int16_t	bw_percent;
175};
176
177int	yyerror(char *, ...);
178int	rule_consistent(struct pf_rule *);
179int	nat_consistent(struct pf_nat *);
180int	rdr_consistent(struct pf_rdr *);
181int	yyparse(void);
182void	set_ipmask(struct node_host *, u_int8_t);
183void	expand_rdr(struct pf_rdr *, struct node_if *, struct node_proto *,
184	    struct node_host *, struct node_host *);
185void	expand_nat(struct pf_nat *, struct node_if *, struct node_proto *,
186	    struct node_host *, struct node_port *,
187	    struct node_host *, struct node_port *);
188void	expand_label_if(const char *, char *, const char *);
189void	expand_label_addr(const char *, char *, u_int8_t, struct node_host *);
190void	expand_label_port(const char *, char *, struct node_port *);
191void	expand_label_proto(const char *, char *, u_int8_t);
192void	expand_label_nr(const char *, char *);
193void	expand_label(char *, const char *, u_int8_t, struct node_host *,
194	    struct node_port *, struct node_host *, struct node_port *,
195	    u_int8_t);
196void	expand_rule(struct pf_rule *, struct node_if *, struct node_proto *,
197	    struct node_host *, struct node_port *, struct node_host *,
198	    struct node_port *, struct node_uid *, struct node_gid *,
199	    struct node_icmp *);
200void	expand_altq(struct pf_altq *, struct node_if *, struct node_queue *);
201int	expand_queue(struct pf_altq *, struct node_queue *,
202	    struct node_queue_bw);
203int	check_rulestate(int);
204int	kw_cmp(const void *, const void *);
205int	lookup(char *);
206int	lgetc(FILE *);
207int	lungetc(int, FILE *);
208int	findeol(void);
209int	yylex(void);
210struct	node_host *host(char *, int);
211int	atoul(char *, u_long *);
212int	getservice(char *);
213
214struct sym {
215	struct sym *next;
216	int used;
217	char *nam;
218	char *val;
219};
220struct sym *symhead = NULL;
221
222int	symset(const char *, const char *);
223char *	symget(const char *);
224
225void	ifa_load(void);
226struct	node_host *ifa_exists(char *);
227struct	node_host *ifa_lookup(char *, enum pfctl_iflookup_mode);
228struct	node_host *ifa_pick_ip(struct node_host *, u_int8_t);
229u_int16_t	parseicmpspec(char *, u_int8_t);
230
231typedef struct {
232	union {
233		u_int32_t		number;
234		int			i;
235		char			*string;
236		struct {
237			u_int8_t	b1;
238			u_int8_t	b2;
239			u_int16_t	w;
240			u_int16_t	w2;
241		}			b;
242		struct range {
243			int		a;
244			int		b;
245			int		t;
246		}			range;
247		struct node_if		*interface;
248		struct node_proto	*proto;
249		struct node_icmp	*icmp;
250		struct node_host	*host;
251		struct node_port	*port;
252		struct node_uid		*uid;
253		struct node_gid		*gid;
254		struct node_state_opt	*state_opt;
255		struct peer		peer;
256		struct {
257			struct peer	src, dst;
258		}			fromto;
259		struct {
260			char		*string;
261			struct pf_addr	*addr;
262			u_int8_t	rt;
263			sa_family_t	af;
264		}			route;
265		struct redirection {
266			struct node_host	*address;
267			struct range		 rport;
268		}			*redirection;
269		struct {
270			int			 action;
271			struct node_state_opt	*options;
272		}			keep_state;
273		struct {
274			u_int8_t	log;
275			u_int8_t	quick;
276		}			logquick;
277		struct node_queue	*queue;
278		struct node_queue_opt	queue_options;
279		struct node_queue_bw	queue_bwspec;
280	} v;
281	int lineno;
282} YYSTYPE;
283
284%}
285
286%token	PASS BLOCK SCRUB RETURN IN OUT LOG LOGALL QUICK ON FROM TO FLAGS
287%token	RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
288%token	ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
289%token	MINTTL ERROR ALLOWOPTS FASTROUTE ROUTETO DUPTO REPLYTO NO LABEL
290%token	NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP
291%token	FRAGNORM FRAGDROP FRAGCROP
292%token	SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY
293%token	REQUIREORDER YES
294%token	ANTISPOOF FOR
295%token	ALTQ SCHEDULER CBQ BANDWIDTH TBRSIZE
296%token	QUEUE PRIORITY QLIMIT
297%token	DEFAULT CONTROL BORROW RED ECN RIO
298%token	<v.string> STRING
299%token	<v.i>	PORTUNARY PORTBINARY
300%type	<v.interface>	interface if_list if_item_not if_item
301%type	<v.number>	number port icmptype icmp6type minttl uid gid maxmss
302%type	<v.number>	tos
303%type	<v.i>	no dir log af nodf allowopts fragment fragcache
304%type	<v.b>	action flag flags blockspec
305%type	<v.range>	dport rport
306%type	<v.proto>	proto proto_list proto_item
307%type	<v.icmp>	icmpspec icmp_list icmp6_list icmp_item icmp6_item
308%type	<v.fromto>	fromto
309%type	<v.peer>	ipportspec
310%type	<v.host>	ipspec xhost host address host_list
311%type	<v.port>	portspec port_list port_item
312%type	<v.uid>		uids uid_list uid_item
313%type	<v.gid>		gids gid_list gid_item
314%type	<v.route>	route
315%type	<v.redirection>	redirection
316%type	<v.string>	label string
317%type	<v.keep_state>	keep
318%type	<v.state_opt>	state_opt_spec state_opt_list state_opt_item
319%type	<v.logquick>	logquick
320%type	<v.interface>	antispoof_ifspc antispoof_iflst
321%type	<v.number>	priority qlimit tbrsize
322%type	<v.string>	qname
323%type	<v.queue>	qassign qassign_list qassign_item
324%type	<v.queue_options>	schedtype
325%type	<v.number>	cbqflags_list cbqflags_item
326%type	<v.queue_bwspec>	bandwidth
327%%
328
329ruleset		: /* empty */
330		| ruleset '\n'
331		| ruleset option '\n'
332		| ruleset scrubrule '\n'
333		| ruleset natrule '\n'
334		| ruleset binatrule '\n'
335		| ruleset rdrrule '\n'
336		| ruleset pfrule '\n'
337		| ruleset altqif '\n'
338		| ruleset queuespec '\n'
339		| ruleset varset '\n'
340		| ruleset antispoof '\n'
341		| ruleset error '\n'		{ errors++; }
342		;
343
344option		: SET OPTIMIZATION STRING		{
345			if (pf->opts & PF_OPT_VERBOSE)
346				printf("set optimization %s\n", $3);
347			if (check_rulestate(PFCTL_STATE_OPTION))
348				YYERROR;
349			if (pfctl_set_optimization(pf, $3) != 0) {
350				yyerror("unknown optimization %s", $3);
351				YYERROR;
352			}
353		}
354		| SET TIMEOUT timeout_spec
355		| SET TIMEOUT '{' timeout_list '}'
356		| SET LIMIT limit_spec
357		| SET LIMIT '{' limit_list '}'
358		| SET LOGINTERFACE STRING		{
359			if (pf->opts & PF_OPT_VERBOSE)
360				printf("set loginterface %s\n", $3);
361			if (check_rulestate(PFCTL_STATE_OPTION))
362				YYERROR;
363			if (pfctl_set_logif(pf, $3) != 0) {
364				yyerror("error setting loginterface %s", $3);
365				YYERROR;
366			}
367		}
368		| SET BLOCKPOLICY DROP	{
369			if (pf->opts & PF_OPT_VERBOSE)
370				printf("set block-policy drop\n");
371			if (check_rulestate(PFCTL_STATE_OPTION))
372				YYERROR;
373			blockpolicy = PFRULE_DROP;
374		}
375		| SET BLOCKPOLICY RETURN {
376			if (pf->opts & PF_OPT_VERBOSE)
377				printf("set block-policy return\n");
378			if (check_rulestate(PFCTL_STATE_OPTION))
379				YYERROR;
380			blockpolicy = PFRULE_RETURN;
381		}
382		| SET REQUIREORDER YES {
383			if (pf->opts & PF_OPT_VERBOSE)
384				printf("set require-order yes\n");
385			require_order = 1;
386		}
387		| SET REQUIREORDER NO {
388			if (pf->opts & PF_OPT_VERBOSE)
389				printf("set require-order no\n");
390			require_order = 0;
391		}
392		;
393
394string		: string STRING				{
395			if (asprintf(&$$, "%s %s", $1, $2) == -1) {
396				yyerror("malloc failed");
397				YYERROR;
398			}
399			free($1);
400			free($2);
401		}
402		| STRING
403		;
404
405varset		: STRING PORTUNARY string		{
406			if (pf->opts & PF_OPT_VERBOSE)
407				printf("%s = %s\n", $1, $3);
408			if (symset($1, $3) == -1) {
409				yyerror("cannot store variable %s", $1);
410				YYERROR;
411			}
412		}
413		;
414
415scrubrule	: SCRUB dir interface af fromto nodf minttl maxmss fragcache
416		{
417			struct pf_rule r;
418
419			if (check_rulestate(PFCTL_STATE_SCRUB))
420				YYERROR;
421
422			memset(&r, 0, sizeof(r));
423
424			r.action = PF_SCRUB;
425			r.direction = $2;
426
427			if ($3) {
428				if ($3->not) {
429					yyerror("scrub rules don't support "
430					    "'! <if>'");
431					YYERROR;
432				}
433			}
434			r.af = $4;
435			if ($6)
436				r.rule_flag |= PFRULE_NODF;
437			if ($7)
438				r.min_ttl = $7;
439			if ($8)
440				r.max_mss = $8;
441			if ($9)
442				r.rule_flag |= $9;
443
444			expand_rule(&r, $3, NULL, $5.src.host, $5.src.port,
445			    $5.dst.host, $5.dst.port, NULL, NULL, NULL);
446		}
447		;
448
449antispoof	: ANTISPOOF logquick antispoof_ifspc af {
450			struct pf_rule r;
451			struct node_host *h = NULL;
452			struct node_if *i, *j;
453
454			if (check_rulestate(PFCTL_STATE_FILTER))
455				YYERROR;
456
457			for (i = $3; i; i = i->next) {
458				memset(&r, 0, sizeof(r));
459
460				r.action = PF_DROP;
461				r.direction = PF_IN;
462				r.log = $2.log;
463				r.quick = $2.quick;
464				r.af = $4;
465
466				j = calloc(1, sizeof(struct node_if));
467				if (j == NULL)
468					errx(1, "antispoof: calloc");
469				strlcpy(j->ifname, i->ifname, IFNAMSIZ);
470				j->not = 1;
471				h = ifa_lookup(j->ifname, PFCTL_IFLOOKUP_NET);
472
473				expand_rule(&r, j, NULL, h, NULL, NULL, NULL,
474				    NULL, NULL, NULL);
475
476				if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
477					memset(&r, 0, sizeof(r));
478
479					r.action = PF_DROP;
480					r.direction = PF_IN;
481					r.log = $2.log;
482					r.quick = $2.quick;
483					r.af = $4;
484
485					h = ifa_lookup(i->ifname,
486					    PFCTL_IFLOOKUP_HOST);
487
488					expand_rule(&r, NULL, NULL, h, NULL,
489					    NULL, NULL, NULL, NULL, NULL);
490				}
491			}
492		}
493		;
494
495antispoof_ifspc	: FOR if_item			{ $$ = $2; }
496		| FOR '{' antispoof_iflst '}'	{ $$ = $3; }
497		;
498
499antispoof_iflst	: if_item			{ $$ = $1; }
500		| antispoof_iflst comma if_item	{
501			$1->tail->next = $3;
502			$1->tail = $3;
503			$$ = $1;
504		}
505		;
506
507
508/* altq stuff */
509
510altqif		: ALTQ interface SCHEDULER schedtype bandwidth tbrsize
511		  qassign	{
512			struct	pf_altq a;
513
514			memset(&a, 0, sizeof(a));
515			if ($4.qtype == ALTQT_NONE) {
516				yyerror("no scheduler specified!");
517				YYERROR;
518			}
519			a.scheduler = $4.qtype;
520			a.pq_u.cbq_opts.flags = $4.data.cbq_opts.flags;
521			if ((a.ifbandwidth = $5.bw_absolute) == 0) {
522				yyerror("interface bandwidth must be absolute");
523				YYERROR;
524			}
525			a.tbrsize = $6;
526			expand_altq(&a,	$2, $7);
527		}
528		;
529
530qassign		: /* empty */			{ $$ = NULL; }
531		| QUEUE qassign_item		{ $$ = $2; }
532		| QUEUE '{' qassign_list '}'	{ $$ = $3; }
533		;
534
535qassign_list	: qassign_item			{ $$ = $1; }
536		| qassign_list comma qassign_item	{
537			$1->tail->next = $3;
538			$1->tail = $3;
539			$$ = $1;
540		}
541		;
542
543qassign_item	: STRING			{
544			$$ = malloc(sizeof(struct node_queue));
545			if ($$ == NULL)
546				err(1, "queue_item: malloc");
547			strlcpy($$->queue, $1, PF_QNAME_SIZE);
548			$$->next = NULL;
549			$$->tail = $$;
550		}
551		;
552
553queuespec	: QUEUE STRING bandwidth priority qlimit schedtype qassign {
554			struct	pf_altq a;
555
556			memset(&a, 0, sizeof(a));
557
558			if (strlcpy(a.qname, $2, sizeof(a.qname)) >=
559			    PF_QNAME_SIZE) {
560				yyerror("queue name too long (max "
561				    "%d chars)", PF_QNAME_SIZE-1);
562				YYERROR;
563			}
564			if ($4 > 255) {
565				yyerror("priority out of range: max 255");
566				YYERROR;
567			}
568			a.priority = $4;
569			a.qlimit = $5;
570			a.scheduler = $6.qtype;
571			a.pq_u.cbq_opts.flags = $6.data.cbq_opts.flags;
572			if (expand_queue(&a, $7, $3))
573				YYERROR;
574
575		}
576		;
577
578schedtype	: /* empty */			{ $$.qtype = ALTQT_NONE; }
579		| CBQ				{ $$.qtype = ALTQT_CBQ; }
580		| CBQ '(' cbqflags_list ')'	{
581			$$.qtype = ALTQT_CBQ;
582			$$.data.cbq_opts.flags = $3;
583		}
584		;
585
586cbqflags_list	: cbqflags_item				{ $$ |= $1; }
587		| cbqflags_list comma cbqflags_item	{ $$ |= $3; }
588		;
589
590
591cbqflags_item	: DEFAULT	{ $$ = CBQCLF_DEFCLASS; }
592		| CONTROL	{ $$ = CBQCLF_CTLCLASS; }
593		| BORROW	{ $$ = CBQCLF_BORROW; }
594		| RED		{ $$ = CBQCLF_RED; }
595		| ECN		{ $$ = CBQCLF_RED|CBQCLF_ECN; }
596		| RIO		{ $$ = CBQCLF_RIO; }
597		;
598
599bandwidth	: /* empty */		{
600			$$.bw_absolute = 0;
601			$$.bw_percent = 0;
602		}
603		| BANDWIDTH STRING {
604			double bps;
605			char *cp;
606
607			$$.bw_percent = 0;
608
609			bps = strtod($2, &cp);
610			if (cp != NULL) {
611				if (!strcmp(cp, "b")) {
612					/* nothing */
613				} else if (!strcmp(cp, "Kb"))
614					bps *= 1024;
615				else if (!strcmp(cp, "Mb"))
616					bps *= 1024 * 1024;
617				else if (!strcasecmp(cp, "Gb"))
618					bps *= 1024 * 1024 * 1024;
619				else if (*cp == '%') {
620					if (bps < 0 || bps > 100) {
621						yyerror("bandwidth spec "
622						    "out of range");
623						YYERROR;
624					}
625					$$.bw_percent = bps;
626					bps = 0;
627				} else {
628					yyerror("unknown unit %s", cp);
629					YYERROR;
630				}
631			}
632			$$.bw_absolute = (u_int32_t)bps;
633		}
634		;
635
636priority	: /* empty */		{ $$ = 0; }
637		| PRIORITY number	{
638			if ($2 > 255) {
639				yyerror("priority out of range: max 255");
640				YYERROR;
641			}
642			$$ = $2;
643		}
644		;
645
646qlimit		: /* empty */		{ $$ = 0; }
647		| QLIMIT number		{
648			if ($2 > 65535) {
649				yyerror("qlimit out of range: max 65535");
650				YYERROR;
651			}
652			$$ = $2;
653		}
654		;
655
656
657tbrsize		: /* empty */		{ $$ = 0; }
658		| number		{
659			if ($1 > 65535) {
660				yyerror("tbrsize too big: max 65535");
661				YYERROR;
662			}
663			$$ = $1;
664		}
665		;
666
667pfrule		: action dir logquick interface route af proto fromto
668		  uids gids flags icmpspec tos keep fragment allowopts label
669		  qname
670		{
671			struct pf_rule r;
672			struct node_state_opt *o;
673			struct node_proto *proto;
674
675			if (check_rulestate(PFCTL_STATE_FILTER))
676				YYERROR;
677
678			memset(&r, 0, sizeof(r));
679
680			r.action = $1.b1;
681			switch ($1.b2) {
682			case PFRULE_RETURNRST:
683				r.rule_flag |= PFRULE_RETURNRST;
684				r.return_ttl = $1.w;
685				break;
686			case PFRULE_RETURNICMP:
687				r.rule_flag |= PFRULE_RETURNICMP;
688				r.return_icmp = $1.w;
689				r.return_icmp6 = $1.w2;
690				break;
691			case PFRULE_RETURN:
692				r.rule_flag |= PFRULE_RETURN;
693				r.return_icmp = $1.w;
694				r.return_icmp6 = $1.w2;
695				break;
696			}
697			r.direction = $2;
698			r.log = $3.log;
699			r.quick = $3.quick;
700
701			r.af = $6;
702			r.flags = $11.b1;
703			r.flagset = $11.b2;
704
705			if ($11.b1 || $11.b2) {
706				for (proto = $7; proto != NULL &&
707				    proto->proto != IPPROTO_TCP;
708				    proto = proto->next)
709					;	/* nothing */
710				if (proto == NULL && $7 != NULL) {
711					yyerror("flags only apply to tcp");
712					YYERROR;
713				}
714			}
715
716			r.tos = $13;
717			r.keep_state = $14.action;
718			o = $14.options;
719			while (o) {
720				struct node_state_opt *p = o;
721
722				switch (o->type) {
723				case PF_STATE_OPT_MAX:
724					if (r.max_states) {
725						yyerror("state option 'max' "
726						    "multiple definitions");
727						YYERROR;
728					}
729					r.max_states = o->data.max_states;
730					break;
731				case PF_STATE_OPT_TIMEOUT:
732					if (r.timeout[o->data.timeout.number]) {
733						yyerror("state timeout %s "
734						    "multiple definitions",
735						    pf_timeouts[o->data.
736						    timeout.number].name);
737						YYERROR;
738					}
739					r.timeout[o->data.timeout.number] =
740					    o->data.timeout.seconds;
741				}
742				o = o->next;
743				free(p);
744			}
745
746			if ($15)
747				r.rule_flag |= PFRULE_FRAGMENT;
748			r.allow_opts = $16;
749
750			if ($5.rt) {
751				r.rt = $5.rt;
752				if ($5.string) {
753					strlcpy(r.rt_ifname, $5.string,
754					    IFNAMSIZ);
755					if (ifa_exists(r.rt_ifname) == NULL) {
756						yyerror("unknown interface %s",
757						    r.rt_ifname);
758						YYERROR;
759					}
760					free($5.string);
761				}
762				if ($5.addr) {
763					if (!r.af)
764						r.af = $5.af;
765					else if (r.af != $5.af) {
766						yyerror("address family"
767						    " mismatch");
768						YYERROR;
769					}
770					memcpy(&r.rt_addr, $5.addr,
771					    sizeof(r.rt_addr));
772					free($5.addr);
773				}
774			}
775
776			if ($17) {
777				if (strlcpy(r.label, $17, sizeof(r.label)) >=
778				    PF_RULE_LABEL_SIZE) {
779					yyerror("rule label too long (max "
780					    "%d chars)", PF_RULE_LABEL_SIZE-1);
781					YYERROR;
782				}
783				free($17);
784			}
785
786			if ($18) {
787				if (strlcpy(r.qname, $18, sizeof(r.qname)) >=
788				    PF_QNAME_SIZE) {
789					yyerror("rule qname too long (max "
790					    "%d chars)", PF_QNAME_SIZE-1);
791					YYERROR;
792				}
793				free($18);
794			}
795
796			expand_rule(&r, $4, $7, $8.src.host, $8.src.port,
797			    $8.dst.host, $8.dst.port, $9, $10, $12);
798		}
799		;
800
801action		: PASS			{ $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
802		| BLOCK blockspec	{ $$ = $2; $$.b1 = PF_DROP; }
803		;
804
805blockspec	: /* empty */		{
806			$$.b2 = blockpolicy;
807			$$.w = returnicmpdefault;
808			$$.w2 = returnicmp6default;
809		}
810		| DROP			{
811			$$.b2 = PFRULE_DROP;
812			$$.w = 0;
813			$$.w2 = 0;
814		}
815		| RETURNRST		{
816			$$.b2 = PFRULE_RETURNRST;
817			$$.w = 0;
818			$$.w2 = 0;
819		}
820		| RETURNRST '(' TTL number ')'	{
821			$$.b2 = PFRULE_RETURNRST;
822			$$.w = $4;
823			$$.w2 = 0;
824		}
825		| RETURNICMP		{
826			$$.b2 = PFRULE_RETURNICMP;
827			$$.w = returnicmpdefault;
828			$$.w2 = returnicmp6default;
829		}
830		| RETURNICMP6		{
831			$$.b2 = PFRULE_RETURNICMP;
832			$$.w = returnicmpdefault;
833			$$.w2 = returnicmp6default;
834		}
835		| RETURNICMP '(' STRING ')'	{
836			$$.b2 = PFRULE_RETURNICMP;
837			if (!($$.w = parseicmpspec($3, AF_INET)))
838				YYERROR;
839			$$.w2 = returnicmp6default;
840		}
841		| RETURNICMP6 '(' STRING ')'	{
842			$$.b2 = PFRULE_RETURNICMP;
843			$$.w = returnicmpdefault;
844			if (!($$.w2 = parseicmpspec($3, AF_INET6)))
845				YYERROR;
846		}
847		| RETURNICMP '(' STRING comma STRING ')' {
848			$$.b2 = PFRULE_RETURNICMP;
849			if (!($$.w = parseicmpspec($3, AF_INET)))
850				YYERROR;
851			if (!($$.w2 = parseicmpspec($5, AF_INET6)));
852		}
853		| RETURN {
854			$$.b2 = PFRULE_RETURN;
855			$$.w = returnicmpdefault;
856			$$.w2 = returnicmp6default;
857		}
858		;
859
860fragcache	: /* empty */		{ $$ = 0; }
861		| fragment FRAGNORM	{ $$ = 0; /* default */ }
862		| fragment FRAGCROP	{ $$ = PFRULE_FRAGCROP; }
863		| fragment FRAGDROP	{ $$ = PFRULE_FRAGDROP; }
864		;
865
866
867dir		: IN				{ $$ = PF_IN; }
868		| OUT				{ $$ = PF_OUT; }
869		;
870
871logquick	: /* empty */			{ $$.log = 0; $$.quick = 0; }
872		| log				{ $$.log = $1; $$.quick = 0; }
873		| QUICK				{ $$.log = 0; $$.quick = 1; }
874		| log QUICK			{ $$.log = $1; $$.quick = 1; }
875		| QUICK log			{ $$.log = $2; $$.quick = 1; }
876		;
877
878log		: LOG				{ $$ = 1; }
879		| LOGALL			{ $$ = 2; }
880		;
881
882interface	: /* empty */			{ $$ = NULL; }
883		| ON if_item_not		{ $$ = $2; }
884		| ON '{' if_list '}'		{ $$ = $3; }
885		;
886
887if_list		: if_item_not			{ $$ = $1; }
888		| if_list comma if_item_not	{
889			$1->tail->next = $3;
890			$1->tail = $3;
891			$$ = $1;
892		}
893		;
894
895if_item_not	: '!' if_item			{ $$ = $2; $$->not = 1; }
896		| if_item			{ $$ = $1; }
897
898if_item		: STRING			{
899			struct node_host *n;
900
901			if ((n = ifa_exists($1)) == NULL) {
902				yyerror("unknown interface %s", $1);
903				YYERROR;
904			}
905			$$ = malloc(sizeof(struct node_if));
906			if ($$ == NULL)
907				err(1, "if_item: malloc");
908			strlcpy($$->ifname, $1, IFNAMSIZ);
909			$$->ifa_flags = n->ifa_flags;
910			$$->not = 0;
911			$$->next = NULL;
912			$$->tail = $$;
913		}
914		;
915
916af		: /* empty */			{ $$ = 0; }
917		| INET				{ $$ = AF_INET; }
918		| INET6				{ $$ = AF_INET6; }
919
920proto		: /* empty */			{ $$ = NULL; }
921		| PROTO proto_item		{ $$ = $2; }
922		| PROTO '{' proto_list '}'	{ $$ = $3; }
923		;
924
925proto_list	: proto_item			{ $$ = $1; }
926		| proto_list comma proto_item	{
927			$1->tail->next = $3;
928			$1->tail = $3;
929			$$ = $1;
930		}
931		;
932
933proto_item	: STRING			{
934			u_int8_t pr;
935			u_long ulval;
936
937			if (atoul($1, &ulval) == 0) {
938				if (ulval > 255) {
939					yyerror("protocol outside range");
940					YYERROR;
941				}
942				pr = (u_int8_t)ulval;
943			} else {
944				struct protoent *p;
945
946				p = getprotobyname($1);
947				if (p == NULL) {
948					yyerror("unknown protocol %s", $1);
949					YYERROR;
950				}
951				pr = p->p_proto;
952			}
953			if (pr == 0) {
954				yyerror("proto 0 cannot be used");
955				YYERROR;
956			}
957			$$ = malloc(sizeof(struct node_proto));
958			if ($$ == NULL)
959				err(1, "proto_item: malloc");
960			$$->proto = pr;
961			$$->next = NULL;
962			$$->tail = $$;
963		}
964		;
965
966fromto		: ALL				{
967			$$.src.host = NULL;
968			$$.src.port = NULL;
969			$$.dst.host = NULL;
970			$$.dst.port = NULL;
971		}
972		| FROM ipportspec TO ipportspec	{
973			$$.src = $2;
974			$$.dst = $4;
975		}
976		;
977
978ipportspec	: ipspec			{ $$.host = $1; $$.port = NULL; }
979		| ipspec PORT portspec		{
980			$$.host = $1;
981			$$.port = $3;
982		}
983		;
984
985ipspec		: ANY				{ $$ = NULL; }
986		| xhost				{ $$ = $1; }
987		| '{' host_list '}'		{ $$ = $2; }
988		;
989
990host_list	: xhost				{ $$ = $1; }
991		| host_list comma xhost		{
992			/* $3 may be a list, so use its tail pointer */
993			$1->tail->next = $3->tail;
994			$1->tail = $3->tail;
995			$$ = $1;
996		}
997		;
998
999xhost		: '!' host			{
1000			struct node_host *h;
1001			for (h = $2; h; h = h->next)
1002				h->not = 1;
1003			$$ = $2;
1004		}
1005		| host				{ $$ = $1; }
1006		| NOROUTE			{
1007			$$ = calloc(1, sizeof(struct node_host));
1008			if ($$ == NULL)
1009				err(1, "xhost: calloc");
1010			$$->noroute = 1;
1011			$$->next = NULL;
1012			$$->tail = $$;
1013		}
1014		;
1015
1016host		: address
1017		| STRING '/' number		{ $$ = host($1, $3); }
1018		;
1019
1020number		: STRING			{
1021			u_long ulval;
1022
1023			if (atoul($1, &ulval) == -1) {
1024				yyerror("%s is not a number", $1);
1025				YYERROR;
1026			} else
1027				$$ = ulval;
1028		}
1029		;
1030
1031address		: '(' STRING ')'		{
1032			$$ = calloc(1, sizeof(struct node_host));
1033			if ($$ == NULL)
1034				err(1, "address: calloc");
1035			$$->af = 0;
1036			set_ipmask($$, 128);
1037			$$->addr.addr_dyn = (struct pf_addr_dyn *)1;
1038			strncpy($$->addr.addr.pfa.ifname, $2,
1039			    sizeof($$->addr.addr.pfa.ifname));
1040			$$->next = NULL;
1041			$$->tail = $$;
1042		}
1043		| STRING			{ $$ = host($1, -1); }
1044		;
1045
1046portspec	: port_item			{ $$ = $1; }
1047		| '{' port_list '}'		{ $$ = $2; }
1048		;
1049
1050port_list	: port_item			{ $$ = $1; }
1051		| port_list comma port_item	{
1052			$1->tail->next = $3;
1053			$1->tail = $3;
1054			$$ = $1;
1055		}
1056		;
1057
1058port_item	: port				{
1059			$$ = malloc(sizeof(struct node_port));
1060			if ($$ == NULL)
1061				err(1, "port_item: malloc");
1062			$$->port[0] = $1;
1063			$$->port[1] = $1;
1064			$$->op = PF_OP_EQ;
1065			$$->next = NULL;
1066			$$->tail = $$;
1067		}
1068		| PORTUNARY port		{
1069			$$ = malloc(sizeof(struct node_port));
1070			if ($$ == NULL)
1071				err(1, "port_item: malloc");
1072			$$->port[0] = $2;
1073			$$->port[1] = $2;
1074			$$->op = $1;
1075			$$->next = NULL;
1076			$$->tail = $$;
1077		}
1078		| port PORTBINARY port		{
1079			$$ = malloc(sizeof(struct node_port));
1080			if ($$ == NULL)
1081				err(1, "port_item: malloc");
1082			$$->port[0] = $1;
1083			$$->port[1] = $3;
1084			$$->op = $2;
1085			$$->next = NULL;
1086			$$->tail = $$;
1087		}
1088		;
1089
1090port		: STRING			{
1091			struct servent *s = NULL;
1092			u_long ulval;
1093
1094			if (atoul($1, &ulval) == 0) {
1095				if (ulval > 65535) {
1096					yyerror("illegal port value %d", ulval);
1097					YYERROR;
1098				}
1099				$$ = htons(ulval);
1100			} else {
1101				s = getservbyname($1, "tcp");
1102				if (s == NULL)
1103					s = getservbyname($1, "udp");
1104				if (s == NULL) {
1105					yyerror("unknown port %s", $1);
1106					YYERROR;
1107				}
1108				$$ = s->s_port;
1109			}
1110		}
1111		;
1112
1113uids		: /* empty */			{ $$ = NULL; }
1114		| USER uid_item			{ $$ = $2; }
1115		| USER '{' uid_list '}'		{ $$ = $3; }
1116		;
1117
1118uid_list	: uid_item			{ $$ = $1; }
1119		| uid_list comma uid_item	{
1120			$1->tail->next = $3;
1121			$1->tail = $3;
1122			$$ = $1;
1123		}
1124		;
1125
1126uid_item	: uid				{
1127			$$ = malloc(sizeof(struct node_uid));
1128			if ($$ == NULL)
1129				err(1, "uid_item: malloc");
1130			$$->uid[0] = $1;
1131			$$->uid[1] = $1;
1132			$$->op = PF_OP_EQ;
1133			$$->next = NULL;
1134			$$->tail = $$;
1135		}
1136		| PORTUNARY uid			{
1137			if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
1138				yyerror("user unknown requires operator = or !=");
1139				YYERROR;
1140			}
1141			$$ = malloc(sizeof(struct node_uid));
1142			if ($$ == NULL)
1143				err(1, "uid_item: malloc");
1144			$$->uid[0] = $2;
1145			$$->uid[1] = $2;
1146			$$->op = $1;
1147			$$->next = NULL;
1148			$$->tail = $$;
1149		}
1150		| uid PORTBINARY uid		{
1151			if ($1 == UID_MAX || $3 == UID_MAX) {
1152				yyerror("user unknown requires operator = or !=");
1153				YYERROR;
1154			}
1155			$$ = malloc(sizeof(struct node_uid));
1156			if ($$ == NULL)
1157				err(1, "uid_item: malloc");
1158			$$->uid[0] = $1;
1159			$$->uid[1] = $3;
1160			$$->op = $2;
1161			$$->next = NULL;
1162			$$->tail = $$;
1163		}
1164		;
1165
1166uid		: STRING			{
1167			u_long ulval;
1168
1169			if (atoul($1, &ulval) == -1) {
1170				if (!strcmp($1, "unknown"))
1171					$$ = UID_MAX;
1172				else {
1173					struct passwd *pw;
1174
1175					if ((pw = getpwnam($1)) == NULL) {
1176						yyerror("unknown user %s", $1);
1177						YYERROR;
1178					}
1179					$$ = pw->pw_uid;
1180				}
1181			} else {
1182				if (ulval >= UID_MAX) {
1183					yyerror("illegal uid value %lu", ulval);
1184					YYERROR;
1185				}
1186				$$ = ulval;
1187			}
1188		}
1189		;
1190
1191gids		: /* empty */			{ $$ = NULL; }
1192		| GROUP gid_item		{ $$ = $2; }
1193		| GROUP '{' gid_list '}'	{ $$ = $3; }
1194		;
1195
1196gid_list	: gid_item			{ $$ = $1; }
1197		| gid_list comma gid_item	{
1198			$1->tail->next = $3;
1199			$1->tail = $3;
1200			$$ = $1;
1201		}
1202		;
1203
1204gid_item	: gid				{
1205			$$ = malloc(sizeof(struct node_gid));
1206			if ($$ == NULL)
1207				err(1, "gid_item: malloc");
1208			$$->gid[0] = $1;
1209			$$->gid[1] = $1;
1210			$$->op = PF_OP_EQ;
1211			$$->next = NULL;
1212			$$->tail = $$;
1213		}
1214		| PORTUNARY gid			{
1215			if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
1216				yyerror("group unknown requires operator = or !=");
1217				YYERROR;
1218			}
1219			$$ = malloc(sizeof(struct node_gid));
1220			if ($$ == NULL)
1221				err(1, "gid_item: malloc");
1222			$$->gid[0] = $2;
1223			$$->gid[1] = $2;
1224			$$->op = $1;
1225			$$->next = NULL;
1226			$$->tail = $$;
1227		}
1228		| gid PORTBINARY gid		{
1229			if ($1 == GID_MAX || $3 == GID_MAX) {
1230				yyerror("group unknown requires operator = or !=");
1231				YYERROR;
1232			}
1233			$$ = malloc(sizeof(struct node_gid));
1234			if ($$ == NULL)
1235				err(1, "gid_item: malloc");
1236			$$->gid[0] = $1;
1237			$$->gid[1] = $3;
1238			$$->op = $2;
1239			$$->next = NULL;
1240			$$->tail = $$;
1241		}
1242		;
1243
1244gid		: STRING			{
1245			u_long ulval;
1246
1247			if (atoul($1, &ulval) == -1) {
1248				if (!strcmp($1, "unknown"))
1249					$$ = GID_MAX;
1250				else {
1251					struct group *grp;
1252
1253					if ((grp = getgrnam($1)) == NULL) {
1254						yyerror("unknown group %s", $1);
1255						YYERROR;
1256					}
1257					$$ = grp->gr_gid;
1258				}
1259			} else {
1260				if (ulval >= GID_MAX) {
1261					yyerror("illegal gid value %lu", ulval);
1262					YYERROR;
1263				}
1264				$$ = ulval;
1265			}
1266		}
1267		;
1268
1269flag		: STRING			{
1270			int f;
1271
1272			if ((f = parse_flags($1)) < 0) {
1273				yyerror("bad flags %s", $1);
1274				YYERROR;
1275			}
1276			$$.b1 = f;
1277		}
1278		;
1279
1280flags		: /* empty */			{ $$.b1 = 0; $$.b2 = 0; }
1281		| FLAGS flag "/" flag		{ $$.b1 = $2.b1; $$.b2 = $4.b1; }
1282		| FLAGS "/" flag		{ $$.b1 = 0; $$.b2 = $3.b1; }
1283		;
1284
1285icmpspec	: /* empty */			{ $$ = NULL; }
1286		| ICMPTYPE icmp_item		{ $$ = $2; }
1287		| ICMPTYPE '{' icmp_list '}'	{ $$ = $3; }
1288		| ICMP6TYPE icmp6_item		{ $$ = $2; }
1289		| ICMP6TYPE '{' icmp6_list '}'	{ $$ = $3; }
1290		;
1291
1292icmp_list	: icmp_item			{ $$ = $1; }
1293		| icmp_list comma icmp_item	{
1294			$1->tail->next = $3;
1295			$1->tail = $3;
1296			$$ = $1;
1297		}
1298		;
1299
1300icmp6_list	: icmp6_item			{ $$ = $1; }
1301		| icmp6_list comma icmp6_item	{
1302			$1->tail->next = $3;
1303			$1->tail = $3;
1304			$$ = $1;
1305		}
1306		;
1307
1308icmp_item	: icmptype		{
1309			$$ = malloc(sizeof(struct node_icmp));
1310			if ($$ == NULL)
1311				err(1, "icmp_item: malloc");
1312			$$->type = $1;
1313			$$->code = 0;
1314			$$->proto = IPPROTO_ICMP;
1315			$$->next = NULL;
1316			$$->tail = $$;
1317		}
1318		| icmptype CODE STRING	{
1319			const struct icmpcodeent *p;
1320			u_long ulval;
1321
1322			if (atoul($3, &ulval) == 0) {
1323				if (ulval > 255) {
1324					yyerror("illegal icmp-code %d", ulval);
1325					YYERROR;
1326				}
1327			} else {
1328				if ((p = geticmpcodebyname($1-1, $3,
1329				    AF_INET)) == NULL) {
1330					yyerror("unknown icmp-code %s", $3);
1331					YYERROR;
1332				}
1333				ulval = p->code;
1334			}
1335			$$ = malloc(sizeof(struct node_icmp));
1336			if ($$ == NULL)
1337				err(1, "icmp_item: malloc");
1338			$$->type = $1;
1339			$$->code = ulval + 1;
1340			$$->proto = IPPROTO_ICMP;
1341			$$->next = NULL;
1342			$$->tail = $$;
1343		}
1344		;
1345
1346icmp6_item	: icmp6type		{
1347			$$ = malloc(sizeof(struct node_icmp));
1348			if ($$ == NULL)
1349				err(1, "icmp_item: malloc");
1350			$$->type = $1;
1351			$$->code = 0;
1352			$$->proto = IPPROTO_ICMPV6;
1353			$$->next = NULL;
1354			$$->tail = $$;
1355		}
1356		| icmp6type CODE STRING	{
1357			const struct icmpcodeent *p;
1358			u_long ulval;
1359
1360			if (atoul($3, &ulval) == 0) {
1361				if (ulval > 255) {
1362					yyerror("illegal icmp6-code %ld", ulval);
1363					YYERROR;
1364				}
1365			} else {
1366				if ((p = geticmpcodebyname($1-1, $3,
1367				    AF_INET6)) == NULL) {
1368					yyerror("unknown icmp6-code %s", $3);
1369					YYERROR;
1370				}
1371				ulval = p->code;
1372			}
1373			$$ = malloc(sizeof(struct node_icmp));
1374			if ($$ == NULL)
1375				err(1, "icmp_item: malloc");
1376			$$->type = $1;
1377			$$->code = ulval + 1;
1378			$$->proto = IPPROTO_ICMPV6;
1379			$$->next = NULL;
1380			$$->tail = $$;
1381		}
1382		;
1383
1384icmptype	: STRING			{
1385			const struct icmptypeent *p;
1386			u_long ulval;
1387
1388			if (atoul($1, &ulval) == 0) {
1389				if (ulval > 255) {
1390					yyerror("illegal icmp-type %d", ulval);
1391					YYERROR;
1392				}
1393				$$ = ulval + 1;
1394			} else {
1395				if ((p = geticmptypebyname($1, AF_INET)) == NULL) {
1396					yyerror("unknown icmp-type %s", $1);
1397					YYERROR;
1398				}
1399				$$ = p->type + 1;
1400			}
1401		}
1402		;
1403
1404icmp6type	: STRING			{
1405			const struct icmptypeent *p;
1406			u_long ulval;
1407
1408			if (atoul($1, &ulval) == 0) {
1409				if (ulval > 255) {
1410					yyerror("illegal icmp6-type %d", ulval);
1411					YYERROR;
1412				}
1413				$$ = ulval + 1;
1414			} else {
1415				if ((p = geticmptypebyname($1, AF_INET6)) == NULL) {
1416					yyerror("unknown ipv6-icmp-type %s", $1);
1417					YYERROR;
1418				}
1419				$$ = p->type + 1;
1420			}
1421		}
1422		;
1423
1424tos		: /* empty */			{ $$ = 0; }
1425		| TOS STRING			{
1426			if (!strcmp($2, "lowdelay"))
1427				$$ = IPTOS_LOWDELAY;
1428			else if (!strcmp($2, "throughput"))
1429				$$ = IPTOS_THROUGHPUT;
1430			else if (!strcmp($2, "reliability"))
1431				$$ = IPTOS_RELIABILITY;
1432			else if ($2[0] == '0' && $2[1] == 'x')
1433				$$ = strtoul($2, NULL, 16);
1434			else
1435				$$ = strtoul($2, NULL, 10);
1436			if (!$$ || $$ > 255) {
1437				yyerror("illegal tos value %s", $2);
1438				YYERROR;
1439			}
1440		}
1441		;
1442
1443keep		: /* empty */			{
1444			$$.action = 0;
1445			$$.options = NULL;
1446		}
1447		| KEEP STATE state_opt_spec	{
1448			$$.action = PF_STATE_NORMAL;
1449			$$.options = $3;
1450		}
1451		| MODULATE STATE state_opt_spec	{
1452			$$.action = PF_STATE_MODULATE;
1453			$$.options = $3;
1454		}
1455		;
1456
1457state_opt_spec	: /* empty */			{ $$ = NULL; }
1458		| '(' state_opt_list ')'	{ $$ = $2; }
1459		;
1460
1461state_opt_list	: state_opt_item		{ $$ = $1; }
1462		| state_opt_list comma state_opt_item {
1463			$1->tail->next = $3;
1464			$1->tail = $3;
1465			$$ = $1;
1466		}
1467		;
1468
1469state_opt_item	: MAXIMUM number		{
1470			if ($2 <= 0) {
1471				yyerror("illegal states max value %d", $2);
1472				YYERROR;
1473			}
1474			$$ = calloc(1, sizeof(struct node_state_opt));
1475			if ($$ == NULL)
1476				err(1, "state_opt_item: calloc");
1477			$$->type = PF_STATE_OPT_MAX;
1478			$$->data.max_states = $2;
1479			$$->next = NULL;
1480			$$->tail = $$;
1481		}
1482		| STRING number			{
1483			int i;
1484
1485			for (i = 0; pf_timeouts[i].name &&
1486			    strcmp(pf_timeouts[i].name, $1); ++i)
1487				;	/* nothing */
1488			if (!pf_timeouts[i].name) {
1489				yyerror("illegal timeout name %s", $1);
1490				YYERROR;
1491			}
1492			if (strchr(pf_timeouts[i].name, '.') == NULL) {
1493				yyerror("illegal state timeout %s", $1);
1494				YYERROR;
1495			}
1496			$$ = calloc(1, sizeof(struct node_state_opt));
1497			if ($$ == NULL)
1498				err(1, "state_opt_item: calloc");
1499			$$->type = PF_STATE_OPT_TIMEOUT;
1500			$$->data.timeout.number = pf_timeouts[i].timeout;
1501			$$->data.timeout.seconds = $2;
1502			$$->next = NULL;
1503			$$->tail = $$;
1504		}
1505		;
1506
1507fragment	: /* empty */			{ $$ = 0; }
1508		| FRAGMENT			{ $$ = 1; }
1509
1510minttl		: /* empty */			{ $$ = 0; }
1511		| MINTTL number			{
1512			if ($2 > 255) {
1513				yyerror("illegal min-ttl value %d", $2);
1514				YYERROR;
1515			}
1516			$$ = $2;
1517		}
1518		;
1519
1520nodf		: /* empty */			{ $$ = 0; }
1521		| NODF				{ $$ = 1; }
1522		;
1523
1524maxmss		: /* empty */			{ $$ = 0; }
1525		| MAXMSS number			{ $$ = $2; }
1526		;
1527
1528allowopts	: /* empty */			{ $$ = 0; }
1529		| ALLOWOPTS			{ $$ = 1; }
1530
1531label		: /* empty */			{ $$ = NULL; }
1532		| LABEL STRING			{
1533			if (($$ = strdup($2)) == NULL) {
1534				yyerror("rule label strdup() failed");
1535				YYERROR;
1536			}
1537		}
1538		;
1539qname		: /* empty */			{ $$ = NULL; }
1540		| QUEUE STRING			{
1541			if (($$ = strdup($2)) == NULL) {
1542				yyerror("qname strdup() failed");
1543				YYERROR;
1544			}
1545		}
1546		;
1547
1548no		: /* empty */			{ $$ = 0; }
1549		| NO				{ $$ = 1; }
1550		;
1551
1552rport		: STRING			{
1553			char *p = strchr($1, ':');
1554
1555			if (p == NULL) {
1556				if (($$.a = getservice($1)) == -1)
1557					YYERROR;
1558				$$.b = $$.t = 0;
1559			} else if (!strcmp(p+1, "*")) {
1560				*p = 0;
1561				if (($$.a = getservice($1)) == -1)
1562					YYERROR;
1563				$$.b = 0;
1564				$$.t = PF_RPORT_RANGE;
1565			} else {
1566				*p++ = 0;
1567				if (($$.a = getservice($1)) == -1 ||
1568				    ($$.b = getservice(p)) == -1)
1569					YYERROR;
1570				$$.t = PF_RPORT_RANGE;
1571			}
1572		}
1573		;
1574
1575redirection	: /* empty */			{ $$ = NULL; }
1576		| ARROW host			{
1577			$$ = malloc(sizeof(struct redirection));
1578			if ($$ == NULL)
1579				err(1, "redirection: malloc");
1580			$$->address = $2;
1581			$$->rport.a = $$->rport.b = $$->rport.t = 0;
1582		}
1583		| ARROW host PORT rport	{
1584			$$ = malloc(sizeof(struct redirection));
1585			if ($$ == NULL)
1586				err(1, "redirection: malloc");
1587			$$->address = $2;
1588			$$->rport = $4;
1589		}
1590		;
1591
1592natrule		: no NAT interface af proto fromto redirection
1593		{
1594			struct pf_nat nat;
1595
1596			if (check_rulestate(PFCTL_STATE_NAT))
1597				YYERROR;
1598
1599			memset(&nat, 0, sizeof(nat));
1600
1601			nat.no = $1;
1602			nat.af = $4;
1603
1604			if (!nat.af) {
1605				if ($6.src.host && $6.src.host->af &&
1606				    !$6.src.host->ifindex)
1607					nat.af = $6.src.host->af;
1608				else if ($6.dst.host && $6.dst.host->af &&
1609				    !$6.dst.host->ifindex)
1610					nat.af = $6.dst.host->af;
1611			}
1612
1613			if (nat.no) {
1614				if ($7 != NULL) {
1615					yyerror("'no nat' rule does not need "
1616					    "'->'");
1617					YYERROR;
1618				}
1619			} else {
1620				struct node_host *n;
1621
1622				if ($7 == NULL || $7->address == NULL) {
1623					yyerror("'nat' rule requires '-> "
1624					    "address'");
1625					YYERROR;
1626				}
1627				if (!nat.af && !$7->address->ifindex)
1628					nat.af = $7->address->af;
1629				n = ifa_pick_ip($7->address, nat.af);
1630				if (n == NULL)
1631					YYERROR;
1632				if (!nat.af)
1633					nat.af = n->af;
1634				memcpy(&nat.raddr, &n->addr,
1635				    sizeof(nat.raddr));
1636				nat.proxy_port[0] = ntohs($7->rport.a);
1637				nat.proxy_port[1] = ntohs($7->rport.b);
1638				if (!nat.proxy_port[0] && !nat.proxy_port[1]) {
1639					nat.proxy_port[0] =
1640					    PF_NAT_PROXY_PORT_LOW;
1641					nat.proxy_port[1] =
1642					    PF_NAT_PROXY_PORT_HIGH;
1643				} else if (!nat.proxy_port[1])
1644					nat.proxy_port[1] = nat.proxy_port[0];
1645				free($7->address);
1646				free($7);
1647			}
1648
1649			expand_nat(&nat, $3, $5, $6.src.host, $6.src.port,
1650			    $6.dst.host, $6.dst.port);
1651		}
1652		;
1653
1654binatrule	: no BINAT interface af proto FROM host TO ipspec redirection
1655		{
1656			struct pf_binat binat;
1657
1658			if (check_rulestate(PFCTL_STATE_NAT))
1659				YYERROR;
1660
1661			memset(&binat, 0, sizeof(binat));
1662
1663			binat.no = $1;
1664			if ($3 != NULL) {
1665				memcpy(binat.ifname, $3->ifname,
1666				    sizeof(binat.ifname));
1667				free($3);
1668			}
1669			binat.af = $4;
1670			if ($5 != NULL) {
1671				binat.proto = $5->proto;
1672				free($5);
1673			}
1674			if ($7 != NULL && $9 != NULL && $7->af != $9->af) {
1675				yyerror("binat ip versions must match");
1676				YYERROR;
1677			}
1678			if ($7 != NULL) {
1679				if ($7->next) {
1680					yyerror("multiple binat ip addresses");
1681					YYERROR;
1682				}
1683				if ($7->addr.addr_dyn != NULL) {
1684					if (!binat.af) {
1685						yyerror("address family (inet/"
1686						    "inet6) undefined");
1687						YYERROR;
1688					}
1689					$7->af = binat.af;
1690				}
1691				if (binat.af && $7->af != binat.af) {
1692					yyerror("binat ip versions must match");
1693					YYERROR;
1694				}
1695				binat.af = $7->af;
1696				memcpy(&binat.saddr.addr, &$7->addr.addr,
1697				    sizeof(binat.saddr.addr));
1698				memcpy(&binat.smask, &$7->mask,
1699				    sizeof(binat.smask));
1700				free($7);
1701			}
1702			if ($9 != NULL) {
1703				if ($9->next) {
1704					yyerror("multiple binat ip addresses");
1705					YYERROR;
1706				}
1707				if ($9->addr.addr_dyn != NULL) {
1708					if (!binat.af) {
1709						yyerror("address family (inet/"
1710						    "inet6) undefined");
1711						YYERROR;
1712					}
1713					$9->af = binat.af;
1714				}
1715				if (binat.af && $9->af != binat.af) {
1716					yyerror("binat ip versions must match");
1717					YYERROR;
1718				}
1719				binat.af = $9->af;
1720				memcpy(&binat.daddr.addr, &$9->addr.addr,
1721				    sizeof(binat.daddr.addr));
1722				memcpy(&binat.dmask, &$9->mask,
1723				    sizeof(binat.dmask));
1724				binat.dnot  = $9->not;
1725				free($9);
1726			}
1727
1728			if (binat.no) {
1729				if ($10 != NULL) {
1730					yyerror("'no binat' rule does not need"
1731					    " '->'");
1732					YYERROR;
1733				}
1734			} else {
1735				struct node_host *n;
1736
1737				if ($10 == NULL || $10->address == NULL) {
1738					yyerror("'binat' rule requires"
1739					    " '-> address'");
1740					YYERROR;
1741				}
1742				n = ifa_pick_ip($10->address, binat.af);
1743				if (n == NULL)
1744					YYERROR;
1745				if (n->addr.addr_dyn != NULL) {
1746					if (!binat.af) {
1747						yyerror("address family (inet/"
1748						    "inet6) undefined");
1749						YYERROR;
1750					}
1751					n->af = binat.af;
1752				}
1753				if (binat.af && n->af != binat.af) {
1754					yyerror("binat ip versions must match");
1755					YYERROR;
1756				}
1757				binat.af = n->af;
1758				memcpy(&binat.raddr.addr, &n->addr.addr,
1759				    sizeof(binat.raddr.addr));
1760				memcpy(&binat.rmask, &n->mask,
1761				    sizeof(binat.rmask));
1762				if (PF_ANEQ(&binat.smask, &binat.rmask, binat.af)) {
1763					yyerror("'binat' source mask and "
1764					    "redirect mask must be the same");
1765					YYERROR;
1766				}
1767				free($10->address);
1768				free($10);
1769			}
1770
1771			pfctl_add_binat(pf, &binat);
1772		}
1773
1774rdrrule		: no RDR interface af proto FROM ipspec TO ipspec dport redirection
1775		{
1776			struct pf_rdr rdr;
1777
1778			if (check_rulestate(PFCTL_STATE_NAT))
1779				YYERROR;
1780
1781			memset(&rdr, 0, sizeof(rdr));
1782
1783			rdr.no = $1;
1784			rdr.af = $4;
1785			if ($7 != NULL) {
1786				memcpy(&rdr.saddr, &$7->addr,
1787				    sizeof(rdr.saddr));
1788				memcpy(&rdr.smask, &$7->mask,
1789				    sizeof(rdr.smask));
1790				rdr.snot  = $7->not;
1791				if (!rdr.af && !$7->ifindex)
1792					rdr.af = $7->af;
1793			}
1794			if ($9 != NULL) {
1795				memcpy(&rdr.daddr, &$9->addr,
1796				    sizeof(rdr.daddr));
1797				memcpy(&rdr.dmask, &$9->mask,
1798				    sizeof(rdr.dmask));
1799				rdr.dnot  = $9->not;
1800				if (!rdr.af && !$9->ifindex)
1801					rdr.af = $9->af;
1802			}
1803
1804			rdr.dport  = $10.a;
1805			rdr.dport2 = $10.b;
1806			rdr.opts  |= $10.t;
1807
1808			if (rdr.no) {
1809				if ($11 != NULL) {
1810					yyerror("'no rdr' rule does not need '->'");
1811					YYERROR;
1812				}
1813			} else {
1814				struct node_host *n;
1815
1816				if ($11 == NULL || $11->address == NULL) {
1817					yyerror("'rdr' rule requires '-> "
1818					    "address'");
1819					YYERROR;
1820				}
1821				if (!rdr.af && !$11->address->ifindex)
1822					rdr.af = $11->address->af;
1823				n = ifa_pick_ip($11->address, rdr.af);
1824				if (n == NULL)
1825					YYERROR;
1826				if (!rdr.af)
1827					rdr.af = n->af;
1828				memcpy(&rdr.raddr, &n->addr,
1829				    sizeof(rdr.raddr));
1830				free($11->address);
1831				rdr.rport  = $11->rport.a;
1832				rdr.opts  |= $11->rport.t;
1833				free($11);
1834			}
1835
1836			expand_rdr(&rdr, $3, $5, $7, $9);
1837		}
1838		;
1839
1840dport		: /* empty */			{
1841			$$.a = $$.b = $$.t = 0;
1842		}
1843		| PORT STRING			{
1844			char *p = strchr($2, ':');
1845
1846			if (p == NULL) {
1847				if (($$.a = getservice($2)) == -1)
1848					YYERROR;
1849				$$.b = $$.t = 0;
1850			} else {
1851				*p++ = 0;
1852				if (($$.a = getservice($2)) == -1 ||
1853				    ($$.b = getservice(p)) == -1)
1854					YYERROR;
1855				$$.t = PF_DPORT_RANGE;
1856			}
1857		}
1858		;
1859
1860route		: /* empty */			{
1861			$$.string = NULL;
1862			$$.rt = 0;
1863			$$.addr = NULL;
1864			$$.af = 0;
1865		}
1866		| FASTROUTE {
1867			$$.string = NULL;
1868			$$.rt = PF_FASTROUTE;
1869			$$.addr = NULL;
1870		}
1871		| ROUTETO '(' STRING address ')' {
1872			if (($$.string = strdup($3)) == NULL) {
1873				yyerror("routeto: strdup");
1874				YYERROR;
1875			}
1876			$$.rt = PF_ROUTETO;
1877			if ($4->addr.addr_dyn != NULL) {
1878				yyerror("route-to does not support"
1879				    " dynamic addresses");
1880				YYERROR;
1881			}
1882			if ($4->next) {
1883				yyerror("multiple route-to ip addresses");
1884				YYERROR;
1885			}
1886			$$.addr = &$4->addr.addr;
1887			$$.af = $4->af;
1888		}
1889		| ROUTETO STRING {
1890			if (($$.string = strdup($2)) == NULL) {
1891				yyerror("routeto: strdup");
1892				YYERROR;
1893			}
1894			$$.rt = PF_ROUTETO;
1895			$$.addr = NULL;
1896		}
1897		| REPLYTO '(' STRING address ')' {
1898			if (($$.string = strdup($3)) == NULL) {
1899				yyerror("reply-to: strdup");
1900				YYERROR;
1901			}
1902			$$.rt = PF_REPLYTO;
1903			if ($4->addr.addr_dyn != NULL) {
1904				yyerror("reply-to does not support"
1905				    " dynamic addresses");
1906				YYERROR;
1907			}
1908			if ($4->next) {
1909				yyerror("multiple reply-to ip addresses");
1910				YYERROR;
1911			}
1912			$$.addr = &$4->addr.addr;
1913			$$.af = $4->af;
1914		}
1915		| REPLYTO STRING {
1916			if (($$.string = strdup($2)) == NULL) {
1917				yyerror("reply-to: strdup");
1918				YYERROR;
1919			}
1920			$$.rt = PF_REPLYTO;
1921			$$.addr = NULL;
1922		}
1923		| DUPTO '(' STRING address ')' {
1924			if (($$.string = strdup($3)) == NULL) {
1925				yyerror("dupto: strdup");
1926				YYERROR;
1927			}
1928			$$.rt = PF_DUPTO;
1929			if ($4->addr.addr_dyn != NULL) {
1930				yyerror("dup-to does not support"
1931				    " dynamic addresses");
1932				YYERROR;
1933			}
1934			if ($4->next) {
1935				yyerror("multiple dup-to ip addresses");
1936				YYERROR;
1937			}
1938			$$.addr = &$4->addr.addr;
1939			$$.af = $4->af;
1940		}
1941		| DUPTO STRING {
1942			if (($$.string = strdup($2)) == NULL) {
1943				yyerror("dupto: strdup");
1944				YYERROR;
1945			}
1946			$$.rt = PF_DUPTO;
1947			$$.addr = NULL;
1948		}
1949		;
1950
1951timeout_spec	: STRING number
1952		{
1953			if (pf->opts & PF_OPT_VERBOSE)
1954				printf("set timeout %s %us\n", $1, $2);
1955			if (check_rulestate(PFCTL_STATE_OPTION))
1956				YYERROR;
1957			if (pfctl_set_timeout(pf, $1, $2) != 0) {
1958				yyerror("unknown timeout %s", $1);
1959				YYERROR;
1960			}
1961		}
1962		;
1963
1964timeout_list	: timeout_list comma timeout_spec
1965		| timeout_spec
1966		;
1967
1968limit_spec	: STRING number
1969		{
1970			if (pf->opts & PF_OPT_VERBOSE)
1971				printf("set limit %s %u\n", $1, $2);
1972			if (check_rulestate(PFCTL_STATE_OPTION))
1973				YYERROR;
1974			if (pfctl_set_limit(pf, $1, $2) != 0) {
1975				yyerror("unable to set limit %s %u", $1, $2);
1976				YYERROR;
1977			}
1978		}
1979
1980limit_list	: limit_list comma limit_spec
1981		| limit_spec
1982		;
1983
1984comma		: ','
1985		| /* empty */
1986		;
1987
1988%%
1989
1990int
1991yyerror(char *fmt, ...)
1992{
1993	va_list ap;
1994	extern char *infile;
1995	errors = 1;
1996
1997	va_start(ap, fmt);
1998	fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
1999	vfprintf(stderr, fmt, ap);
2000	fprintf(stderr, "\n");
2001	va_end(ap);
2002	return (0);
2003}
2004
2005int
2006rule_consistent(struct pf_rule *r)
2007{
2008	int problems = 0;
2009
2010	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
2011	    (r->src.port_op || r->dst.port_op)) {
2012		yyerror("port only applies to tcp/udp");
2013		problems++;
2014	}
2015	if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
2016	    (r->type || r->code)) {
2017		yyerror("icmp-type/code only applies to icmp");
2018		problems++;
2019	}
2020	if (!r->af && (r->type || r->code)) {
2021		yyerror("must indicate address family with icmp-type/code");
2022		problems++;
2023	}
2024	if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
2025	    (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
2026		yyerror("icmp version does not match address family");
2027		problems++;
2028	}
2029	if (r->keep_state == PF_STATE_MODULATE && r->proto &&
2030	    r->proto != IPPROTO_TCP) {
2031		yyerror("modulate state can only be applied to TCP rules");
2032		problems++;
2033	}
2034	if (r->allow_opts && r->action != PF_PASS) {
2035		yyerror("allow-opts can only be specified for pass rules");
2036		problems++;
2037	}
2038	if (!r->af && (r->src.addr.addr_dyn != NULL ||
2039	    r->dst.addr.addr_dyn != NULL)) {
2040		yyerror("dynamic addresses require address family (inet/inet6)");
2041		problems++;
2042	}
2043	if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
2044	    r->dst.port_op || r->flagset || r->type || r->code)) {
2045		yyerror("fragments can be filtered only on IP header fields");
2046		problems++;
2047	}
2048	if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) {
2049		yyerror("return-rst can only be applied to TCP rules");
2050		problems++;
2051	}
2052	if (r->action == PF_DROP && r->keep_state) {
2053		yyerror("keep state on block rules doesn't make sense");
2054		problems++;
2055	}
2056	return (-problems);
2057}
2058
2059int
2060nat_consistent(struct pf_nat *r)
2061{
2062	int problems = 0;
2063
2064	if (!r->af && (r->raddr.addr_dyn != NULL)) {
2065		yyerror("dynamic addresses require address family (inet/inet6)");
2066		problems++;
2067	}
2068	return (-problems);
2069}
2070
2071int
2072rdr_consistent(struct pf_rdr *r)
2073{
2074	int problems = 0;
2075
2076	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
2077	    (r->dport || r->dport2 || r->rport)) {
2078		yyerror("port only applies to tcp/udp");
2079		problems++;
2080	}
2081	if (!r->af && (r->saddr.addr_dyn != NULL ||
2082	    r->daddr.addr_dyn != NULL || r->raddr.addr_dyn != NULL)) {
2083		yyerror("dynamic addresses require address family (inet/inet6)");
2084		problems++;
2085	}
2086	return (-problems);
2087}
2088
2089struct keywords {
2090	const char	*k_name;
2091	int	 k_val;
2092};
2093
2094/* macro gore, but you should've seen the prior indentation nightmare... */
2095
2096#define FREE_LIST(T,r) \
2097	do { \
2098		T *p, *n = r; \
2099		while (n != NULL) { \
2100			p = n; \
2101			n = n->next; \
2102			free(p); \
2103		} \
2104	} while (0)
2105
2106#define LOOP_THROUGH(T,n,r,C) \
2107	do { \
2108		T *n; \
2109		if (r == NULL) { \
2110			r = calloc(1, sizeof(T)); \
2111			if (r == NULL) \
2112				err(1, "LOOP: calloc"); \
2113			r->next = NULL; \
2114		} \
2115		n = r; \
2116		while (n != NULL) { \
2117			do { \
2118				C; \
2119			} while (0); \
2120			n = n->next; \
2121		} \
2122	} while (0)
2123
2124void
2125expand_label_if(const char *name, char *label, const char *ifname)
2126{
2127	char tmp[PF_RULE_LABEL_SIZE];
2128	char *p;
2129
2130	while ((p = strstr(label, name)) != NULL) {
2131		tmp[0] = 0;
2132		strlcat(tmp, label, p-label+1);
2133		if (!*ifname)
2134			strlcat(tmp, "any", PF_RULE_LABEL_SIZE);
2135		else
2136			strlcat(tmp, ifname, PF_RULE_LABEL_SIZE);
2137		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
2138		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
2139	}
2140}
2141
2142void
2143expand_label_addr(const char *name, char *label, sa_family_t af,
2144    struct node_host *host)
2145{
2146	char tmp[PF_RULE_LABEL_SIZE];
2147	char *p;
2148
2149	while ((p = strstr(label, name)) != NULL) {
2150		tmp[0] = 0;
2151
2152		strlcat(tmp, label, p-label+1);
2153
2154		if (host->not)
2155			strlcat(tmp, "! ", PF_RULE_LABEL_SIZE);
2156		if (host->addr.addr_dyn != NULL) {
2157			strlcat(tmp, "(", PF_RULE_LABEL_SIZE);
2158			strlcat(tmp, host->addr.addr.pfa.ifname,
2159			    PF_RULE_LABEL_SIZE);
2160			strlcat(tmp, ")", PF_RULE_LABEL_SIZE);
2161		} else if (!af || (PF_AZERO(&host->addr.addr, af) &&
2162		    PF_AZERO(&host->mask, af)))
2163			strlcat(tmp, "any", PF_RULE_LABEL_SIZE);
2164		else {
2165			char a[48];
2166			int bits;
2167
2168			if (inet_ntop(af, &host->addr.addr, a,
2169			    sizeof(a)) == NULL)
2170				strlcat(a, "?", sizeof(a));
2171			strlcat(tmp, a, PF_RULE_LABEL_SIZE);
2172			bits = unmask(&host->mask, af);
2173			a[0] = 0;
2174			if ((af == AF_INET && bits < 32) ||
2175			    (af == AF_INET6 && bits < 128))
2176				snprintf(a, sizeof(a), "/%d", bits);
2177			strlcat(tmp, a, PF_RULE_LABEL_SIZE);
2178		}
2179		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
2180		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
2181	}
2182}
2183
2184void
2185expand_label_port(const char *name, char *label, struct node_port *port)
2186{
2187	char tmp[PF_RULE_LABEL_SIZE];
2188	char *p;
2189	char a1[6], a2[6], op[13];
2190
2191	while ((p = strstr(label, name)) != NULL) {
2192		tmp[0] = 0;
2193
2194		strlcat(tmp, label, p-label+1);
2195
2196		snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0]));
2197		snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1]));
2198		if (!port->op)
2199			op[0] = 0;
2200		else if (port->op == PF_OP_IRG)
2201			snprintf(op, sizeof(op), "%s><%s", a1, a2);
2202		else if (port->op == PF_OP_XRG)
2203			snprintf(op, sizeof(op), "%s<>%s", a1, a2);
2204		else if (port->op == PF_OP_EQ)
2205			snprintf(op, sizeof(op), "%s", a1);
2206		else if (port->op == PF_OP_NE)
2207			snprintf(op, sizeof(op), "!=%s", a1);
2208		else if (port->op == PF_OP_LT)
2209			snprintf(op, sizeof(op), "<%s", a1);
2210		else if (port->op == PF_OP_LE)
2211			snprintf(op, sizeof(op), "<=%s", a1);
2212		else if (port->op == PF_OP_GT)
2213			snprintf(op, sizeof(op), ">%s", a1);
2214		else if (port->op == PF_OP_GE)
2215			snprintf(op, sizeof(op), ">=%s", a1);
2216		strlcat(tmp, op, PF_RULE_LABEL_SIZE);
2217		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
2218		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
2219	}
2220}
2221
2222void
2223expand_label_proto(const char *name, char *label, u_int8_t proto)
2224{
2225	char tmp[PF_RULE_LABEL_SIZE];
2226	char *p;
2227	struct protoent *pe;
2228
2229	while ((p = strstr(label, name)) != NULL) {
2230		tmp[0] = 0;
2231		strlcat(tmp, label, p-label+1);
2232		pe = getprotobynumber(proto);
2233		if (pe != NULL)
2234		    strlcat(tmp, pe->p_name, PF_RULE_LABEL_SIZE);
2235		else
2236		    snprintf(tmp+strlen(tmp), PF_RULE_LABEL_SIZE-strlen(tmp),
2237			"%u", proto);
2238		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
2239		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
2240	}
2241}
2242
2243void
2244expand_label_nr(const char *name, char *label)
2245{
2246	char tmp[PF_RULE_LABEL_SIZE];
2247	char *p;
2248
2249	while ((p = strstr(label, name)) != NULL) {
2250		tmp[0] = 0;
2251		strlcat(tmp, label, p-label+1);
2252		snprintf(tmp+strlen(tmp), PF_RULE_LABEL_SIZE-strlen(tmp),
2253		    "%u", pf->rule_nr);
2254		strlcat(tmp, p+strlen(name), PF_RULE_LABEL_SIZE);
2255		strncpy(label, tmp, PF_RULE_LABEL_SIZE);
2256	}
2257}
2258
2259void
2260expand_label(char *label, const char *ifname, sa_family_t af,
2261    struct node_host *src_host, struct node_port *src_port,
2262    struct node_host *dst_host, struct node_port *dst_port,
2263    u_int8_t proto)
2264{
2265	expand_label_if("$if", label, ifname);
2266	expand_label_addr("$srcaddr", label, af, src_host);
2267	expand_label_addr("$dstaddr", label, af, dst_host);
2268	expand_label_port("$srcport", label, src_port);
2269	expand_label_port("$dstport", label, dst_port);
2270	expand_label_proto("$proto", label, proto);
2271	expand_label_nr("$nr", label);
2272}
2273
2274void
2275expand_altq(struct pf_altq *a, struct node_if *interfaces,
2276    struct node_queue *nqueues)
2277{
2278	struct	pf_altq pa, pb;
2279	char	qname[PF_QNAME_SIZE];
2280	struct	node_queue *n;
2281
2282	LOOP_THROUGH(struct node_if, interface, interfaces,
2283		memcpy(&pa, a, sizeof(struct pf_altq));
2284		strlcpy(pa.ifname, interface->ifname, IFNAMSIZ);
2285
2286		if (interface->not)
2287			yyerror("altq on ! <interface> is not supported");
2288		else {
2289			eval_pfaltq(pf, &pa);
2290			pfctl_add_altq(pf, &pa);
2291
2292			/* now create a root queue */
2293			memset(&pb, 0, sizeof(struct pf_altq));
2294			strlcpy(qname, "root_", sizeof(qname));
2295			strlcat(qname, interface->ifname, sizeof(qname));
2296			strlcpy(pb.qname, qname, PF_QNAME_SIZE);
2297			strlcpy(pb.ifname, interface->ifname, IFNAMSIZ);
2298			pb.qlimit = pa.qlimit;
2299			pb.scheduler = pa.scheduler;
2300			pb.pq_u.cbq_opts.flags = pa.pq_u.cbq_opts.flags;
2301			eval_pfqueue(pf, &pb, pa.ifbandwidth, 0);
2302			pfctl_add_altq(pf, &pb);
2303
2304			LOOP_THROUGH(struct node_queue, queue, nqueues,
2305				n = calloc(1, sizeof(struct node_queue));
2306				if (n == NULL)
2307					err(1, "expand_altq: malloc");
2308				strlcpy(n->parent, qname, PF_QNAME_SIZE);
2309				strlcpy(n->queue, queue->queue, PF_QNAME_SIZE);
2310				strlcpy(n->ifname, interface->ifname, IFNAMSIZ);
2311				n->next = NULL;
2312				n->tail = n;
2313				if (queues == NULL)
2314					queues = n;
2315				else {
2316					queues->tail->next = n;
2317					queues->tail = n;
2318				}
2319			);
2320		}
2321	);
2322	FREE_LIST(struct node_if, interfaces);
2323	FREE_LIST(struct node_queue, nqueues);
2324}
2325
2326int
2327expand_queue(struct pf_altq *a, struct node_queue *nqueues,
2328    struct node_queue_bw bwspec)
2329{
2330	struct	node_queue *n;
2331	u_int8_t	added = 0;
2332
2333	LOOP_THROUGH(struct node_queue, tqueue, queues,
2334		if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE)) {
2335			/* found ourselve in queues */
2336			LOOP_THROUGH(struct node_queue, queue, nqueues,
2337				n = malloc(sizeof(struct node_queue));
2338				if (n == NULL)
2339					err(1, "expand_queue: malloc");
2340				strlcpy(n->parent, a->qname, PF_QNAME_SIZE);
2341				strlcpy(n->queue, queue->queue, PF_QNAME_SIZE);
2342				strlcpy(n->ifname, tqueue->ifname, IFNAMSIZ);
2343				n->next = NULL;
2344				n->tail = n;
2345				if (queues == NULL)
2346					queues = n;
2347				else {
2348					queues->tail->next = n;
2349					queues->tail = n;
2350				}
2351			);
2352			FREE_LIST(struct node_queue, nqueues);
2353			strlcpy(a->ifname, tqueue->ifname, IFNAMSIZ);
2354			strlcpy(a->parent, tqueue->parent, PF_QNAME_SIZE);
2355
2356			eval_pfqueue(pf, a, bwspec.bw_absolute,
2357			    bwspec.bw_percent);
2358			pfctl_add_altq(pf, a);
2359			added++;
2360		}
2361	);
2362
2363	if (!added) {
2364		yyerror("queue has no parent");
2365		return (1);
2366	} else
2367		return (0);
2368}
2369
2370void
2371expand_rule(struct pf_rule *r,
2372    struct node_if *interfaces, struct node_proto *protos,
2373    struct node_host *src_hosts, struct node_port *src_ports,
2374    struct node_host *dst_hosts, struct node_port *dst_ports,
2375    struct node_uid *uids, struct node_gid *gids,
2376    struct node_icmp *icmp_types)
2377{
2378	sa_family_t	af = r->af;
2379	int nomatch = 0, added = 0;
2380	char	ifname[IF_NAMESIZE];
2381	char	label[PF_RULE_LABEL_SIZE];
2382	char	qname[PF_QNAME_SIZE];
2383	u_int8_t flags, flagset;
2384
2385	strlcpy(label, r->label, sizeof(label));
2386	strlcpy(qname, r->qname, sizeof(qname));
2387	flags = r->flags;
2388	flagset = r->flagset;
2389
2390	LOOP_THROUGH(struct node_if, interface, interfaces,
2391	LOOP_THROUGH(struct node_proto, proto, protos,
2392	LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
2393	LOOP_THROUGH(struct node_host, src_host, src_hosts,
2394	LOOP_THROUGH(struct node_port, src_port, src_ports,
2395	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
2396	LOOP_THROUGH(struct node_port, dst_port, dst_ports,
2397	LOOP_THROUGH(struct node_uid, uid, uids,
2398	LOOP_THROUGH(struct node_gid, gid, gids,
2399
2400		r->af = af;
2401		/* for link-local IPv6 address, interface must match up */
2402		if ((r->af && src_host->af && r->af != src_host->af) ||
2403		    (r->af && dst_host->af && r->af != dst_host->af) ||
2404		    (src_host->af && dst_host->af &&
2405		    src_host->af != dst_host->af) ||
2406		    (src_host->ifindex && dst_host->ifindex &&
2407		    src_host->ifindex != dst_host->ifindex) ||
2408		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
2409		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
2410		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
2411		    dst_host->ifindex != if_nametoindex(interface->ifname)))
2412			continue;
2413		if (!r->af && src_host->af)
2414			r->af = src_host->af;
2415		else if (!r->af && dst_host->af)
2416			r->af = dst_host->af;
2417
2418		if (if_indextoname(src_host->ifindex, ifname))
2419			memcpy(r->ifname, ifname, sizeof(r->ifname));
2420		else if (if_indextoname(dst_host->ifindex, ifname))
2421			memcpy(r->ifname, ifname, sizeof(r->ifname));
2422		else
2423			memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
2424
2425		strlcpy(r->label, label, PF_RULE_LABEL_SIZE);
2426		expand_label(r->label, r->ifname, r->af, src_host, src_port,
2427		    dst_host, dst_port, proto->proto);
2428		strlcpy(r->qname, qname, PF_QNAME_SIZE);
2429		r->qid = qname_to_qid(qname, r->ifname);
2430		r->ifnot = interface->not;
2431		r->proto = proto->proto;
2432		r->src.addr = src_host->addr;
2433		r->src.mask = src_host->mask;
2434		r->src.noroute = src_host->noroute;
2435		r->src.not = src_host->not;
2436		r->src.port[0] = src_port->port[0];
2437		r->src.port[1] = src_port->port[1];
2438		r->src.port_op = src_port->op;
2439		r->dst.addr = dst_host->addr;
2440		r->dst.mask = dst_host->mask;
2441		r->dst.noroute = dst_host->noroute;
2442		r->dst.not = dst_host->not;
2443		r->dst.port[0] = dst_port->port[0];
2444		r->dst.port[1] = dst_port->port[1];
2445		r->dst.port_op = dst_port->op;
2446		r->uid.op = uid->op;
2447		r->uid.uid[0] = uid->uid[0];
2448		r->uid.uid[1] = uid->uid[1];
2449		r->gid.op = gid->op;
2450		r->gid.gid[0] = gid->gid[0];
2451		r->gid.gid[1] = gid->gid[1];
2452		r->type = icmp_type->type;
2453		r->code = icmp_type->code;
2454
2455		if (r->proto && r->proto != IPPROTO_TCP) {
2456			r->flags = 0;
2457			r->flagset = 0;
2458		} else {
2459			r->flags = flags;
2460			r->flagset = flagset;
2461		}
2462		if (icmp_type->proto && r->proto != icmp_type->proto) {
2463			yyerror("icmp-type mismatch");
2464			nomatch++;
2465		}
2466
2467		if (rule_consistent(r) < 0 || nomatch)
2468			yyerror("skipping filter rule due to errors");
2469		else {
2470			r->nr = pf->rule_nr++;
2471			pfctl_add_rule(pf, r);
2472			added++;
2473		}
2474
2475	)))))))));
2476
2477	FREE_LIST(struct node_if, interfaces);
2478	FREE_LIST(struct node_proto, protos);
2479	FREE_LIST(struct node_host, src_hosts);
2480	FREE_LIST(struct node_port, src_ports);
2481	FREE_LIST(struct node_host, dst_hosts);
2482	FREE_LIST(struct node_port, dst_ports);
2483	FREE_LIST(struct node_uid, uids);
2484	FREE_LIST(struct node_gid, gids);
2485	FREE_LIST(struct node_icmp, icmp_types);
2486
2487	if (!added)
2488		yyerror("rule expands to no valid combination");
2489}
2490
2491void
2492expand_nat(struct pf_nat *n,
2493    struct node_if *interfaces, struct node_proto *protos,
2494    struct node_host *src_hosts, struct node_port *src_ports,
2495    struct node_host *dst_hosts, struct node_port *dst_ports)
2496{
2497	char ifname[IF_NAMESIZE];
2498	sa_family_t af = n->af;
2499	int added = 0;
2500
2501	LOOP_THROUGH(struct node_if, interface, interfaces,
2502	LOOP_THROUGH(struct node_proto, proto, protos,
2503	LOOP_THROUGH(struct node_host, src_host, src_hosts,
2504	LOOP_THROUGH(struct node_port, src_port, src_ports,
2505	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
2506	LOOP_THROUGH(struct node_port, dst_port, dst_ports,
2507
2508		n->af = af;
2509		/* for link-local IPv6 address, interface must match up */
2510		if ((n->af && src_host->af && n->af != src_host->af) ||
2511		    (n->af && dst_host->af && n->af != dst_host->af) ||
2512		    (src_host->af && dst_host->af &&
2513		    src_host->af != dst_host->af) ||
2514		    (src_host->ifindex && dst_host->ifindex &&
2515		    src_host->ifindex != dst_host->ifindex) ||
2516		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
2517		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
2518		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
2519		    dst_host->ifindex != if_nametoindex(interface->ifname)))
2520			continue;
2521		if (!n->af && src_host->af)
2522			n->af = src_host->af;
2523		else if (!n->af && dst_host->af)
2524			n->af = dst_host->af;
2525
2526		if (if_indextoname(src_host->ifindex, ifname))
2527			memcpy(n->ifname, ifname, sizeof(n->ifname));
2528		else if (if_indextoname(dst_host->ifindex, ifname))
2529			memcpy(n->ifname, ifname, sizeof(n->ifname));
2530		else
2531			memcpy(n->ifname, interface->ifname, sizeof(n->ifname));
2532
2533		n->ifnot = interface->not;
2534		n->proto = proto->proto;
2535		n->src.addr = src_host->addr;
2536		n->src.mask = src_host->mask;
2537		n->src.noroute = src_host->noroute;
2538		n->src.not = src_host->not;
2539		n->src.port[0] = src_port->port[0];
2540		n->src.port[1] = src_port->port[1];
2541		n->src.port_op = src_port->op;
2542		n->dst.addr = dst_host->addr;
2543		n->dst.mask = dst_host->mask;
2544		n->dst.noroute = dst_host->noroute;
2545		n->dst.not = dst_host->not;
2546		n->dst.port[0] = dst_port->port[0];
2547		n->dst.port[1] = dst_port->port[1];
2548		n->dst.port_op = dst_port->op;
2549
2550		if (nat_consistent(n) < 0)
2551			yyerror("skipping nat rule due to errors");
2552		else {
2553			pfctl_add_nat(pf, n);
2554			added++;
2555		}
2556
2557	))))));
2558
2559	FREE_LIST(struct node_if, interfaces);
2560	FREE_LIST(struct node_proto, protos);
2561	FREE_LIST(struct node_host, src_hosts);
2562	FREE_LIST(struct node_port, src_ports);
2563	FREE_LIST(struct node_host, dst_hosts);
2564	FREE_LIST(struct node_port, dst_ports);
2565
2566	if (!added)
2567		yyerror("nat rule expands to no valid combinations");
2568}
2569
2570void
2571expand_rdr(struct pf_rdr *r, struct node_if *interfaces,
2572    struct node_proto *protos, struct node_host *src_hosts,
2573    struct node_host *dst_hosts)
2574{
2575	sa_family_t af = r->af;
2576	int added = 0;
2577	char ifname[IF_NAMESIZE];
2578
2579	LOOP_THROUGH(struct node_if, interface, interfaces,
2580	LOOP_THROUGH(struct node_proto, proto, protos,
2581	LOOP_THROUGH(struct node_host, src_host, src_hosts,
2582	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
2583
2584		r->af = af;
2585		if ((r->af && src_host->af && r->af != src_host->af) ||
2586		    (r->af && dst_host->af && r->af != dst_host->af) ||
2587		    (src_host->af && dst_host->af &&
2588		    src_host->af != dst_host->af) ||
2589		    (src_host->ifindex && dst_host->ifindex &&
2590		    src_host->ifindex != dst_host->ifindex) ||
2591		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
2592		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
2593		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
2594		    dst_host->ifindex != if_nametoindex(interface->ifname)))
2595			continue;
2596
2597		if (!r->af && src_host->af)
2598			r->af = src_host->af;
2599		else if (!r->af && dst_host->af)
2600			r->af = dst_host->af;
2601
2602		if (if_indextoname(src_host->ifindex, ifname))
2603			memcpy(r->ifname, ifname, sizeof(r->ifname));
2604		else if (if_indextoname(dst_host->ifindex, ifname))
2605			memcpy(r->ifname, ifname, sizeof(r->ifname));
2606		else
2607			memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
2608
2609		r->proto = proto->proto;
2610		r->ifnot = interface->not;
2611		r->saddr = src_host->addr;
2612		r->smask = src_host->mask;
2613		r->daddr = dst_host->addr;
2614		r->dmask = dst_host->mask;
2615
2616		if (rdr_consistent(r) < 0)
2617			yyerror("skipping rdr rule due to errors");
2618		else {
2619			pfctl_add_rdr(pf, r);
2620			added++;
2621		}
2622
2623	))));
2624
2625	FREE_LIST(struct node_if, interfaces);
2626	FREE_LIST(struct node_proto, protos);
2627	FREE_LIST(struct node_host, src_hosts);
2628	FREE_LIST(struct node_host, dst_hosts);
2629
2630	if (!added)
2631		yyerror("rdr rule expands to no valid combination");
2632}
2633
2634#undef FREE_LIST
2635#undef LOOP_THROUGH
2636
2637int
2638check_rulestate(int desired_state)
2639{
2640	if (require_order && (rulestate > desired_state)) {
2641		yyerror("Rules must be in order: options, normalization, "
2642		    "translation, filter");
2643		return (1);
2644	}
2645	rulestate = desired_state;
2646	return (0);
2647}
2648
2649int
2650kw_cmp(const void *k, const void *e)
2651{
2652	return (strcmp(k, ((const struct keywords *)e)->k_name));
2653}
2654
2655int
2656lookup(char *s)
2657{
2658	/* this has to be sorted always */
2659	static const struct keywords keywords[] = {
2660		{ "all",	ALL},
2661		{ "allow-opts",	ALLOWOPTS},
2662		{ "altq",	ALTQ},
2663		{ "antispoof",	ANTISPOOF},
2664		{ "any",	ANY},
2665		{ "bandwidth",	BANDWIDTH},
2666		{ "binat",	BINAT},
2667		{ "block",	BLOCK},
2668		{ "block-policy", BLOCKPOLICY},
2669		{ "borrow",	BORROW},
2670		{ "cbq",	CBQ},
2671		{ "code",	CODE},
2672		{ "control",	CONTROL},
2673		{ "crop",	FRAGCROP},
2674		{ "default",	DEFAULT},
2675		{ "drop",	DROP},
2676		{ "drop-ovl",	FRAGDROP},
2677		{ "dup-to",	DUPTO},
2678		{ "ecn",	ECN},
2679		{ "fastroute",	FASTROUTE},
2680		{ "flags",	FLAGS},
2681		{ "for",	FOR},
2682		{ "fragment",	FRAGMENT},
2683		{ "from",	FROM},
2684		{ "group",	GROUP},
2685		{ "icmp-type",	ICMPTYPE},
2686		{ "in",		IN},
2687		{ "inet",	INET},
2688		{ "inet6",	INET6},
2689		{ "ipv6-icmp-type", ICMP6TYPE},
2690		{ "keep",	KEEP},
2691		{ "label",	LABEL},
2692		{ "limit",	LIMIT},
2693		{ "log",	LOG},
2694		{ "log-all",	LOGALL},
2695		{ "loginterface", LOGINTERFACE},
2696		{ "max",	MAXIMUM},
2697		{ "max-mss",	MAXMSS},
2698		{ "min-ttl",	MINTTL},
2699		{ "modulate",	MODULATE},
2700		{ "nat",	NAT},
2701		{ "no",		NO},
2702		{ "no-df",	NODF},
2703		{ "no-route",	NOROUTE},
2704		{ "on",		ON},
2705		{ "optimization", OPTIMIZATION},
2706		{ "out",	OUT},
2707		{ "pass",	PASS},
2708		{ "port",	PORT},
2709		{ "priority",	PRIORITY},
2710		{ "proto",	PROTO},
2711		{ "qlimit",	QLIMIT},
2712		{ "queue",	QUEUE},
2713		{ "quick",	QUICK},
2714		{ "rdr",	RDR},
2715		{ "reassemble",	FRAGNORM},
2716		{ "red",	RED},
2717		{ "reply-to",	REPLYTO},
2718		{ "require-order", REQUIREORDER},
2719		{ "return",	RETURN},
2720		{ "return-icmp",RETURNICMP},
2721		{ "return-icmp6",RETURNICMP6},
2722		{ "return-rst",	RETURNRST},
2723		{ "rio",	RIO},
2724		{ "route-to",	ROUTETO},
2725		{ "scheduler",	SCHEDULER},
2726		{ "scrub",	SCRUB},
2727		{ "set",	SET},
2728		{ "state",	STATE},
2729		{ "tbrsize",	TBRSIZE},
2730		{ "timeout",	TIMEOUT},
2731		{ "to",		TO},
2732		{ "tos",	TOS},
2733		{ "ttl",	TTL},
2734		{ "user",	USER},
2735		{ "yes",	YES},
2736	};
2737	const struct keywords *p;
2738
2739	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
2740	    sizeof(keywords[0]), kw_cmp);
2741
2742	if (p) {
2743		if (debug > 1)
2744			fprintf(stderr, "%s: %d\n", s, p->k_val);
2745		return (p->k_val);
2746	} else {
2747		if (debug > 1)
2748			fprintf(stderr, "string: %s\n", s);
2749		return (STRING);
2750	}
2751}
2752
2753#define MAXPUSHBACK	128
2754
2755char	*parsebuf;
2756int	parseindex;
2757char	pushback_buffer[MAXPUSHBACK];
2758int	pushback_index = 0;
2759
2760int
2761lgetc(FILE *fin)
2762{
2763	int c, next;
2764
2765	if (parsebuf) {
2766		/* Read character from the parsebuffer instead of input. */
2767		if (parseindex >= 0) {
2768			c = parsebuf[parseindex++];
2769			if (c != '\0')
2770				return (c);
2771			parsebuf = NULL;
2772		} else
2773			parseindex++;
2774	}
2775
2776	if (pushback_index)
2777		return (pushback_buffer[--pushback_index]);
2778
2779	while ((c = getc(fin)) == '\\') {
2780		next = getc(fin);
2781		if (next != '\n') {
2782			if (isspace(next))
2783				yyerror("whitespace after \\");
2784			ungetc(next, fin);
2785			break;
2786		}
2787		yylval.lineno = lineno;
2788		lineno++;
2789	}
2790	if (c == '\t' || c == ' ') {
2791		/* Compress blanks to a single space. */
2792		do {
2793			c = getc(fin);
2794		} while (c == '\t' || c == ' ');
2795		ungetc(c, fin);
2796		c = ' ';
2797	}
2798
2799	return (c);
2800}
2801
2802int
2803lungetc(int c, FILE *fin)
2804{
2805	if (c == EOF)
2806		return (EOF);
2807	if (parsebuf) {
2808		parseindex--;
2809		if (parseindex >= 0)
2810			return (c);
2811	}
2812	if (pushback_index < MAXPUSHBACK-1)
2813		return (pushback_buffer[pushback_index++] = c);
2814	else
2815		return (EOF);
2816}
2817
2818int
2819findeol(void)
2820{
2821	int c;
2822
2823	parsebuf = NULL;
2824	pushback_index = 0;
2825
2826	/* skip to either EOF or the first real EOL */
2827	while (1) {
2828		c = lgetc(fin);
2829		if (c == '\n') {
2830			lineno++;
2831			break;
2832		}
2833		if (c == EOF)
2834			break;
2835	}
2836	return (ERROR);
2837}
2838
2839int
2840yylex(void)
2841{
2842	char buf[8096], *p, *val;
2843	int endc, c, next;
2844	int token;
2845
2846top:
2847	p = buf;
2848	while ((c = lgetc(fin)) == ' ')
2849		;
2850
2851	yylval.lineno = lineno;
2852	if (c == '#')
2853		while ((c = lgetc(fin)) != '\n' && c != EOF)
2854			;
2855	if (c == '$' && parsebuf == NULL) {
2856		while (1) {
2857			if ((c = lgetc(fin)) == EOF)
2858				return (0);
2859			if (p + 1 >= buf + sizeof(buf) - 1) {
2860				yyerror("string too long");
2861				return (findeol());
2862			}
2863			if (isalnum(c) || c == '_') {
2864				*p++ = (char)c;
2865				continue;
2866			}
2867			*p = '\0';
2868			lungetc(c, fin);
2869			break;
2870		}
2871		val = symget(buf);
2872		if (val == NULL) {
2873			yyerror("macro '%s' not defined", buf);
2874			return (findeol());
2875		}
2876		parsebuf = val;
2877		parseindex = 0;
2878		goto top;
2879	}
2880
2881	switch (c) {
2882	case '\'':
2883	case '"':
2884		endc = c;
2885		while (1) {
2886			if ((c = lgetc(fin)) == EOF)
2887				return (0);
2888			if (c == endc) {
2889				*p = '\0';
2890				break;
2891			}
2892			if (c == '\n') {
2893				lineno++;
2894				continue;
2895			}
2896			if (p + 1 >= buf + sizeof(buf) - 1) {
2897				yyerror("string too long");
2898				return (findeol());
2899			}
2900			*p++ = (char)c;
2901		}
2902		yylval.v.string = strdup(buf);
2903		if (yylval.v.string == NULL)
2904			err(1, "yylex: strdup");
2905		return (STRING);
2906	case '=':
2907		yylval.v.i = PF_OP_EQ;
2908		return (PORTUNARY);
2909	case '!':
2910		next = lgetc(fin);
2911		if (next == '=') {
2912			yylval.v.i = PF_OP_NE;
2913			return (PORTUNARY);
2914		}
2915		lungetc(next, fin);
2916		break;
2917	case '<':
2918		next = lgetc(fin);
2919		if (next == '>') {
2920			yylval.v.i = PF_OP_XRG;
2921			return (PORTBINARY);
2922		} else  if (next == '=') {
2923			yylval.v.i = PF_OP_LE;
2924		} else {
2925			yylval.v.i = PF_OP_LT;
2926			lungetc(next, fin);
2927		}
2928		return (PORTUNARY);
2929		break;
2930	case '>':
2931		next = lgetc(fin);
2932		if (next == '<') {
2933			yylval.v.i = PF_OP_IRG;
2934			return (PORTBINARY);
2935		} else  if (next == '=') {
2936			yylval.v.i = PF_OP_GE;
2937		} else {
2938			yylval.v.i = PF_OP_GT;
2939			lungetc(next, fin);
2940		}
2941		return (PORTUNARY);
2942		break;
2943	case '-':
2944		next = lgetc(fin);
2945		if (next == '>')
2946			return (ARROW);
2947		lungetc(next, fin);
2948		break;
2949	}
2950
2951#define allowed_in_string(x) \
2952	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
2953	x != '{' && x != '}' && x != '<' && x != '>' && \
2954	x != '!' && x != '=' && x != '/' && x != '#' && \
2955	x != ','))
2956
2957	if (isalnum(c) || c == ':') {
2958		do {
2959			*p++ = c;
2960			if ((unsigned)(p-buf) >= sizeof(buf)) {
2961				yyerror("string too long");
2962				return (findeol());
2963			}
2964		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
2965		lungetc(c, fin);
2966		*p = '\0';
2967		token = lookup(buf);
2968		yylval.v.string = strdup(buf);
2969		if (yylval.v.string == NULL)
2970			err(1, "yylex: strdup");
2971		return (token);
2972	}
2973	if (c == '\n') {
2974		yylval.lineno = lineno;
2975		lineno++;
2976	}
2977	if (c == EOF)
2978		return (0);
2979	return (c);
2980}
2981
2982int
2983parse_rules(FILE *input, struct pfctl *xpf)
2984{
2985	struct sym *sym;
2986
2987	fin = input;
2988	pf = xpf;
2989	lineno = 1;
2990	errors = 0;
2991	rulestate = PFCTL_STATE_NONE;
2992	yyparse();
2993
2994	/* Check which macros have not been used. */
2995	for (sym = symhead; sym; sym = sym->next)
2996		if (!sym->used)
2997			fprintf(stderr, "warning: macro '%s' not used\n",
2998			    sym->nam);
2999
3000	return (errors ? -1 : 0);
3001}
3002
3003void
3004set_ipmask(struct node_host *h, u_int8_t b)
3005{
3006	struct pf_addr *m, *n;
3007	int i, j = 0;
3008
3009	m = &h->mask;
3010
3011	for (i = 0; i < 4; i++)
3012		m->addr32[i] = 0;
3013
3014	while (b >= 32) {
3015		m->addr32[j++] = 0xffffffff;
3016		b -= 32;
3017	}
3018	for (i = 31; i > 31-b; --i)
3019		m->addr32[j] |= (1 << i);
3020	if (b)
3021		m->addr32[j] = htonl(m->addr32[j]);
3022
3023	/* Mask off bits of the address that will never be used. */
3024	n = &h->addr.addr;
3025	for (i = 0; i < 4; i++)
3026		n->addr32[i] = n->addr32[i] & m->addr32[i];
3027}
3028
3029/*
3030 * Over-designed efficiency is a French and German concept, so how about
3031 * we wait until they discover this ugliness and make it all fancy.
3032 */
3033int
3034symset(const char *nam, const char *val)
3035{
3036	struct sym *sym;
3037
3038	sym = calloc(1, sizeof(*sym));
3039	if (sym == NULL)
3040		return (-1);
3041	sym->nam = strdup(nam);
3042	if (sym->nam == NULL) {
3043		free(sym);
3044		return (-1);
3045	}
3046	sym->val = strdup(val);
3047	if (sym->val == NULL) {
3048		free(sym->nam);
3049		free(sym);
3050		return (-1);
3051	}
3052	sym->next = symhead;
3053	sym->used = 0;
3054	symhead = sym;
3055	return (0);
3056}
3057
3058char *
3059symget(const char *nam)
3060{
3061	struct sym *sym;
3062
3063	for (sym = symhead; sym; sym = sym->next)
3064		if (strcmp(nam, sym->nam) == 0) {
3065			sym->used = 1;
3066			return (sym->val);
3067		}
3068	return (NULL);
3069}
3070
3071/* interface lookup routines */
3072
3073struct node_host *iftab;
3074
3075void
3076ifa_load(void)
3077{
3078	struct ifaddrs *ifap, *ifa;
3079	struct node_host *n = NULL, *h = NULL;
3080
3081	if (getifaddrs(&ifap) < 0)
3082		err(1, "getifaddrs");
3083
3084	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
3085		if (!(ifa->ifa_addr->sa_family == AF_INET ||
3086		    ifa->ifa_addr->sa_family == AF_INET6 ||
3087		    ifa->ifa_addr->sa_family == AF_LINK))
3088				continue;
3089		n = calloc(1, sizeof(struct node_host));
3090		if (n == NULL)
3091			err(1, "address: calloc");
3092		n->af = ifa->ifa_addr->sa_family;
3093		n->addr.addr_dyn = NULL;
3094		n->ifa_flags = ifa->ifa_flags;
3095#ifdef __KAME__
3096		if (n->af == AF_INET6 &&
3097		    IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr) &&
3098		    ((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_scope_id == 0) {
3099			struct sockaddr_in6 *sin6;
3100
3101			sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
3102			sin6->sin6_scope_id = sin6->sin6_addr.s6_addr[2] << 8 |
3103			    sin6->sin6_addr.s6_addr[3];
3104			sin6->sin6_addr.s6_addr[2] = 0;
3105			sin6->sin6_addr.s6_addr[3] = 0;
3106		}
3107#endif
3108		n->ifindex = 0;
3109		if (n->af == AF_INET) {
3110			memcpy(&n->addr.addr, &((struct sockaddr_in *)
3111			    ifa->ifa_addr)->sin_addr.s_addr,
3112			    sizeof(struct in_addr));
3113			memcpy(&n->mask, &((struct sockaddr_in *)
3114			    ifa->ifa_netmask)->sin_addr.s_addr,
3115			    sizeof(struct in_addr));
3116			if (ifa->ifa_broadaddr != NULL)
3117				memcpy(&n->bcast, &((struct sockaddr_in *)
3118				    ifa->ifa_broadaddr)->sin_addr.s_addr,
3119				    sizeof(struct in_addr));
3120		} else if (n->af == AF_INET6) {
3121			memcpy(&n->addr.addr, &((struct sockaddr_in6 *)
3122			    ifa->ifa_addr)->sin6_addr.s6_addr,
3123			    sizeof(struct in6_addr));
3124			memcpy(&n->mask, &((struct sockaddr_in6 *)
3125			    ifa->ifa_netmask)->sin6_addr.s6_addr,
3126			    sizeof(struct in6_addr));
3127			if (ifa->ifa_broadaddr != NULL)
3128				memcpy(&n->bcast, &((struct sockaddr_in6 *)
3129				    ifa->ifa_broadaddr)->sin6_addr.s6_addr,
3130				    sizeof(struct in6_addr));
3131			n->ifindex = ((struct sockaddr_in6 *)
3132			    ifa->ifa_addr)->sin6_scope_id;
3133		}
3134		if ((n->ifname = strdup(ifa->ifa_name)) == NULL) {
3135			yyerror("malloc failed");
3136			exit(1);
3137		}
3138		n->next = NULL;
3139		n->tail = n;
3140		if (h == NULL)
3141			h = n;
3142		else {
3143			h->tail->next = n;
3144			h->tail = n;
3145		}
3146	}
3147	iftab = h;
3148	freeifaddrs(ifap);
3149}
3150
3151struct node_host *
3152ifa_exists(char *ifa_name)
3153{
3154	struct node_host *n;
3155
3156	if (iftab == NULL)
3157		ifa_load();
3158
3159	for (n = iftab; n; n = n->next) {
3160		if (n->af == AF_LINK && !strncmp(n->ifname, ifa_name, IFNAMSIZ))
3161			return (n);
3162	}
3163	return (NULL);
3164}
3165
3166struct node_host *
3167ifa_lookup(char *ifa_name, enum pfctl_iflookup_mode mode)
3168{
3169	struct node_host *p = NULL, *h = NULL, *n = NULL;
3170	int return_all = 0;
3171
3172	if (!strncmp(ifa_name, "self", IFNAMSIZ))
3173		return_all = 1;
3174
3175	if (iftab == NULL)
3176		ifa_load();
3177
3178	for (p = iftab; p; p = p->next) {
3179		if (!((p->af == AF_INET || p->af == AF_INET6) &&
3180		    (!strncmp(p->ifname, ifa_name, IFNAMSIZ) || return_all)))
3181			continue;
3182		if (mode == PFCTL_IFLOOKUP_BCAST && p->af != AF_INET)
3183			continue;
3184		if (mode == PFCTL_IFLOOKUP_NET && p->ifindex > 0)
3185			continue;
3186		n = calloc(1, sizeof(struct node_host));
3187		if (n == NULL)
3188			err(1, "address: calloc");
3189		n->af = p->af;
3190		n->addr.addr_dyn = NULL;
3191		if (mode == PFCTL_IFLOOKUP_BCAST) {
3192				memcpy(&n->addr.addr, &p->bcast,
3193				    sizeof(struct pf_addr));
3194		} else
3195			memcpy(&n->addr.addr, &p->addr.addr,
3196			    sizeof(struct pf_addr));
3197		if (mode == PFCTL_IFLOOKUP_NET)
3198			memcpy(&n->mask, &p->mask, sizeof(struct pf_addr));
3199		else {
3200			if (n->af == AF_INET)
3201				set_ipmask(n, 32);
3202			else
3203				set_ipmask(n, 128);
3204		}
3205		n->ifindex = p->ifindex;
3206
3207		n->next = NULL;
3208		n->tail = n;
3209		if (h == NULL)
3210			h = n;
3211		else {
3212			h->tail->next = n;
3213			h->tail = n;
3214		}
3215	}
3216	if (h == NULL && mode == PFCTL_IFLOOKUP_HOST) {
3217		yyerror("no IP address found for %s", ifa_name);
3218	}
3219	return (h);
3220}
3221
3222struct node_host *
3223ifa_pick_ip(struct node_host *nh, sa_family_t af)
3224{
3225	struct node_host *h, *n = NULL;
3226
3227	if (af == 0 && nh && nh->next) {
3228		yyerror("address family not given and translation address "
3229		    "expands to multiple IPs");
3230		return (NULL);
3231	}
3232	for (h = nh; h; h = h->next) {
3233		if (h->af == af || h->af == 0 || af == 0) {
3234			if (n != NULL) {
3235				yyerror("translation address expands to "
3236				    "multiple IPs of this address family");
3237				return (NULL);
3238			}
3239			n = h;
3240		}
3241	}
3242	if (n == NULL)
3243		yyerror("no translation address with matching address family "
3244		    "found.");
3245	else {
3246		n->next = NULL;
3247		n->tail = n;
3248	}
3249
3250	return (n);
3251}
3252
3253struct node_host *
3254host(char *s, int mask)
3255{
3256	struct node_host *h = NULL, *n;
3257	struct in_addr ina;
3258	struct addrinfo hints, *res0, *res;
3259	int bits, error, v4mask, v6mask;
3260	char *buf = NULL;
3261
3262	if (ifa_exists(s) || !strncmp(s, "self", IFNAMSIZ)) {
3263		/* interface with this name exists */
3264		h = ifa_lookup(s, PFCTL_IFLOOKUP_HOST);
3265		if (h != NULL && mask > -1)
3266			set_ipmask(h, mask);
3267		return (h);
3268	}
3269
3270	if (mask == -1) {
3271		if (asprintf(&buf, "%s", s) == -1)
3272			err(1, "host: malloc");
3273		v4mask = 32;
3274		v6mask = 128;
3275	} else if (mask <= 128) {
3276		if (asprintf(&buf, "%s/%d", s, mask) == -1)
3277			err(1, "host: malloc");
3278		v4mask = v6mask = mask;
3279	} else {
3280		yyerror("illegal mask");
3281		return (NULL);
3282	}
3283
3284	memset(&ina, 0, sizeof(struct in_addr));
3285	if ((bits = inet_net_pton(AF_INET, buf, &ina, sizeof(&ina))) > -1) {
3286		h = calloc(1, sizeof(struct node_host));
3287		if (h == NULL)
3288			err(1, "address: calloc");
3289		h->af = AF_INET;
3290		h->addr.addr_dyn = NULL;
3291		h->addr.addr.addr32[0] = ina.s_addr;
3292		set_ipmask(h, bits);
3293		h->next = NULL;
3294		h->tail = h;
3295		free(buf);
3296		return (h);
3297	}
3298	free(buf);
3299
3300	memset(&hints, 0, sizeof(hints));
3301	hints.ai_family = AF_INET6;
3302	hints.ai_socktype = SOCK_DGRAM; /*dummy*/
3303	hints.ai_flags = AI_NUMERICHOST;
3304	if (getaddrinfo(s, "0", &hints, &res) == 0) {
3305		n = calloc(1, sizeof(struct node_host));
3306		if (n == NULL)
3307			err(1, "address: calloc");
3308		n->af = AF_INET6;
3309		n->addr.addr_dyn = NULL;
3310		memcpy(&n->addr.addr,
3311		    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
3312		    sizeof(n->addr.addr));
3313		n->ifindex = ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
3314		set_ipmask(n, v6mask);
3315		freeaddrinfo(res);
3316		n->next = NULL;
3317		n->tail = n;
3318		return (n);
3319	}
3320
3321	memset(&hints, 0, sizeof(hints));
3322	hints.ai_family = PF_UNSPEC;
3323	hints.ai_socktype = SOCK_STREAM; /* DUMMY */
3324	error = getaddrinfo(s, NULL, &hints, &res0);
3325	if (error) {
3326		yyerror("cannot resolve %s: %s",
3327		    s, gai_strerror(error));
3328		return (NULL);
3329	}
3330	for (res = res0; res; res = res->ai_next) {
3331		if (res->ai_family != AF_INET &&
3332		    res->ai_family != AF_INET6)
3333			continue;
3334		n = calloc(1, sizeof(struct node_host));
3335		if (n == NULL)
3336			err(1, "address: calloc");
3337		n->af = res->ai_family;
3338		n->addr.addr_dyn = NULL;
3339		if (res->ai_family == AF_INET) {
3340			memcpy(&n->addr.addr,
3341			    &((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr,
3342			    sizeof(struct in_addr));
3343			set_ipmask(n, v4mask);
3344		} else {
3345			memcpy(&n->addr.addr,
3346			    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr,
3347			    sizeof(struct in6_addr));
3348			n->ifindex =
3349			    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
3350			set_ipmask(n, v6mask);
3351		}
3352		n->next = NULL;
3353		n->tail = n;
3354		if (h == NULL)
3355			h = n;
3356		else {
3357			h->tail->next = n;
3358			h->tail = n;
3359		}
3360	}
3361	freeaddrinfo(res0);
3362	if (h == NULL) {
3363		yyerror("no IP address found for %s", s);
3364		return (NULL);
3365	}
3366	return (h);
3367}
3368
3369int
3370atoul(char *s, u_long *ulvalp)
3371{
3372	u_long ulval;
3373	char *ep;
3374
3375	errno = 0;
3376	ulval = strtoul(s, &ep, 0);
3377	if (s[0] == '\0' || *ep != '\0')
3378		return (-1);
3379	if (errno == ERANGE && ulval == ULONG_MAX)
3380		return (-1);
3381	*ulvalp = ulval;
3382	return (0);
3383}
3384
3385int
3386getservice(char *n)
3387{
3388	struct servent *s;
3389	u_long ulval;
3390
3391	if (atoul(n, &ulval) == 0) {
3392		if (ulval > 65535) {
3393			yyerror("illegal port value %d", ulval);
3394			return (-1);
3395		}
3396		return (htons(ulval));
3397	} else {
3398		s = getservbyname(n, "tcp");
3399		if (s == NULL)
3400			s = getservbyname(n, "udp");
3401		if (s == NULL) {
3402			yyerror("unknown port %s", n);
3403			return (-1);
3404		}
3405		return (s->s_port);
3406	}
3407}
3408
3409u_int16_t
3410parseicmpspec(char *w, sa_family_t af)
3411{
3412	const struct icmpcodeent *p;
3413	u_long ulval;
3414	u_int8_t icmptype;
3415
3416	if (af == AF_INET)
3417		icmptype = returnicmpdefault >> 8;
3418	else
3419		icmptype = returnicmp6default >> 8;
3420
3421	if (atoul(w, &ulval) == -1) {
3422		if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
3423			yyerror("unknown icmp code %s", w);
3424			return (0);
3425		}
3426		ulval = p->code;
3427	}
3428	return (icmptype << 8 | ulval);
3429}
3430