parse.y revision 1.302
1/*	$OpenBSD: parse.y,v 1.302 2003/02/02 23:22:07 henning Exp $	*/
2
3/*
4 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
5 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27%{
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <sys/ioctl.h>
31#include <net/if.h>
32#include <netinet/in.h>
33#include <netinet/in_systm.h>
34#include <netinet/ip.h>
35#include <netinet/ip_icmp.h>
36#include <netinet/icmp6.h>
37#include <net/pfvar.h>
38#include <arpa/inet.h>
39#include <altq/altq.h>
40#include <altq/altq_cbq.h>
41#include <altq/altq_priq.h>
42#include <altq/altq_hfsc.h>
43
44#include <stdio.h>
45#include <stdlib.h>
46#include <netdb.h>
47#include <stdarg.h>
48#include <errno.h>
49#include <string.h>
50#include <ctype.h>
51#include <err.h>
52#include <pwd.h>
53#include <grp.h>
54#include <md5.h>
55
56#include "pfctl_parser.h"
57#include "pfctl.h"
58
59static struct pfctl	*pf = NULL;
60static FILE		*fin = NULL;
61static int		 debug = 0;
62static int		 lineno = 1;
63static int		 errors = 0;
64static int		 rulestate = 0;
65static u_int16_t	 returnicmpdefault =
66			    (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
67static u_int16_t	 returnicmp6default =
68			    (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
69static int		 blockpolicy = PFRULE_DROP;
70static int		 require_order = 1;
71
72enum {
73	PFCTL_STATE_NONE,
74	PFCTL_STATE_OPTION,
75	PFCTL_STATE_SCRUB,
76	PFCTL_STATE_QUEUE,
77	PFCTL_STATE_NAT,
78	PFCTL_STATE_FILTER
79};
80
81struct node_proto {
82	u_int8_t		 proto;
83	struct node_proto	*next;
84	struct node_proto	*tail;
85};
86
87struct node_port {
88	u_int16_t		 port[2];
89	u_int8_t		 op;
90	struct node_port	*next;
91	struct node_port	*tail;
92};
93
94struct node_uid {
95	uid_t			 uid[2];
96	u_int8_t		 op;
97	struct node_uid		*next;
98	struct node_uid		*tail;
99};
100
101struct node_gid {
102	gid_t			 gid[2];
103	u_int8_t		 op;
104	struct node_gid		*next;
105	struct node_gid		*tail;
106};
107
108struct node_icmp {
109	u_int8_t		 code;
110	u_int8_t		 type;
111	u_int8_t		 proto;
112	struct node_icmp	*next;
113	struct node_icmp	*tail;
114};
115
116enum	{ PF_STATE_OPT_MAX=0, PF_STATE_OPT_TIMEOUT=1 };
117struct node_state_opt {
118	int			 type;
119	union {
120		u_int32_t	 max_states;
121		struct {
122			int		number;
123			u_int32_t	seconds;
124		}		 timeout;
125	}			 data;
126	struct node_state_opt	*next;
127	struct node_state_opt	*tail;
128};
129
130struct peer {
131	struct node_host	*host;
132	struct node_port	*port;
133};
134
135struct node_queue {
136	char			 queue[PF_QNAME_SIZE];
137	char			 parent[PF_QNAME_SIZE];
138	char			 ifname[IFNAMSIZ];
139	int			 scheduler;
140	struct node_queue	*next;
141	struct node_queue	*tail;
142}	*queues = NULL;
143
144struct node_queue_opt {
145	int			 qtype;
146	union {
147		struct cbq_opts		cbq_opts;
148		struct priq_opts	priq_opts;
149	}			 data;
150};
151
152struct node_queue_bw {
153	u_int32_t	bw_absolute;
154	u_int16_t	bw_percent;
155};
156
157struct node_qassign {
158	char		*qname;
159	char		*pqname;
160};
161
162struct filter_opts {
163	int			 marker;
164#define FOM_FLAGS	0x01
165#define FOM_ICMP	0x02
166#define FOM_TOS		0x04
167#define FOM_KEEP	0x08
168	struct node_uid		*uid;
169	struct node_gid		*gid;
170	struct {
171		u_int8_t	 b1;
172		u_int8_t	 b2;
173		u_int16_t	 w;
174		u_int16_t	 w2;
175	} flags;
176	struct node_icmp	*icmpspec;
177	u_int32_t		 tos;
178	struct {
179		int			 action;
180		struct node_state_opt	*options;
181	} keep;
182	int			 fragment;
183	int			 allowopts;
184	char			*label;
185	struct node_qassign	 queues;
186} filter_opts;
187
188struct scrub_opts {
189	int			marker;
190#define SOM_MINTTL	0x01
191#define SOM_MAXMSS	0x02
192#define SOM_FRAGCACHE	0x04
193	int			nodf;
194	int			minttl;
195	int			maxmss;
196	int			fragcache;
197} scrub_opts;
198
199struct queue_opts {
200	int			marker;
201#define QOM_BWSPEC	0x01
202#define QOM_SCHEDULER	0x02
203#define QOM_PRIORITY	0x04
204#define QOM_TBRSIZE	0x08
205#define QOM_QLIMIT	0x10
206	struct node_queue_bw	queue_bwspec;
207	struct node_queue_opt	scheduler;
208	int			priority;
209	int			tbrsize;
210	int			qlimit;
211} queue_opts;
212
213struct table_opts {
214	int			flags;
215	int			init_addr;
216} table_opts;
217
218int	yyerror(char *, ...);
219int	disallow_table(struct node_host *, char *);
220int	rule_consistent(struct pf_rule *);
221int	nat_consistent(struct pf_rule *);
222int	rdr_consistent(struct pf_rule *);
223int	yyparse(void);
224void	expand_rdr(struct pf_rule *, struct node_if *, struct node_proto *,
225	    struct node_host *, struct node_host *, struct node_host *);
226void	expand_nat(struct pf_rule *, struct node_if *, struct node_proto *,
227	    struct node_host *, struct node_port *,
228	    struct node_host *, struct node_port *, struct node_host *);
229void	expand_label_str(char *, const char *, const char *);
230void	expand_label_if(const char *, char *, const char *);
231void	expand_label_addr(const char *, char *, u_int8_t, struct node_host *);
232void	expand_label_port(const char *, char *, struct node_port *);
233void	expand_label_proto(const char *, char *, u_int8_t);
234void	expand_label_nr(const char *, char *);
235void	expand_label(char *, const char *, u_int8_t, struct node_host *,
236	    struct node_port *, struct node_host *, struct node_port *,
237	    u_int8_t);
238void	expand_rule(struct pf_rule *, struct node_if *, struct node_host *,
239	    struct node_proto *, struct node_host *, struct node_port *,
240	    struct node_host *, struct node_port *, struct node_uid *,
241	    struct node_gid *, struct node_icmp *);
242int	expand_altq(struct pf_altq *, struct node_if *, struct node_queue *,
243	    struct node_queue_bw bwspec);
244int	expand_queue(struct pf_altq *, struct node_queue *,
245	    struct node_queue_bw);
246
247int	 check_rulestate(int);
248int	 kw_cmp(const void *, const void *);
249int	 lookup(char *);
250int	 lgetc(FILE *);
251int	 lungetc(int);
252int	 findeol(void);
253int	 yylex(void);
254int	 atoul(char *, u_long *);
255int	 getservice(char *);
256
257struct sym {
258	struct sym	*next;
259	int		 used;
260	char		*nam;
261	char		*val;
262};
263struct sym	*symhead = NULL;
264
265int	 symset(const char *, const char *);
266char	*symget(const char *);
267
268void	 decide_address_family(struct node_host *,
269	    sa_family_t *);
270void	 remove_invalid_hosts(struct node_host **,
271	    sa_family_t *);
272u_int16_t parseicmpspec(char *, sa_family_t);
273
274typedef struct {
275	union {
276		u_int32_t		 number;
277		int			 i;
278		char			*string;
279		struct {
280			u_int8_t	 b1;
281			u_int8_t	 b2;
282			u_int16_t	 w;
283			u_int16_t	 w2;
284		}			 b;
285		struct range {
286			int		 a;
287			int		 b;
288			int		 t;
289		}			 range;
290		struct node_if		*interface;
291		struct node_proto	*proto;
292		struct node_icmp	*icmp;
293		struct node_host	*host;
294		struct node_port	*port;
295		struct node_uid		*uid;
296		struct node_gid		*gid;
297		struct node_state_opt	*state_opt;
298		struct peer		 peer;
299		struct {
300			struct peer	 src, dst;
301		}			 fromto;
302		struct pf_poolhashkey	*hashkey;
303		struct {
304			struct node_host	*host;
305			u_int8_t		 rt;
306			u_int8_t		 pool_opts;
307			sa_family_t		 af;
308			struct pf_poolhashkey	*key;
309		}			 route;
310		struct redirection {
311			struct node_host	*host;
312			struct range		 rport;
313		}			*redirection;
314		struct {
315			int			 type;
316			struct pf_poolhashkey	*key;
317		}			 pooltype;
318		struct {
319			int			 action;
320			struct node_state_opt	*options;
321		}			 keep_state;
322		struct {
323			u_int8_t	 log;
324			u_int8_t	 quick;
325		}			 logquick;
326		struct node_queue	*queue;
327		struct node_queue_opt	 queue_options;
328		struct node_queue_bw	 queue_bwspec;
329		struct node_qassign	 qassign;
330		struct filter_opts	 filter_opts;
331		struct queue_opts	 queue_opts;
332		struct scrub_opts	 scrub_opts;
333		struct table_opts	 table_opts;
334	} v;
335	int lineno;
336} YYSTYPE;
337
338#define PREPARE_ANCHOR_RULE(r, a)				\
339	do {							\
340		memset(&(r), 0, sizeof(r));			\
341		if (strlcpy(r.anchorname, (a),			\
342		    sizeof(r.anchorname)) >=			\
343		    sizeof(r.anchorname)) {			\
344			yyerror("anchor name '%s' too long",	\
345			    (a));				\
346			YYERROR;				\
347		}						\
348	} while (0)
349
350%}
351
352%token	PASS BLOCK SCRUB RETURN IN OUT LOG LOGALL QUICK ON FROM TO FLAGS
353%token	RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
354%token	ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
355%token	MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
356%token	NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
357%token	FRAGNORM FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
358%token	SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY
359%token	REQUIREORDER YES
360%token	ANTISPOOF FOR
361%token	BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT
362%token	ALTQ CBQ PRIQ BANDWIDTH TBRSIZE
363%token	QUEUE PRIORITY QLIMIT
364%token	DEFAULT CONTROL BORROW RED ECN RIO
365%token	<v.string>		STRING
366%token	<v.i>			PORTUNARY PORTBINARY
367%type	<v.interface>		interface if_list if_item_not if_item
368%type	<v.number>		number port icmptype icmp6type uid gid
369%type	<v.number>		tos
370%type	<v.i>			no dir log af fragcache
371%type	<v.i>			staticport
372%type	<v.b>			action flags flag blockspec
373%type	<v.range>		dport rport
374%type	<v.hashkey>		hashkey
375%type	<v.pooltype>		pooltype
376%type	<v.proto>		proto proto_list proto_item
377%type	<v.icmp>		icmpspec
378%type	<v.icmp>		icmp_list icmp_item
379%type	<v.icmp>		icmp6_list icmp6_item
380%type	<v.fromto>		fromto
381%type	<v.peer>		ipportspec
382%type	<v.host>		ipspec xhost host address host_list
383%type	<v.host>		redir_host_list redirspec
384%type	<v.host>		route_host route_host_list routespec
385%type	<v.port>		portspec port_list port_item
386%type	<v.uid>			uids uid_list uid_item
387%type	<v.gid>			gids gid_list gid_item
388%type	<v.route>		route
389%type	<v.redirection>		redirection redirpool
390%type	<v.string>		label string
391%type	<v.keep_state>		keep
392%type	<v.state_opt>		state_opt_spec state_opt_list state_opt_item
393%type	<v.logquick>		logquick
394%type	<v.interface>		antispoof_ifspc antispoof_iflst
395%type	<v.qassign>		qname
396%type	<v.queue>		qassign qassign_list qassign_item
397%type	<v.queue_options>	scheduler
398%type	<v.number>		cbqflags_list cbqflags_item
399%type	<v.number>		priqflags_list priqflags_item
400%type	<v.queue_bwspec>	bandwidth
401%type	<v.filter_opts>		filter_opts filter_opt filter_opts_l
402%type	<v.queue_opts>		queue_opts queue_opt queue_opts_l
403%type	<v.scrub_opts>		scrub_opts scrub_opt scrub_opts_l
404%type	<v.table_opts>		table_opts table_opt table_opts_l
405%%
406
407ruleset		: /* empty */
408		| ruleset '\n'
409		| ruleset option '\n'
410		| ruleset scrubrule '\n'
411		| ruleset natrule '\n'
412		| ruleset binatrule '\n'
413		| ruleset rdrrule '\n'
414		| ruleset pfrule '\n'
415		| ruleset anchorrule '\n'
416		| ruleset altqif '\n'
417		| ruleset queuespec '\n'
418		| ruleset varset '\n'
419		| ruleset antispoof '\n'
420		| ruleset tabledef '\n'
421		| ruleset error '\n'		{ errors++; }
422		;
423
424option		: SET OPTIMIZATION STRING		{
425			if (pf->opts & PF_OPT_VERBOSE)
426				printf("set optimization %s\n", $3);
427			if (check_rulestate(PFCTL_STATE_OPTION))
428				YYERROR;
429			if (pfctl_set_optimization(pf, $3) != 0) {
430				yyerror("unknown optimization %s", $3);
431				YYERROR;
432			}
433		}
434		| SET TIMEOUT timeout_spec
435		| SET TIMEOUT '{' timeout_list '}'
436		| SET LIMIT limit_spec
437		| SET LIMIT '{' limit_list '}'
438		| SET LOGINTERFACE STRING		{
439			if (pf->opts & PF_OPT_VERBOSE)
440				printf("set loginterface %s\n", $3);
441			if (check_rulestate(PFCTL_STATE_OPTION))
442				YYERROR;
443			if (pfctl_set_logif(pf, $3) != 0) {
444				yyerror("error setting loginterface %s", $3);
445				YYERROR;
446			}
447		}
448		| SET BLOCKPOLICY DROP	{
449			if (pf->opts & PF_OPT_VERBOSE)
450				printf("set block-policy drop\n");
451			if (check_rulestate(PFCTL_STATE_OPTION))
452				YYERROR;
453			blockpolicy = PFRULE_DROP;
454		}
455		| SET BLOCKPOLICY RETURN {
456			if (pf->opts & PF_OPT_VERBOSE)
457				printf("set block-policy return\n");
458			if (check_rulestate(PFCTL_STATE_OPTION))
459				YYERROR;
460			blockpolicy = PFRULE_RETURN;
461		}
462		| SET REQUIREORDER YES {
463			if (pf->opts & PF_OPT_VERBOSE)
464				printf("set require-order yes\n");
465			require_order = 1;
466		}
467		| SET REQUIREORDER NO {
468			if (pf->opts & PF_OPT_VERBOSE)
469				printf("set require-order no\n");
470			require_order = 0;
471		}
472		;
473
474string		: string STRING				{
475			if (asprintf(&$$, "%s %s", $1, $2) == -1)
476				err(1, "string: asprintf");
477			free($1);
478			free($2);
479		}
480		| STRING
481		;
482
483varset		: STRING PORTUNARY string		{
484			if (pf->opts & PF_OPT_VERBOSE)
485				printf("%s = \"%s\"\n", $1, $3);
486			if (symset($1, $3) == -1)
487				err(1, "cannot store variable %s", $1);
488		}
489		;
490
491anchorrule	: ANCHOR string	dir interface af proto fromto {
492			struct pf_rule	r;
493
494			if (check_rulestate(PFCTL_STATE_FILTER))
495				YYERROR;
496
497			PREPARE_ANCHOR_RULE(r, $2);
498			r.direction = $3;
499			r.af = $5;
500
501			decide_address_family($7.src.host, &r.af);
502			decide_address_family($7.dst.host, &r.af);
503
504			expand_rule(&r, $4, NULL, $6,
505			    $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
506			    0, 0, 0);
507		}
508		| NATANCHOR string interface af proto fromto {
509			struct pf_rule	r;
510
511			if (check_rulestate(PFCTL_STATE_NAT))
512				YYERROR;
513
514			PREPARE_ANCHOR_RULE(r, $2);
515			r.action = PF_NAT;
516			r.af = $4;
517
518			decide_address_family($6.src.host, &r.af);
519			decide_address_family($6.dst.host, &r.af);
520
521			expand_nat(&r, $3, $5, $6.src.host, $6.src.port,
522			    $6.dst.host, $6.dst.port, NULL);
523		}
524		| RDRANCHOR string interface af proto fromto {
525			struct pf_rule	r;
526
527			if (check_rulestate(PFCTL_STATE_NAT))
528				YYERROR;
529
530			PREPARE_ANCHOR_RULE(r, $2);
531			r.action = PF_RDR;
532			r.af = $4;
533
534			decide_address_family($6.src.host, &r.af);
535			decide_address_family($6.dst.host, &r.af);
536
537			if ($6.src.port != NULL) {
538				yyerror("source port parameter not supported"
539				    " in rdr-anchor");
540				YYERROR;
541			}
542			if ($6.dst.port != NULL) {
543				if ($6.dst.port->next != NULL) {
544					yyerror("destination port list expansion"
545					    " not supported in rdr-anchor");
546					YYERROR;
547				} else if ($6.dst.port->op != PF_OP_EQ) {
548					yyerror("destination port operators"
549					    " not supported in rdr-anchor");
550					YYERROR;
551				}
552				r.dst.port[0] = $6.dst.port->port[0];
553				r.dst.port[1] = $6.dst.port->port[1];
554				r.dst.port_op = $6.dst.port->op;
555			}
556
557			expand_rdr(&r, $3, $5, $6.src.host, $6.dst.host, NULL);
558		}
559		| BINATANCHOR string interface af proto fromto {
560			struct pf_rule	r;
561
562			if (check_rulestate(PFCTL_STATE_NAT))
563				YYERROR;
564
565			PREPARE_ANCHOR_RULE(r, $2);
566			r.action = PF_BINAT;
567			r.af = $4;
568			if ($5 != NULL) {
569				if ($5->next != NULL) {
570					yyerror("proto list expansion"
571					    " not supported in binat-anchor");
572					YYERROR;
573				}
574				r.proto = $5->proto;
575				free($5);
576			}
577
578			if ($6.src.host != NULL || $6.src.port != NULL ||
579			    $6.dst.host != NULL || $6.dst.port != NULL) {
580				yyerror("fromto parameter not supported"
581				    " in binat-anchor");
582				YYERROR;
583			}
584
585			decide_address_family($6.src.host, &r.af);
586			decide_address_family($6.dst.host, &r.af);
587
588			pfctl_add_rule(pf, &r);
589		}
590		;
591
592scrubrule	: SCRUB dir logquick interface af fromto scrub_opts
593		{
594			struct pf_rule	r;
595
596			if (check_rulestate(PFCTL_STATE_SCRUB))
597				YYERROR;
598
599			memset(&r, 0, sizeof(r));
600
601			r.action = PF_SCRUB;
602			r.direction = $2;
603
604			r.log = $3.log;
605			if ($3.quick) {
606				yyerror("scrub rules do not support 'quick'");
607				YYERROR;
608			}
609
610			if ($4) {
611				if ($4->not) {
612					yyerror("scrub rules do not support "
613					    "'! <if>'");
614					YYERROR;
615				}
616			}
617			r.af = $5;
618			if ($7.nodf)
619				r.rule_flag |= PFRULE_NODF;
620			if ($7.minttl)
621				r.min_ttl = $7.minttl;
622			if ($7.maxmss)
623				r.max_mss = $7.maxmss;
624			if ($7.fragcache)
625				r.rule_flag |= $7.fragcache;
626
627			expand_rule(&r, $4, NULL, NULL,
628			    $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
629			    NULL, NULL, NULL);
630		}
631		;
632
633scrub_opts	:	{
634			bzero(&scrub_opts, sizeof scrub_opts);
635		}
636		  scrub_opts_l
637			{ $$ = scrub_opts; }
638		| /* empty */ {
639			bzero(&scrub_opts, sizeof scrub_opts);
640			$$ = scrub_opts;
641		}
642		;
643
644scrub_opts_l	: scrub_opts_l scrub_opt
645		| scrub_opt
646		;
647
648scrub_opt	: NODF	{
649			if (scrub_opts.nodf) {
650				yyerror("nodf cannot be respecified");
651				YYERROR;
652			}
653			scrub_opts.nodf = 1;
654		}
655		| MINTTL number {
656			if (scrub_opts.marker & SOM_MINTTL) {
657				yyerror("minttl cannot be respecified");
658				YYERROR;
659			}
660			if ($2 > 255) {
661				yyerror("illegal min-ttl value %d", $2);
662				YYERROR;
663			}
664			scrub_opts.marker |= SOM_MINTTL;
665			scrub_opts.minttl = $2;
666		}
667		| MAXMSS number {
668			if (scrub_opts.marker & SOM_MAXMSS) {
669				yyerror("maxmss cannot be respecified");
670				YYERROR;
671			}
672			scrub_opts.marker |= SOM_MAXMSS;
673			scrub_opts.maxmss = $2;
674		}
675		| fragcache {
676			if (scrub_opts.marker & SOM_FRAGCACHE) {
677				yyerror("fragcache cannot be respecified");
678				YYERROR;
679			}
680			scrub_opts.marker |= SOM_FRAGCACHE;
681			scrub_opts.fragcache = $1;
682		}
683		;
684
685fragcache	: FRAGMENT FRAGNORM	{ $$ = 0; /* default */ }
686		| FRAGMENT FRAGCROP	{ $$ = PFRULE_FRAGCROP; }
687		| FRAGMENT FRAGDROP	{ $$ = PFRULE_FRAGDROP; }
688		;
689
690antispoof	: ANTISPOOF logquick antispoof_ifspc af {
691			struct pf_rule		 r;
692			struct node_host	*h = NULL;
693			struct node_if		*i, *j;
694
695			if (check_rulestate(PFCTL_STATE_FILTER))
696				YYERROR;
697
698			for (i = $3; i; i = i->next) {
699				memset(&r, 0, sizeof(r));
700
701				r.action = PF_DROP;
702				r.direction = PF_IN;
703				r.log = $2.log;
704				r.quick = $2.quick;
705				r.af = $4;
706
707				j = calloc(1, sizeof(struct node_if));
708				if (j == NULL)
709					err(1, "antispoof: calloc");
710				if (strlcpy(j->ifname, i->ifname,
711				    sizeof(j->ifname)) >= sizeof(j->ifname)) {
712					free(j);
713					yyerror("interface name too long");
714					YYERROR;
715				}
716				j->not = 1;
717				h = ifa_lookup(j->ifname, PFCTL_IFLOOKUP_NET);
718
719				expand_rule(&r, j, NULL, NULL, h, NULL, NULL,
720				    NULL, NULL, NULL, NULL);
721
722				if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
723					memset(&r, 0, sizeof(r));
724
725					r.action = PF_DROP;
726					r.direction = PF_IN;
727					r.log = $2.log;
728					r.quick = $2.quick;
729					r.af = $4;
730
731					h = ifa_lookup(i->ifname,
732					    PFCTL_IFLOOKUP_HOST);
733
734					expand_rule(&r, NULL, NULL, NULL, h,
735					    NULL, NULL, NULL, NULL, NULL, NULL);
736				}
737			}
738		}
739		;
740
741antispoof_ifspc	: FOR if_item			{ $$ = $2; }
742		| FOR '{' antispoof_iflst '}'	{ $$ = $3; }
743		;
744
745antispoof_iflst	: if_item			{ $$ = $1; }
746		| antispoof_iflst comma if_item	{
747			$1->tail->next = $3;
748			$1->tail = $3;
749			$$ = $1;
750		}
751		;
752
753tabledef	: TABLE PORTUNARY STRING PORTUNARY table_opts {
754			if ($2 != PF_OP_LT || $4 != PF_OP_GT)
755				YYERROR;
756			if (strlen($3) >= PF_TABLE_NAME_SIZE) {
757				yyerror("table name too long, max %d chars",
758				    PF_TABLE_NAME_SIZE - 1);
759				YYERROR;
760			}
761			pfctl_define_table($3, $5.flags, $5.init_addr,
762			    pf->opts & PF_OPT_NOACTION);
763		}
764		;
765
766table_opts	:	{
767			bzero(&table_opts, sizeof table_opts);
768		}
769		   table_opts_l
770			{ $$ = table_opts; }
771		| /* empty */
772			{
773			bzero(&table_opts, sizeof table_opts);
774			$$ = table_opts;
775		}
776		;
777
778table_opts_l	: table_opts_l table_opt
779		| table_opt
780		;
781
782table_opt	: STRING
783			{
784			if (!strcmp($1, "const"))
785				table_opts.flags |= PFR_TFLAG_CONST;
786			else if (!strcmp($1, "persist"))
787				table_opts.flags |= PFR_TFLAG_PERSIST;
788			else
789				YYERROR;
790		}
791		| '{' tableaddrs '}'	{ table_opts.init_addr = 1; }
792		| FILENAME STRING	{
793			pfctl_append_file($2);
794			table_opts.init_addr = 1;
795		}
796		;
797
798tableaddrs	: /* empty */
799		| tableaddrs tableaddr comma
800
801tableaddr	: STRING {
802			pfctl_append_addr($1, -1, 0);
803		}
804		| STRING '/' number {
805			pfctl_append_addr($1, $3, 0);
806		}
807		| '!' STRING {
808			pfctl_append_addr($2, -1, 1);
809		}
810		| '!' STRING '/' number {
811			pfctl_append_addr($2, $4, 1);
812		}
813		;
814
815altqif		: ALTQ interface queue_opts QUEUE qassign {
816			struct pf_altq	a;
817
818			if (check_rulestate(PFCTL_STATE_QUEUE))
819				YYERROR;
820
821			memset(&a, 0, sizeof(a));
822			if ($3.scheduler.qtype == ALTQT_NONE) {
823				yyerror("no scheduler specified!");
824				YYERROR;
825			}
826			a.scheduler = $3.scheduler.qtype;
827			switch (a.scheduler) {
828			case ALTQT_CBQ:
829				a.pq_u.cbq_opts =
830				    $3.scheduler.data.cbq_opts;
831				break;
832			case ALTQT_PRIQ:
833				a.pq_u.priq_opts =
834				    $3.scheduler.data.priq_opts;
835				break;
836			default:
837				break;
838			}
839			a.qlimit = $3.qlimit;
840			a.tbrsize = $3.tbrsize;
841			if ($5 == NULL) {
842				yyerror("no child queues specified");
843				YYERROR;
844			}
845			if (expand_altq(&a, $2, $5, $3.queue_bwspec))
846				YYERROR;
847		}
848		;
849
850queuespec	: QUEUE STRING queue_opts qassign {
851			struct pf_altq	a;
852
853			if (check_rulestate(PFCTL_STATE_QUEUE))
854				YYERROR;
855
856			memset(&a, 0, sizeof(a));
857
858			if (strlcpy(a.qname, $2, sizeof(a.qname)) >=
859			    sizeof(a.qname)) {
860				yyerror("queue name too long (max "
861				    "%d chars)", PF_QNAME_SIZE-1);
862				YYERROR;
863			}
864			if ($3.tbrsize) {
865				yyerror("cannot specify tbrsize for queue");
866				YYERROR;
867			}
868			if ($3.priority > 255) {
869				yyerror("priority out of range: max 255");
870				YYERROR;
871			}
872			a.priority = $3.priority;
873			a.qlimit = $3.qlimit;
874			a.scheduler = $3.scheduler.qtype;
875			switch (a.scheduler) {
876			case ALTQT_CBQ:
877				a.pq_u.cbq_opts =
878				    $3.scheduler.data.cbq_opts;
879				break;
880			case ALTQT_PRIQ:
881				a.pq_u.priq_opts =
882				    $3.scheduler.data.priq_opts;
883				break;
884			default:
885				break;
886			}
887			if (expand_queue(&a, $4, $3.queue_bwspec))
888				YYERROR;
889		}
890		;
891
892queue_opts	:	{
893			bzero(&queue_opts, sizeof queue_opts);
894			queue_opts.priority = DEFAULT_PRIORITY;
895			queue_opts.qlimit = DEFAULT_QLIMIT;
896			queue_opts.scheduler.qtype = ALTQT_NONE;
897			queue_opts.queue_bwspec.bw_percent = 100;
898		}
899		  queue_opts_l
900			{ $$ = queue_opts; }
901		| /* empty */ {
902			bzero(&queue_opts, sizeof queue_opts);
903			queue_opts.priority = DEFAULT_PRIORITY;
904			queue_opts.qlimit = DEFAULT_QLIMIT;
905			queue_opts.scheduler.qtype = ALTQT_NONE;
906			queue_opts.queue_bwspec.bw_percent = 100;
907			$$ = queue_opts;
908		}
909		;
910
911queue_opts_l	: queue_opts_l queue_opt
912		| queue_opt
913		;
914
915queue_opt	: bandwidth	{
916			if (queue_opts.marker & QOM_BWSPEC) {
917				yyerror("bandwidth cannot be respecified");
918				YYERROR;
919			}
920			queue_opts.marker |= QOM_BWSPEC;
921			queue_opts.queue_bwspec = $1;
922		}
923		| PRIORITY number	{
924			if (queue_opts.marker & QOM_PRIORITY) {
925				yyerror("priority cannot be respecified");
926				YYERROR;
927			}
928			if ($2 > 255) {
929				yyerror("priority out of range: max 255");
930				YYERROR;
931			}
932			queue_opts.marker |= QOM_PRIORITY;
933			queue_opts.priority = $2;
934		}
935		| QLIMIT number	{
936			if (queue_opts.marker & QOM_QLIMIT) {
937				yyerror("qlimit cannot be respecified");
938				YYERROR;
939			}
940			if ($2 > 65535) {
941				yyerror("qlimit out of range: max 65535");
942				YYERROR;
943			}
944			queue_opts.marker |= QOM_QLIMIT;
945			queue_opts.qlimit = $2;
946		}
947		| scheduler	{
948			if (queue_opts.marker & QOM_SCHEDULER) {
949				yyerror("scheduler cannot be respecified");
950				YYERROR;
951			}
952			queue_opts.marker |= QOM_SCHEDULER;
953			queue_opts.scheduler = $1;
954		}
955		| TBRSIZE number	{
956			if (queue_opts.marker & QOM_TBRSIZE) {
957				yyerror("tbrsize cannot be respecified");
958				YYERROR;
959			}
960			if ($2 > 65535) {
961				yyerror("tbrsize too big: max 65535");
962				YYERROR;
963			}
964			queue_opts.marker |= QOM_TBRSIZE;
965			queue_opts.tbrsize = $2;
966		}
967		;
968
969bandwidth	: BANDWIDTH STRING {
970			double	 bps;
971			char	*cp;
972
973			$$.bw_percent = 0;
974
975			bps = strtod($2, &cp);
976			if (cp != NULL) {
977				if (!strcmp(cp, "b"))
978					; /* nothing */
979				else if (!strcmp(cp, "Kb"))
980					bps *= 1000;
981				else if (!strcmp(cp, "Mb"))
982					bps *= 1000 * 1000;
983				else if (!strcmp(cp, "Gb"))
984					bps *= 1000 * 1000 * 1000;
985				else if (!strcmp(cp, "%")) {
986					if (bps < 0 || bps > 100) {
987						yyerror("bandwidth spec "
988						    "out of range");
989						YYERROR;
990					}
991					$$.bw_percent = bps;
992					bps = 0;
993				} else {
994					yyerror("unknown unit %s", cp);
995					YYERROR;
996				}
997			}
998			$$.bw_absolute = (u_int32_t)bps;
999		}
1000
1001scheduler	: CBQ				{
1002			$$.qtype = ALTQT_CBQ;
1003			$$.data.cbq_opts.flags = 0;
1004		}
1005		| CBQ '(' cbqflags_list ')'	{
1006			$$.qtype = ALTQT_CBQ;
1007			$$.data.cbq_opts.flags = $3;
1008		}
1009		| PRIQ				{
1010			$$.qtype = ALTQT_PRIQ;
1011			$$.data.priq_opts.flags = 0;
1012		}
1013		| PRIQ '(' priqflags_list ')'	{
1014			$$.qtype = ALTQT_PRIQ;
1015			$$.data.priq_opts.flags = $3;
1016		}
1017		;
1018
1019cbqflags_list	: cbqflags_item				{ $$ |= $1; }
1020		| cbqflags_list comma cbqflags_item	{ $$ |= $3; }
1021		;
1022
1023cbqflags_item	: DEFAULT	{ $$ = CBQCLF_DEFCLASS; }
1024		| CONTROL	{ $$ = CBQCLF_CTLCLASS; }
1025		| BORROW	{ $$ = CBQCLF_BORROW; }
1026		| RED		{ $$ = CBQCLF_RED; }
1027		| ECN		{ $$ = CBQCLF_RED|CBQCLF_ECN; }
1028		| RIO		{ $$ = CBQCLF_RIO; }
1029		;
1030
1031priqflags_list	: priqflags_item			{ $$ |= $1; }
1032		| priqflags_list comma priqflags_item	{ $$ |= $3; }
1033		;
1034
1035priqflags_item	: DEFAULT	{ $$ = PRCF_DEFAULTCLASS; }
1036		| RED		{ $$ = PRCF_RED; }
1037		| ECN		{ $$ = PRCF_RED|PRCF_ECN; }
1038		| RIO		{ $$ = PRCF_RIO; }
1039		;
1040
1041qassign		: /* empty */		{ $$ = NULL; }
1042		| qassign_item		{ $$ = $1; }
1043		| '{' qassign_list '}'	{ $$ = $2; }
1044		;
1045
1046qassign_list	: qassign_item			{ $$ = $1; }
1047		| qassign_list comma qassign_item	{
1048			$1->tail->next = $3;
1049			$1->tail = $3;
1050			$$ = $1;
1051		}
1052		;
1053
1054qassign_item	: STRING			{
1055			$$ = calloc(1, sizeof(struct node_queue));
1056			if ($$ == NULL)
1057				err(1, "qassign_item: calloc");
1058			if (strlcpy($$->queue, $1, sizeof($$->queue)) >=
1059			    sizeof($$->queue)) {
1060				free($$);
1061				yyerror("queue name '%s' too long (max "
1062				    "%d chars)", $1, sizeof($$->queue)-1);
1063				YYERROR;
1064			}
1065			$$->next = NULL;
1066			$$->tail = $$;
1067		}
1068		;
1069
1070pfrule		: action dir logquick interface route af proto fromto
1071		  filter_opts
1072		{
1073			struct pf_rule		 r;
1074			struct node_state_opt	*o;
1075			struct node_proto	*proto;
1076
1077			if (check_rulestate(PFCTL_STATE_FILTER))
1078				YYERROR;
1079
1080			memset(&r, 0, sizeof(r));
1081
1082			r.action = $1.b1;
1083			switch ($1.b2) {
1084			case PFRULE_RETURNRST:
1085				r.rule_flag |= PFRULE_RETURNRST;
1086				r.return_ttl = $1.w;
1087				break;
1088			case PFRULE_RETURNICMP:
1089				r.rule_flag |= PFRULE_RETURNICMP;
1090				r.return_icmp = $1.w;
1091				r.return_icmp6 = $1.w2;
1092				break;
1093			case PFRULE_RETURN:
1094				r.rule_flag |= PFRULE_RETURN;
1095				r.return_icmp = $1.w;
1096				r.return_icmp6 = $1.w2;
1097				break;
1098			}
1099			r.direction = $2;
1100			r.log = $3.log;
1101			r.quick = $3.quick;
1102
1103			r.af = $6;
1104			r.flags = $9.flags.b1;
1105			r.flagset = $9.flags.b2;
1106
1107			if ($9.flags.b1 || $9.flags.b2) {
1108				for (proto = $7; proto != NULL &&
1109				    proto->proto != IPPROTO_TCP;
1110				    proto = proto->next)
1111					;	/* nothing */
1112				if (proto == NULL && $7 != NULL) {
1113					yyerror("flags only apply to tcp");
1114					YYERROR;
1115				}
1116			}
1117
1118			r.tos = $9.tos;
1119			r.keep_state = $9.keep.action;
1120			o = $9.keep.options;
1121			while (o) {
1122				struct node_state_opt	*p = o;
1123
1124				switch (o->type) {
1125				case PF_STATE_OPT_MAX:
1126					if (r.max_states) {
1127						yyerror("state option 'max' "
1128						    "multiple definitions");
1129						YYERROR;
1130					}
1131					r.max_states = o->data.max_states;
1132					break;
1133				case PF_STATE_OPT_TIMEOUT:
1134					if (r.timeout[o->data.timeout.number]) {
1135						yyerror("state timeout %s "
1136						    "multiple definitions",
1137						    pf_timeouts[o->data.
1138						    timeout.number].name);
1139						YYERROR;
1140					}
1141					r.timeout[o->data.timeout.number] =
1142					    o->data.timeout.seconds;
1143				}
1144				o = o->next;
1145				free(p);
1146			}
1147
1148			if ($9.fragment)
1149				r.rule_flag |= PFRULE_FRAGMENT;
1150			r.allow_opts = $9.allowopts;
1151
1152			decide_address_family($8.src.host, &r.af);
1153			decide_address_family($8.dst.host, &r.af);
1154
1155			if ($5.rt) {
1156				if (!r.direction) {
1157					yyerror("direction must be explicit "
1158					    "with rules that specify routing");
1159					YYERROR;
1160				}
1161				r.rt = $5.rt;
1162				r.rpool.opts = $5.pool_opts;
1163				if ($5.key != NULL)
1164					memcpy(&r.rpool.key, $5.key,
1165					    sizeof(struct pf_poolhashkey));
1166			}
1167
1168			if (r.rt && r.rt != PF_FASTROUTE) {
1169				decide_address_family($5.host, &r.af);
1170				remove_invalid_hosts(&$5.host, &r.af);
1171				if ($5.host == NULL) {
1172					yyerror("$5.host == NULL");
1173					YYERROR;
1174				}
1175				if ($5.host->next != NULL) {
1176					if (r.rpool.opts == PF_POOL_NONE)
1177						r.rpool.opts =
1178						    PF_POOL_ROUNDROBIN;
1179					if (r.rpool.opts !=
1180					    PF_POOL_ROUNDROBIN) {
1181						yyerror("r.rpool.opts must "
1182						    "be PF_POOL_ROUNDROBIN");
1183						YYERROR;
1184					}
1185				}
1186			}
1187
1188			if ($9.label) {
1189				if (strlcpy(r.label, $9.label,
1190				    sizeof(r.label)) >= sizeof(r.label)) {
1191					yyerror("rule label too long (max "
1192					    "%d chars)", sizeof(r.label)-1);
1193					YYERROR;
1194				}
1195				free($9.label);
1196			}
1197
1198			if ($9.queues.qname != NULL) {
1199				if (strlcpy(r.qname, $9.queues.qname,
1200				    sizeof(r.qname)) >= sizeof(r.qname)) {
1201					yyerror("rule qname too long (max "
1202					    "%d chars)", sizeof(r.qname)-1);
1203					YYERROR;
1204				}
1205				free($9.queues.qname);
1206			}
1207			if ($9.queues.pqname != NULL) {
1208				if (strlcpy(r.pqname, $9.queues.pqname,
1209				    sizeof(r.pqname)) >= sizeof(r.pqname)) {
1210					yyerror("rule pqname too long (max "
1211					    "%d chars)", sizeof(r.pqname)-1);
1212					YYERROR;
1213				}
1214				free($9.queues.pqname);
1215			}
1216
1217			expand_rule(&r, $4, $5.host, $7,
1218			    $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
1219			    $9.uid, $9.gid, $9.icmpspec);
1220		}
1221		;
1222
1223filter_opts	:	{ bzero(&filter_opts, sizeof filter_opts); }
1224		  filter_opts_l
1225			{ $$ = filter_opts; }
1226		| /* empty */	{
1227			bzero(&filter_opts, sizeof filter_opts);
1228			$$ = filter_opts;
1229		}
1230		;
1231
1232filter_opts_l	: filter_opts_l filter_opt
1233		| filter_opt
1234		;
1235
1236filter_opt	: USER uids {
1237			if (filter_opts.uid)
1238				$2->tail->next = filter_opts.uid;
1239			filter_opts.uid = $2;
1240		}
1241		| GROUP gids {
1242			if (filter_opts.gid)
1243				$2->tail->next = filter_opts.gid;
1244			filter_opts.gid = $2;
1245		}
1246		| flags {
1247			if (filter_opts.marker & FOM_FLAGS) {
1248				yyerror("flags cannot be redefined");
1249				YYERROR;
1250			}
1251			filter_opts.marker |= FOM_FLAGS;
1252			filter_opts.flags.b1 |= $1.b1;
1253			filter_opts.flags.b2 |= $1.b2;
1254			filter_opts.flags.w |= $1.w;
1255			filter_opts.flags.w2 |= $1.w2;
1256		}
1257		| icmpspec {
1258			if (filter_opts.marker & FOM_ICMP) {
1259				yyerror("icmp-type cannot be redefined");
1260				YYERROR;
1261			}
1262			filter_opts.marker |= FOM_ICMP;
1263			filter_opts.icmpspec = $1;
1264		}
1265		| tos {
1266			if (filter_opts.marker & FOM_TOS) {
1267				yyerror("tos cannot be redefined");
1268				YYERROR;
1269			}
1270			filter_opts.marker |= FOM_TOS;
1271			filter_opts.tos = $1;
1272		}
1273		| keep {
1274			if (filter_opts.marker & FOM_KEEP) {
1275				yyerror("modulate or keep cannot be redefined");
1276				YYERROR;
1277			}
1278			filter_opts.marker |= FOM_KEEP;
1279			filter_opts.keep.action = $1.action;
1280			filter_opts.keep.options = $1.options;
1281		}
1282		| FRAGMENT {
1283			filter_opts.fragment = 1;
1284		}
1285		| ALLOWOPTS {
1286			filter_opts.allowopts = 1;
1287		}
1288		| label	{
1289			if (filter_opts.label) {
1290				yyerror("label cannot be redefined");
1291				YYERROR;
1292			}
1293			filter_opts.label = $1;
1294		}
1295		| qname	{
1296			if (filter_opts.queues.qname) {
1297				yyerror("queue cannot be redefined");
1298				YYERROR;
1299			}
1300			filter_opts.queues = $1;
1301		}
1302		;
1303
1304action		: PASS			{ $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
1305		| BLOCK blockspec	{ $$ = $2; $$.b1 = PF_DROP; }
1306		;
1307
1308blockspec	: /* empty */		{
1309			$$.b2 = blockpolicy;
1310			$$.w = returnicmpdefault;
1311			$$.w2 = returnicmp6default;
1312		}
1313		| DROP			{
1314			$$.b2 = PFRULE_DROP;
1315			$$.w = 0;
1316			$$.w2 = 0;
1317		}
1318		| RETURNRST		{
1319			$$.b2 = PFRULE_RETURNRST;
1320			$$.w = 0;
1321			$$.w2 = 0;
1322		}
1323		| RETURNRST '(' TTL number ')'	{
1324			$$.b2 = PFRULE_RETURNRST;
1325			$$.w = $4;
1326			$$.w2 = 0;
1327		}
1328		| RETURNICMP		{
1329			$$.b2 = PFRULE_RETURNICMP;
1330			$$.w = returnicmpdefault;
1331			$$.w2 = returnicmp6default;
1332		}
1333		| RETURNICMP6		{
1334			$$.b2 = PFRULE_RETURNICMP;
1335			$$.w = returnicmpdefault;
1336			$$.w2 = returnicmp6default;
1337		}
1338		| RETURNICMP '(' STRING ')'	{
1339			$$.b2 = PFRULE_RETURNICMP;
1340			if (!($$.w = parseicmpspec($3, AF_INET)))
1341				YYERROR;
1342			$$.w2 = returnicmp6default;
1343		}
1344		| RETURNICMP6 '(' STRING ')'	{
1345			$$.b2 = PFRULE_RETURNICMP;
1346			$$.w = returnicmpdefault;
1347			if (!($$.w2 = parseicmpspec($3, AF_INET6)))
1348				YYERROR;
1349		}
1350		| RETURNICMP '(' STRING comma STRING ')' {
1351			$$.b2 = PFRULE_RETURNICMP;
1352			if (!($$.w = parseicmpspec($3, AF_INET)))
1353				YYERROR;
1354			if (!($$.w2 = parseicmpspec($5, AF_INET6)))
1355				YYERROR;
1356		}
1357		| RETURN {
1358			$$.b2 = PFRULE_RETURN;
1359			$$.w = returnicmpdefault;
1360			$$.w2 = returnicmp6default;
1361		}
1362		;
1363
1364dir		: /* empty */			{ $$ = 0; }
1365		| IN				{ $$ = PF_IN; }
1366		| OUT				{ $$ = PF_OUT; }
1367		;
1368
1369logquick	: /* empty */			{ $$.log = 0; $$.quick = 0; }
1370		| log				{ $$.log = $1; $$.quick = 0; }
1371		| QUICK				{ $$.log = 0; $$.quick = 1; }
1372		| log QUICK			{ $$.log = $1; $$.quick = 1; }
1373		| QUICK log			{ $$.log = $2; $$.quick = 1; }
1374		;
1375
1376log		: LOG				{ $$ = 1; }
1377		| LOGALL			{ $$ = 2; }
1378		;
1379
1380interface	: /* empty */			{ $$ = NULL; }
1381		| ON if_item_not		{ $$ = $2; }
1382		| ON '{' if_list '}'		{ $$ = $3; }
1383		;
1384
1385if_list		: if_item_not			{ $$ = $1; }
1386		| if_list comma if_item_not	{
1387			$1->tail->next = $3;
1388			$1->tail = $3;
1389			$$ = $1;
1390		}
1391		;
1392
1393if_item_not	: '!' if_item			{ $$ = $2; $$->not = 1; }
1394		| if_item			{ $$ = $1; }
1395
1396if_item		: STRING			{
1397			struct node_host	*n;
1398
1399			if ((n = ifa_exists($1)) == NULL) {
1400				yyerror("unknown interface %s", $1);
1401				YYERROR;
1402			}
1403			$$ = calloc(1, sizeof(struct node_if));
1404			if ($$ == NULL)
1405				err(1, "if_item: calloc");
1406			if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >=
1407			    sizeof($$->ifname)) {
1408				free($$);
1409				yyerror("interface name too long");
1410				YYERROR;
1411			}
1412			$$->ifa_flags = n->ifa_flags;
1413			$$->not = 0;
1414			$$->next = NULL;
1415			$$->tail = $$;
1416		}
1417		;
1418
1419af		: /* empty */			{ $$ = 0; }
1420		| INET				{ $$ = AF_INET; }
1421		| INET6				{ $$ = AF_INET6; }
1422
1423proto		: /* empty */			{ $$ = NULL; }
1424		| PROTO proto_item		{ $$ = $2; }
1425		| PROTO '{' proto_list '}'	{ $$ = $3; }
1426		;
1427
1428proto_list	: proto_item			{ $$ = $1; }
1429		| proto_list comma proto_item	{
1430			$1->tail->next = $3;
1431			$1->tail = $3;
1432			$$ = $1;
1433		}
1434		;
1435
1436proto_item	: STRING			{
1437			u_int8_t	pr;
1438			u_long		ulval;
1439
1440			if (atoul($1, &ulval) == 0) {
1441				if (ulval > 255) {
1442					yyerror("protocol outside range");
1443					YYERROR;
1444				}
1445				pr = (u_int8_t)ulval;
1446			} else {
1447				struct protoent	*p;
1448
1449				p = getprotobyname($1);
1450				if (p == NULL) {
1451					yyerror("unknown protocol %s", $1);
1452					YYERROR;
1453				}
1454				pr = p->p_proto;
1455			}
1456			if (pr == 0) {
1457				yyerror("proto 0 cannot be used");
1458				YYERROR;
1459			}
1460			$$ = calloc(1, sizeof(struct node_proto));
1461			if ($$ == NULL)
1462				err(1, "proto_item: calloc");
1463			$$->proto = pr;
1464			$$->next = NULL;
1465			$$->tail = $$;
1466		}
1467		;
1468
1469fromto		: /* empty */			{
1470			$$.src.host = NULL;
1471			$$.src.port = NULL;
1472			$$.dst.host = NULL;
1473			$$.dst.port = NULL;
1474		}
1475		| ALL				{
1476			$$.src.host = NULL;
1477			$$.src.port = NULL;
1478			$$.dst.host = NULL;
1479			$$.dst.port = NULL;
1480		}
1481		| FROM ipportspec TO ipportspec	{
1482			$$.src = $2;
1483			$$.dst = $4;
1484		}
1485		;
1486
1487ipportspec	: ipspec			{ $$.host = $1; $$.port = NULL; }
1488		| ipspec PORT portspec		{
1489			$$.host = $1;
1490			$$.port = $3;
1491		}
1492		;
1493
1494ipspec		: ANY				{ $$ = NULL; }
1495		| xhost				{ $$ = $1; }
1496		| '{' host_list '}'		{ $$ = $2; }
1497		;
1498
1499host_list	: xhost				{ $$ = $1; }
1500		| host_list comma xhost		{
1501			/* $3 may be a list, so use its tail pointer */
1502			if ($3 == NULL)
1503				$$ = $1;
1504			else if ($1 == NULL)
1505				$$ = $3;
1506			else {
1507				$1->tail->next = $3->tail;
1508				$1->tail = $3->tail;
1509				$$ = $1;
1510			}
1511		}
1512		;
1513
1514xhost		: '!' host			{
1515			struct node_host	*n;
1516
1517			for (n = $2; n != NULL; n = n->next)
1518				n->not = 1;
1519			$$ = $2;
1520		}
1521		| host				{ $$ = $1; }
1522		| NOROUTE			{
1523			$$ = calloc(1, sizeof(struct node_host));
1524			if ($$ == NULL)
1525				err(1, "xhost: calloc");
1526			$$->addr.type = PF_ADDR_NOROUTE;
1527			$$->next = NULL;
1528			$$->tail = $$;
1529		}
1530		;
1531
1532host		: address
1533		| STRING '/' number		{ $$ = host($1, $3); }
1534		| PORTUNARY STRING PORTUNARY	{
1535			if ($1 != PF_OP_LT || $3 != PF_OP_GT)
1536				YYERROR;
1537			if (strlen($2) >= PF_TABLE_NAME_SIZE) {
1538				yyerror("table name '%s' too long");
1539				YYERROR;
1540			}
1541			$$ = calloc(1, sizeof(struct node_host));
1542			if ($$ == NULL)
1543				err(1, "host: calloc");
1544			$$->addr.type = PF_ADDR_TABLE;
1545			if (strlcpy($$->addr.v.tblname, $2,
1546			    sizeof($$->addr.v.tblname)) >=
1547			    sizeof($$->addr.v.tblname))
1548				errx(1, "host: strlcpy");
1549			$$->next = NULL;
1550			$$->tail = $$;
1551		}
1552		;
1553
1554number		: STRING			{
1555			u_long	ulval;
1556
1557			if (atoul($1, &ulval) == -1) {
1558				yyerror("%s is not a number", $1);
1559				YYERROR;
1560			} else
1561				$$ = ulval;
1562		}
1563		;
1564
1565address		: '(' STRING ')'		{
1566			$$ = calloc(1, sizeof(struct node_host));
1567			if ($$ == NULL)
1568				err(1, "address: calloc");
1569			$$->af = 0;
1570			set_ipmask($$, 128);
1571			$$->addr.type = PF_ADDR_DYNIFTL;
1572			if (strlcpy($$->addr.v.ifname, $2,
1573			    sizeof($$->addr.v.ifname)) >=
1574			    sizeof($$->addr.v.ifname)) {
1575				free($$);
1576				yyerror("interface name too long");
1577				YYERROR;
1578			}
1579			$$->next = NULL;
1580			$$->tail = $$;
1581		}
1582		| STRING			{ $$ = host($1, -1); }
1583		;
1584
1585portspec	: port_item			{ $$ = $1; }
1586		| '{' port_list '}'		{ $$ = $2; }
1587		;
1588
1589port_list	: port_item			{ $$ = $1; }
1590		| port_list comma port_item	{
1591			$1->tail->next = $3;
1592			$1->tail = $3;
1593			$$ = $1;
1594		}
1595		;
1596
1597port_item	: port				{
1598			$$ = calloc(1, sizeof(struct node_port));
1599			if ($$ == NULL)
1600				err(1, "port_item: calloc");
1601			$$->port[0] = $1;
1602			$$->port[1] = $1;
1603			$$->op = PF_OP_EQ;
1604			$$->next = NULL;
1605			$$->tail = $$;
1606		}
1607		| PORTUNARY port		{
1608			$$ = calloc(1, sizeof(struct node_port));
1609			if ($$ == NULL)
1610				err(1, "port_item: calloc");
1611			$$->port[0] = $2;
1612			$$->port[1] = $2;
1613			$$->op = $1;
1614			$$->next = NULL;
1615			$$->tail = $$;
1616		}
1617		| port PORTBINARY port		{
1618			$$ = calloc(1, sizeof(struct node_port));
1619			if ($$ == NULL)
1620				err(1, "port_item: calloc");
1621			$$->port[0] = $1;
1622			$$->port[1] = $3;
1623			$$->op = $2;
1624			$$->next = NULL;
1625			$$->tail = $$;
1626		}
1627		;
1628
1629port		: STRING			{
1630			struct servent	*s = NULL;
1631			u_long		 ulval;
1632
1633			if (atoul($1, &ulval) == 0) {
1634				if (ulval > 65535) {
1635					yyerror("illegal port value %d", ulval);
1636					YYERROR;
1637				}
1638				$$ = htons(ulval);
1639			} else {
1640				s = getservbyname($1, "tcp");
1641				if (s == NULL)
1642					s = getservbyname($1, "udp");
1643				if (s == NULL) {
1644					yyerror("unknown port %s", $1);
1645					YYERROR;
1646				}
1647				$$ = s->s_port;
1648			}
1649		}
1650		;
1651
1652uids		: uid_item			{ $$ = $1; }
1653		| '{' uid_list '}'		{ $$ = $2; }
1654		;
1655
1656uid_list	: uid_item			{ $$ = $1; }
1657		| uid_list comma uid_item	{
1658			$1->tail->next = $3;
1659			$1->tail = $3;
1660			$$ = $1;
1661		}
1662		;
1663
1664uid_item	: uid				{
1665			$$ = calloc(1, sizeof(struct node_uid));
1666			if ($$ == NULL)
1667				err(1, "uid_item: calloc");
1668			$$->uid[0] = $1;
1669			$$->uid[1] = $1;
1670			$$->op = PF_OP_EQ;
1671			$$->next = NULL;
1672			$$->tail = $$;
1673		}
1674		| PORTUNARY uid			{
1675			if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
1676				yyerror("user unknown requires operator = or "
1677				    "!=");
1678				YYERROR;
1679			}
1680			$$ = calloc(1, sizeof(struct node_uid));
1681			if ($$ == NULL)
1682				err(1, "uid_item: calloc");
1683			$$->uid[0] = $2;
1684			$$->uid[1] = $2;
1685			$$->op = $1;
1686			$$->next = NULL;
1687			$$->tail = $$;
1688		}
1689		| uid PORTBINARY uid		{
1690			if ($1 == UID_MAX || $3 == UID_MAX) {
1691				yyerror("user unknown requires operator = or "
1692				    "!=");
1693				YYERROR;
1694			}
1695			$$ = calloc(1, sizeof(struct node_uid));
1696			if ($$ == NULL)
1697				err(1, "uid_item: calloc");
1698			$$->uid[0] = $1;
1699			$$->uid[1] = $3;
1700			$$->op = $2;
1701			$$->next = NULL;
1702			$$->tail = $$;
1703		}
1704		;
1705
1706uid		: STRING			{
1707			u_long	ulval;
1708
1709			if (atoul($1, &ulval) == -1) {
1710				if (!strcmp($1, "unknown"))
1711					$$ = UID_MAX;
1712				else {
1713					struct passwd	*pw;
1714
1715					if ((pw = getpwnam($1)) == NULL) {
1716						yyerror("unknown user %s", $1);
1717						YYERROR;
1718					}
1719					$$ = pw->pw_uid;
1720				}
1721			} else {
1722				if (ulval >= UID_MAX) {
1723					yyerror("illegal uid value %lu", ulval);
1724					YYERROR;
1725				}
1726				$$ = ulval;
1727			}
1728		}
1729		;
1730
1731gids		: gid_item			{ $$ = $1; }
1732		| '{' gid_list '}'		{ $$ = $2; }
1733		;
1734
1735gid_list	: gid_item			{ $$ = $1; }
1736		| gid_list comma gid_item	{
1737			$1->tail->next = $3;
1738			$1->tail = $3;
1739			$$ = $1;
1740		}
1741		;
1742
1743gid_item	: gid				{
1744			$$ = calloc(1, sizeof(struct node_gid));
1745			if ($$ == NULL)
1746				err(1, "gid_item: calloc");
1747			$$->gid[0] = $1;
1748			$$->gid[1] = $1;
1749			$$->op = PF_OP_EQ;
1750			$$->next = NULL;
1751			$$->tail = $$;
1752		}
1753		| PORTUNARY gid			{
1754			if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
1755				yyerror("group unknown requires operator = or "
1756				    "!=");
1757				YYERROR;
1758			}
1759			$$ = calloc(1, sizeof(struct node_gid));
1760			if ($$ == NULL)
1761				err(1, "gid_item: calloc");
1762			$$->gid[0] = $2;
1763			$$->gid[1] = $2;
1764			$$->op = $1;
1765			$$->next = NULL;
1766			$$->tail = $$;
1767		}
1768		| gid PORTBINARY gid		{
1769			if ($1 == GID_MAX || $3 == GID_MAX) {
1770				yyerror("group unknown requires operator = or "
1771				    "!=");
1772				YYERROR;
1773			}
1774			$$ = calloc(1, sizeof(struct node_gid));
1775			if ($$ == NULL)
1776				err(1, "gid_item: calloc");
1777			$$->gid[0] = $1;
1778			$$->gid[1] = $3;
1779			$$->op = $2;
1780			$$->next = NULL;
1781			$$->tail = $$;
1782		}
1783		;
1784
1785gid		: STRING			{
1786			u_long	ulval;
1787
1788			if (atoul($1, &ulval) == -1) {
1789				if (!strcmp($1, "unknown"))
1790					$$ = GID_MAX;
1791				else {
1792					struct group	*grp;
1793
1794					if ((grp = getgrnam($1)) == NULL) {
1795						yyerror("unknown group %s", $1);
1796						YYERROR;
1797					}
1798					$$ = grp->gr_gid;
1799				}
1800			} else {
1801				if (ulval >= GID_MAX) {
1802					yyerror("illegal gid value %lu", ulval);
1803					YYERROR;
1804				}
1805				$$ = ulval;
1806			}
1807		}
1808		;
1809
1810flag		: STRING			{
1811			int	f;
1812
1813			if ((f = parse_flags($1)) < 0) {
1814				yyerror("bad flags %s", $1);
1815				YYERROR;
1816			}
1817			$$.b1 = f;
1818		}
1819		;
1820
1821flags		: FLAGS flag '/' flag	{ $$.b1 = $2.b1; $$.b2 = $4.b1; }
1822		| FLAGS '/' flag	{ $$.b1 = 0; $$.b2 = $3.b1; }
1823		;
1824
1825icmpspec	: ICMPTYPE icmp_item		{ $$ = $2; }
1826		| ICMPTYPE '{' icmp_list '}'	{ $$ = $3; }
1827		| ICMP6TYPE icmp6_item		{ $$ = $2; }
1828		| ICMP6TYPE '{' icmp6_list '}'	{ $$ = $3; }
1829		;
1830
1831icmp_list	: icmp_item			{ $$ = $1; }
1832		| icmp_list comma icmp_item	{
1833			$1->tail->next = $3;
1834			$1->tail = $3;
1835			$$ = $1;
1836		}
1837		;
1838
1839icmp6_list	: icmp6_item			{ $$ = $1; }
1840		| icmp6_list comma icmp6_item	{
1841			$1->tail->next = $3;
1842			$1->tail = $3;
1843			$$ = $1;
1844		}
1845		;
1846
1847icmp_item	: icmptype		{
1848			$$ = calloc(1, sizeof(struct node_icmp));
1849			if ($$ == NULL)
1850				err(1, "icmp_item: calloc");
1851			$$->type = $1;
1852			$$->code = 0;
1853			$$->proto = IPPROTO_ICMP;
1854			$$->next = NULL;
1855			$$->tail = $$;
1856		}
1857		| icmptype CODE STRING	{
1858			const struct icmpcodeent	*p;
1859			u_long				 ulval;
1860
1861			if (atoul($3, &ulval) == 0) {
1862				if (ulval > 255) {
1863					yyerror("illegal icmp-code %d", ulval);
1864					YYERROR;
1865				}
1866			} else {
1867				if ((p = geticmpcodebyname($1-1, $3,
1868				    AF_INET)) == NULL) {
1869					yyerror("unknown icmp-code %s", $3);
1870					YYERROR;
1871				}
1872				ulval = p->code;
1873			}
1874			$$ = calloc(1, sizeof(struct node_icmp));
1875			if ($$ == NULL)
1876				err(1, "icmp_item: calloc");
1877			$$->type = $1;
1878			$$->code = ulval + 1;
1879			$$->proto = IPPROTO_ICMP;
1880			$$->next = NULL;
1881			$$->tail = $$;
1882		}
1883		;
1884
1885icmp6_item	: icmp6type		{
1886			$$ = calloc(1, sizeof(struct node_icmp));
1887			if ($$ == NULL)
1888				err(1, "icmp_item: calloc");
1889			$$->type = $1;
1890			$$->code = 0;
1891			$$->proto = IPPROTO_ICMPV6;
1892			$$->next = NULL;
1893			$$->tail = $$;
1894		}
1895		| icmp6type CODE STRING	{
1896			const struct icmpcodeent	*p;
1897			u_long				 ulval;
1898
1899			if (atoul($3, &ulval) == 0) {
1900				if (ulval > 255) {
1901					yyerror("illegal icmp6-code %ld", ulval);
1902					YYERROR;
1903				}
1904			} else {
1905				if ((p = geticmpcodebyname($1-1, $3,
1906				    AF_INET6)) == NULL) {
1907					yyerror("unknown icmp6-code %s", $3);
1908					YYERROR;
1909				}
1910				ulval = p->code;
1911			}
1912			$$ = calloc(1, sizeof(struct node_icmp));
1913			if ($$ == NULL)
1914				err(1, "icmp_item: calloc");
1915			$$->type = $1;
1916			$$->code = ulval + 1;
1917			$$->proto = IPPROTO_ICMPV6;
1918			$$->next = NULL;
1919			$$->tail = $$;
1920		}
1921		;
1922
1923icmptype	: STRING			{
1924			const struct icmptypeent	*p;
1925			u_long				 ulval;
1926
1927			if (atoul($1, &ulval) == 0) {
1928				if (ulval > 255) {
1929					yyerror("illegal icmp-type %d", ulval);
1930					YYERROR;
1931				}
1932				$$ = ulval + 1;
1933			} else {
1934				if ((p = geticmptypebyname($1, AF_INET)) == NULL) {
1935					yyerror("unknown icmp-type %s", $1);
1936					YYERROR;
1937				}
1938				$$ = p->type + 1;
1939			}
1940		}
1941		;
1942
1943icmp6type	: STRING			{
1944			const struct icmptypeent	*p;
1945			u_long				 ulval;
1946
1947			if (atoul($1, &ulval) == 0) {
1948				if (ulval > 255) {
1949					yyerror("illegal icmp6-type %d", ulval);
1950					YYERROR;
1951				}
1952				$$ = ulval + 1;
1953			} else {
1954				if ((p = geticmptypebyname($1, AF_INET6)) == NULL) {
1955					yyerror("unknown icmp6-type %s", $1);
1956					YYERROR;
1957				}
1958				$$ = p->type + 1;
1959			}
1960		}
1961		;
1962
1963tos		: TOS STRING			{
1964			if (!strcmp($2, "lowdelay"))
1965				$$ = IPTOS_LOWDELAY;
1966			else if (!strcmp($2, "throughput"))
1967				$$ = IPTOS_THROUGHPUT;
1968			else if (!strcmp($2, "reliability"))
1969				$$ = IPTOS_RELIABILITY;
1970			else if ($2[0] == '0' && $2[1] == 'x')
1971				$$ = strtoul($2, NULL, 16);
1972			else
1973				$$ = strtoul($2, NULL, 10);
1974			if (!$$ || $$ > 255) {
1975				yyerror("illegal tos value %s", $2);
1976				YYERROR;
1977			}
1978		}
1979		;
1980
1981keep		: KEEP STATE state_opt_spec	{
1982			$$.action = PF_STATE_NORMAL;
1983			$$.options = $3;
1984		}
1985		| MODULATE STATE state_opt_spec	{
1986			$$.action = PF_STATE_MODULATE;
1987			$$.options = $3;
1988		}
1989		;
1990
1991state_opt_spec	: '(' state_opt_list ')'	{ $$ = $2; }
1992		| /* empty */			{ $$ = NULL; }
1993		;
1994
1995state_opt_list	: state_opt_item		{ $$ = $1; }
1996		| state_opt_list comma state_opt_item {
1997			$1->tail->next = $3;
1998			$1->tail = $3;
1999			$$ = $1;
2000		}
2001		;
2002
2003state_opt_item	: MAXIMUM number		{
2004			if ($2 <= 0) {
2005				yyerror("illegal states max value %d", $2);
2006				YYERROR;
2007			}
2008			$$ = calloc(1, sizeof(struct node_state_opt));
2009			if ($$ == NULL)
2010				err(1, "state_opt_item: calloc");
2011			$$->type = PF_STATE_OPT_MAX;
2012			$$->data.max_states = $2;
2013			$$->next = NULL;
2014			$$->tail = $$;
2015		}
2016		| STRING number			{
2017			int	i;
2018
2019			for (i = 0; pf_timeouts[i].name &&
2020			    strcmp(pf_timeouts[i].name, $1); ++i)
2021				;	/* nothing */
2022			if (!pf_timeouts[i].name) {
2023				yyerror("illegal timeout name %s", $1);
2024				YYERROR;
2025			}
2026			if (strchr(pf_timeouts[i].name, '.') == NULL) {
2027				yyerror("illegal state timeout %s", $1);
2028				YYERROR;
2029			}
2030			$$ = calloc(1, sizeof(struct node_state_opt));
2031			if ($$ == NULL)
2032				err(1, "state_opt_item: calloc");
2033			$$->type = PF_STATE_OPT_TIMEOUT;
2034			$$->data.timeout.number = pf_timeouts[i].timeout;
2035			$$->data.timeout.seconds = $2;
2036			$$->next = NULL;
2037			$$->tail = $$;
2038		}
2039		;
2040
2041label		: LABEL STRING			{
2042			if (($$ = strdup($2)) == NULL)
2043				err(1, "rule label strdup() failed");
2044		}
2045		;
2046
2047qname		: QUEUE STRING				{
2048			if (($$.qname = strdup($2)) == NULL)
2049				err(1, "qname strdup() failed");
2050		}
2051		| QUEUE '(' STRING ')'			{
2052			if (($$.qname = strdup($3)) == NULL)
2053				err(1, "qname strdup() failed");
2054		}
2055		| QUEUE '(' STRING comma STRING ')'	{
2056			if (($$.qname = strdup($3)) == NULL ||
2057			    ($$.pqname = strdup($5)) == NULL)
2058				err(1, "qname strdup() failed");
2059		}
2060		;
2061
2062no		: /* empty */			{ $$ = 0; }
2063		| NO				{ $$ = 1; }
2064		;
2065
2066rport		: STRING			{
2067			char	*p = strchr($1, ':');
2068
2069			if (p == NULL) {
2070				if (($$.a = getservice($1)) == -1)
2071					YYERROR;
2072				$$.b = $$.t = 0;
2073			} else if (!strcmp(p+1, "*")) {
2074				*p = 0;
2075				if (($$.a = getservice($1)) == -1)
2076					YYERROR;
2077				$$.b = 0;
2078				$$.t = 1;
2079			} else {
2080				*p++ = 0;
2081				if (($$.a = getservice($1)) == -1 ||
2082				    ($$.b = getservice(p)) == -1)
2083					YYERROR;
2084				if ($$.a == $$.b)
2085					$$.b = 0;
2086				$$.t = 0;
2087			}
2088		}
2089		;
2090
2091redirspec	: host				{ $$ = $1; }
2092		| '{' redir_host_list '}'	{ $$ = $2; }
2093		;
2094
2095redir_host_list	: host				{ $$ = $1; }
2096		| redir_host_list comma host	{
2097			/* $3 may be a list, so use its tail pointer */
2098			$1->tail->next = $3->tail;
2099			$1->tail = $3->tail;
2100			$$ = $1;
2101		}
2102		;
2103
2104redirpool	: /* empty */			{ $$ = NULL; }
2105		| ARROW redirspec		{
2106			$$ = calloc(1, sizeof(struct redirection));
2107			if ($$ == NULL)
2108				err(1, "redirection: calloc");
2109			$$->host = $2;
2110			$$->rport.a = $$->rport.b = $$->rport.t = 0;
2111		}
2112		| ARROW redirspec PORT rport	{
2113			$$ = calloc(1, sizeof(struct redirection));
2114			if ($$ == NULL)
2115				err(1, "redirection: calloc");
2116			$$->host = $2;
2117			$$->rport = $4;
2118		}
2119		;
2120
2121hashkey		: /* empty */
2122		{
2123			$$ = calloc(1, sizeof(struct pf_poolhashkey));
2124			if ($$ == NULL)
2125				err(1, "hashkey: calloc");
2126			$$->key32[0] = arc4random();
2127			$$->key32[1] = arc4random();
2128			$$->key32[2] = arc4random();
2129			$$->key32[3] = arc4random();
2130		}
2131		| string
2132		{
2133			if (!strncmp((char *)$1, "0x", 2)) {
2134				if (strlen((char *)$1) != 34) {
2135					yyerror("hex key must be 128 bits "
2136						"(32 hex digits) long");
2137					YYERROR;
2138				}
2139				$$ = calloc(1, sizeof(struct pf_poolhashkey));
2140				if ($$ == NULL)
2141					err(1, "hashkey: calloc");
2142
2143				if (sscanf($1, "0x%8x%8x%8x%8x",
2144				    &$$->key32[0], &$$->key32[1],
2145				    &$$->key32[2], &$$->key32[3]) != 4) {
2146					free($$);
2147					yyerror("invalid hex key");
2148					YYERROR;
2149				}
2150			} else {
2151				MD5_CTX	context;
2152
2153				$$ = calloc(1, sizeof(struct pf_poolhashkey));
2154				if ($$ == NULL)
2155					err(1, "hashkey: calloc");
2156				MD5Init(&context);
2157				MD5Update(&context, (unsigned char *)$1,
2158				    strlen($1));
2159				MD5Final((unsigned char *)$$, &context);
2160				HTONL($$->key32[0]);
2161				HTONL($$->key32[1]);
2162				HTONL($$->key32[2]);
2163				HTONL($$->key32[3]);
2164			}
2165		}
2166		;
2167
2168pooltype	: /* empty */
2169		{
2170			$$.type = PF_POOL_NONE;
2171			$$.key = NULL;
2172		}
2173		| BITMASK
2174		{
2175			$$.type = PF_POOL_BITMASK;
2176			$$.key = NULL;
2177		}
2178		| RANDOM
2179		{
2180			$$.type = PF_POOL_RANDOM;
2181			$$.key = NULL;
2182		}
2183		| SOURCEHASH hashkey
2184		{
2185			$$.type = PF_POOL_SRCHASH;
2186			$$.key = $2;
2187		}
2188		| ROUNDROBIN
2189		{
2190			$$.type = PF_POOL_ROUNDROBIN;
2191			$$.key = NULL;
2192		}
2193		;
2194
2195staticport	: /* empty */			{ $$ = 0; }
2196		| STATICPORT			{ $$ = PF_POOL_STATICPORT; }
2197		;
2198
2199redirection	: /* empty */			{ $$ = NULL; }
2200		| ARROW host			{
2201			$$ = calloc(1, sizeof(struct redirection));
2202			if ($$ == NULL)
2203				err(1, "redirection: calloc");
2204			$$->host = $2;
2205			$$->rport.a = $$->rport.b = $$->rport.t = 0;
2206		}
2207		| ARROW host PORT rport	{
2208			$$ = calloc(1, sizeof(struct redirection));
2209			if ($$ == NULL)
2210				err(1, "redirection: calloc");
2211			$$->host = $2;
2212			$$->rport = $4;
2213		}
2214		;
2215
2216natrule		: no NAT interface af proto fromto redirpool pooltype staticport
2217		{
2218			struct pf_rule	nat;
2219
2220			if (check_rulestate(PFCTL_STATE_NAT))
2221				YYERROR;
2222
2223			memset(&nat, 0, sizeof(nat));
2224
2225			if ($1)
2226				nat.action = PF_NONAT;
2227			else
2228				nat.action = PF_NAT;
2229			nat.af = $4;
2230
2231			if (!nat.af) {
2232				if ($6.src.host && $6.src.host->af &&
2233				    !$6.src.host->ifindex)
2234					nat.af = $6.src.host->af;
2235				else if ($6.dst.host && $6.dst.host->af &&
2236				    !$6.dst.host->ifindex)
2237					nat.af = $6.dst.host->af;
2238			}
2239
2240			if (nat.action == PF_NONAT) {
2241				if ($7 != NULL) {
2242					yyerror("'no nat' rule does not need "
2243					    "'->'");
2244					YYERROR;
2245				}
2246			} else {
2247				if ($7 == NULL || $7->host == NULL) {
2248					yyerror("'nat' rule requires '-> "
2249					    "address'");
2250					YYERROR;
2251				}
2252				if (disallow_table($7->host, "invalid use of "
2253				    "table <%s> as the redirection address "
2254				    "a nat rule"))
2255					YYERROR;
2256				if (!nat.af && ! $7->host->ifindex)
2257					nat.af = $7->host->af;
2258
2259				remove_invalid_hosts(&$7->host, &nat.af);
2260				if ($7->host == NULL)
2261					YYERROR;
2262				nat.rpool.proxy_port[0] = ntohs($7->rport.a);
2263				nat.rpool.proxy_port[1] = ntohs($7->rport.b);
2264				if (!nat.rpool.proxy_port[0] &&
2265				    !nat.rpool.proxy_port[1]) {
2266					nat.rpool.proxy_port[0] =
2267					    PF_NAT_PROXY_PORT_LOW;
2268					nat.rpool.proxy_port[1] =
2269					    PF_NAT_PROXY_PORT_HIGH;
2270				} else if (!nat.rpool.proxy_port[1])
2271					nat.rpool.proxy_port[1] =
2272					    nat.rpool.proxy_port[0];
2273				if ($7->host->next) {
2274					nat.rpool.opts = $8.type;
2275					if (nat.rpool.opts == PF_POOL_NONE)
2276						nat.rpool.opts =
2277						    PF_POOL_ROUNDROBIN;
2278					if (nat.rpool.opts !=
2279					    PF_POOL_ROUNDROBIN) {
2280						yyerror("nat: only round-robin "
2281						    "valid for multiple "
2282						    "redirection addresses");
2283						YYERROR;
2284					}
2285				} else {
2286					if ((nat.af == AF_INET &&
2287					    unmask(&$7->host->addr.v.a.mask,
2288					    nat.af) == 32) ||
2289					    (nat.af == AF_INET6 &&
2290					    unmask(&$7->host->addr.v.a.mask,
2291					    nat.af) == 128)) {
2292						nat.rpool.opts = PF_POOL_NONE;
2293					} else {
2294						if ($8.type == PF_POOL_NONE)
2295							nat.rpool.opts =
2296							    PF_POOL_ROUNDROBIN;
2297						else
2298							nat.rpool.opts =
2299							    $8.type;
2300					}
2301				}
2302			}
2303
2304			if ($8.key != NULL)
2305				memcpy(&nat.rpool.key, $8.key,
2306				    sizeof(struct pf_poolhashkey));
2307
2308			if ($9 != NULL)
2309				nat.rpool.opts |= PF_POOL_STATICPORT;
2310
2311			expand_nat(&nat, $3, $5, $6.src.host, $6.src.port,
2312			    $6.dst.host, $6.dst.port,
2313			    $7 == NULL ? NULL : $7->host);
2314			free($7);
2315		}
2316		;
2317
2318binatrule	: no BINAT interface af proto FROM host TO ipspec redirection
2319		{
2320			struct pf_rule		binat;
2321			struct pf_pooladdr	*pa;
2322
2323			if (check_rulestate(PFCTL_STATE_NAT))
2324				YYERROR;
2325
2326			memset(&binat, 0, sizeof(binat));
2327
2328			if ($1)
2329				binat.action = PF_NOBINAT;
2330			else
2331				binat.action = PF_BINAT;
2332			binat.af = $4;
2333
2334			if ($3 != NULL) {
2335				memcpy(binat.ifname, $3->ifname,
2336				    sizeof(binat.ifname));
2337				free($3);
2338			}
2339			if ($5 != NULL) {
2340				binat.proto = $5->proto;
2341				free($5);
2342			}
2343			if ($7 != NULL && disallow_table($7, "invalid use of "
2344			    "table <%s> as the source address of a binat rule"))
2345				YYERROR;
2346			if ($7 != NULL && $9 != NULL && $7->af != $9->af) {
2347				yyerror("binat ip versions must match");
2348				YYERROR;
2349			}
2350			if ($7 != NULL) {
2351				if ($7->next) {
2352					yyerror("multiple binat ip addresses");
2353					YYERROR;
2354				}
2355				if ($7->addr.type == PF_ADDR_DYNIFTL) {
2356					if (!binat.af) {
2357						yyerror("address family (inet/"
2358						    "inet6) undefined");
2359						YYERROR;
2360					}
2361					$7->af = binat.af;
2362				}
2363				if (binat.af && $7->af != binat.af) {
2364					yyerror("binat ip versions must match");
2365					YYERROR;
2366				}
2367				binat.af = $7->af;
2368				memcpy(&binat.src.addr.v.a.addr,
2369				    &$7->addr.v.a.addr,
2370				    sizeof(binat.src.addr.v.a.addr));
2371				memcpy(&binat.src.addr.v.a.mask,
2372				    &$7->addr.v.a.mask,
2373				    sizeof(binat.src.addr.v.a.mask));
2374				free($7);
2375			}
2376			if ($9 != NULL) {
2377				if ($9->next) {
2378					yyerror("multiple binat ip addresses");
2379					YYERROR;
2380				}
2381				if ($9->addr.type == PF_ADDR_DYNIFTL) {
2382					if (!binat.af) {
2383						yyerror("address family (inet/"
2384						    "inet6) undefined");
2385						YYERROR;
2386					}
2387					$9->af = binat.af;
2388				}
2389				if (binat.af && $9->af != binat.af) {
2390					yyerror("binat ip versions must match");
2391					YYERROR;
2392				}
2393				binat.af = $9->af;
2394				memcpy(&binat.dst.addr.v.a.addr,
2395				    &$9->addr.v.a.addr,
2396				    sizeof(binat.dst.addr.v.a.addr));
2397				memcpy(&binat.dst.addr.v.a.mask,
2398				    &$9->addr.v.a.mask,
2399				    sizeof(binat.dst.addr.v.a.mask));
2400				binat.dst.not = $9->not;
2401				free($9);
2402			}
2403
2404			if (binat.action == PF_NOBINAT) {
2405				if ($10 != NULL) {
2406					yyerror("'no binat' rule does not need"
2407					    " '->'");
2408					YYERROR;
2409				}
2410			} else {
2411				if ($10 == NULL || $10->host == NULL) {
2412					yyerror("'binat' rule requires"
2413					    " '-> address'");
2414					YYERROR;
2415				}
2416
2417				remove_invalid_hosts(&$10->host, &binat.af);
2418				if ($10->host == NULL)
2419					YYERROR;
2420				if ($10->host->next != NULL) {
2421					yyerror("binat rule must redirect to "
2422					    "a single address");
2423					YYERROR;
2424				}
2425
2426				if (!PF_AZERO(&binat.src.addr.v.a.mask, binat.af) &&
2427				    !PF_AEQ(&binat.src.addr.v.a.mask,
2428				    &$10->host->addr.v.a.mask, binat.af)) {
2429					yyerror("'binat' source mask and "
2430					    "redirect mask must be the same");
2431					YYERROR;
2432				}
2433
2434				TAILQ_INIT(&binat.rpool.list);
2435				pa = calloc(1, sizeof(struct pf_pooladdr));
2436				if (pa == NULL)
2437					err(1, "binat: calloc");
2438				pa->addr.addr = $10->host->addr;
2439				pa->ifname[0] = 0;
2440				TAILQ_INSERT_TAIL(&binat.rpool.list,
2441				    pa, entries);
2442
2443				free($10);
2444			}
2445
2446			pfctl_add_rule(pf, &binat);
2447		}
2448		;
2449
2450rdrrule		: no RDR interface af proto FROM ipspec TO ipspec dport
2451		  redirpool pooltype
2452		{
2453			struct pf_rule	rdr;
2454
2455			if (check_rulestate(PFCTL_STATE_NAT))
2456				YYERROR;
2457
2458			memset(&rdr, 0, sizeof(rdr));
2459
2460			if ($1)
2461				rdr.action = PF_NORDR;
2462			else
2463				rdr.action = PF_RDR;
2464			rdr.af = $4;
2465
2466			if ($7 != NULL) {
2467				memcpy(&rdr.src.addr.v.a.addr,
2468				    &$7->addr.v.a.addr,
2469				    sizeof(rdr.src.addr.v.a.addr));
2470				memcpy(&rdr.src.addr.v.a.mask,
2471				    &$7->addr.v.a.mask,
2472				    sizeof(rdr.src.addr.v.a.mask));
2473				rdr.src.not = $7->not;
2474				if (!rdr.af && !$7->ifindex)
2475					rdr.af = $7->af;
2476			}
2477			if ($9 != NULL) {
2478				memcpy(&rdr.dst.addr.v.a.addr,
2479				    &$9->addr.v.a.addr,
2480				    sizeof(rdr.dst.addr.v.a.addr));
2481				memcpy(&rdr.dst.addr.v.a.mask,
2482				    &$9->addr.v.a.mask,
2483				    sizeof(rdr.dst.addr.v.a.mask));
2484				rdr.dst.not = $9->not;
2485				if (!rdr.af && !$9->ifindex)
2486					rdr.af = $9->af;
2487			}
2488
2489			rdr.dst.port[0] = $10.a;
2490			rdr.dst.port[1] = $10.b;
2491			rdr.dst.port_op |= $10.t;
2492
2493			if ($12.type == PF_POOL_NONE)
2494				rdr.rpool.opts = PF_POOL_RANDOM;
2495			else
2496				rdr.rpool.opts = $12.type;
2497
2498			if (rdr.action == PF_NORDR) {
2499				if ($11 != NULL) {
2500					yyerror("'no rdr' rule does not need '->'");
2501					YYERROR;
2502				}
2503			} else {
2504				if ($11 == NULL || $11->host == NULL) {
2505					yyerror("'rdr' rule requires '-> "
2506					    "address'");
2507					YYERROR;
2508				}
2509				if (disallow_table($11->host, "invalid use of "
2510				    "table <%s> as the redirection address "
2511				    "of a rdr rule"))
2512					YYERROR;
2513				if (!rdr.af && !$11->host->ifindex)
2514					rdr.af = $11->host->af;
2515
2516				remove_invalid_hosts(&$11->host, &rdr.af);
2517				if ($11->host == NULL)
2518					YYERROR;
2519				rdr.rpool.proxy_port[0] = $11->rport.a;
2520				if ($11->rport.t && $10.b) {
2521					rdr.rpool.proxy_port[1] = $11->rport.a +
2522					    (rdr.dst.port[1] - rdr.dst.port[0]);
2523				} else
2524					rdr.rpool.proxy_port[1] = $11->rport.b;
2525
2526				if ($11->host->next) {
2527					rdr.rpool.opts = $12.type;
2528					if (rdr.rpool.opts == PF_POOL_NONE)
2529						rdr.rpool.opts =
2530						    PF_POOL_ROUNDROBIN;
2531					if (rdr.rpool.opts !=
2532					    PF_POOL_ROUNDROBIN) {
2533						yyerror("rdr: only round-robin "
2534						    "valid for multiple "
2535						    "redirection addresses");
2536						YYERROR;
2537					}
2538				} else {
2539					if ((rdr.af == AF_INET &&
2540					    unmask(&$11->host->addr.v.a.mask,
2541					    rdr.af) == 32) ||
2542					    (rdr.af == AF_INET6 &&
2543					    unmask(&$11->host->addr.v.a.mask,
2544					    rdr.af) == 128)) {
2545						rdr.rpool.opts = PF_POOL_NONE;
2546					} else {
2547						if ($12.type == PF_POOL_NONE)
2548							rdr.rpool.opts =
2549							    PF_POOL_ROUNDROBIN;
2550						else
2551							rdr.rpool.opts =
2552							    $12.type;
2553					}
2554				}
2555			}
2556
2557			if ($12.key != NULL)
2558				memcpy(&rdr.rpool.key, $12.key,
2559				    sizeof(struct pf_poolhashkey));
2560
2561			expand_rdr(&rdr, $3, $5, $7, $9,
2562			    $11 == NULL ? NULL : $11->host);
2563		}
2564		;
2565
2566dport		: /* empty */			{
2567			$$.a = $$.b = $$.t = 0;
2568		}
2569		| PORT STRING			{
2570			char	*p = strchr($2, ':');
2571
2572			if (p == NULL) {
2573				if (($$.a = getservice($2)) == -1)
2574					YYERROR;
2575				$$.b = 0;
2576				$$.t = PF_OP_EQ;
2577			} else {
2578				*p++ = 0;
2579				if (($$.a = getservice($2)) == -1 ||
2580				    ($$.b = getservice(p)) == -1)
2581					YYERROR;
2582				$$.t = PF_OP_RRG;
2583			}
2584		}
2585		;
2586
2587route_host	: STRING			{
2588			$$ = calloc(1, sizeof(struct node_host));
2589			if ($$ == NULL)
2590				err(1, "route_host: calloc");
2591			if (($$->ifname = strdup($1)) == NULL)
2592				err(1, "routeto: strdup");
2593			if (ifa_exists($$->ifname) == NULL) {
2594				yyerror("routeto: unknown interface %s",
2595				    $$->ifname);
2596				YYERROR;
2597			}
2598			$$->next = NULL;
2599			$$->tail = $$;
2600		}
2601		| '(' STRING host ')'		{
2602			$$ = $3;
2603			if (($$->ifname = strdup($2)) == NULL)
2604				err(1, "routeto: strdup");
2605			if (ifa_exists($$->ifname) == NULL) {
2606				yyerror("routeto: unknown interface %s",
2607				    $$->ifname);
2608				YYERROR;
2609			}
2610			if (disallow_table($3, "invalid use of table <%s> in "
2611			    "a route expression"))
2612				YYERROR;
2613		}
2614		;
2615
2616route_host_list	: route_host				{ $$ = $1; }
2617		| route_host_list comma route_host	{
2618			if ($1->af == 0)
2619				$1->af = $3->af;
2620			if ($1->af != $3->af) {
2621				yyerror("all pool addresses must be in the "
2622				    "same address family");
2623				YYERROR;
2624			}
2625			/* $3 may be a list, so use its tail pointer */
2626			$1->tail->next = $3->tail;
2627			$1->tail = $3->tail;
2628			$$ = $1;
2629		}
2630		;
2631
2632routespec	: route_host			{ $$ = $1; }
2633		| '{' route_host_list '}'	{ $$ = $2; }
2634		;
2635
2636route		: /* empty */			{
2637			$$.host = NULL;
2638			$$.rt = 0;
2639			$$.pool_opts = 0;
2640		}
2641		| FASTROUTE {
2642			$$.host = NULL;
2643			$$.rt = PF_FASTROUTE;
2644			$$.pool_opts = 0;
2645		}
2646		| ROUTETO routespec pooltype {
2647			$$.host = $2;
2648			$$.rt = PF_ROUTETO;
2649			$$.pool_opts = $3.type;
2650			if ($3.key != NULL)
2651				$$.key = $3.key;
2652		}
2653		| REPLYTO routespec pooltype {
2654			$$.host = $2;
2655			$$.rt = PF_REPLYTO;
2656			$$.pool_opts = $3.type;
2657			if ($3.key != NULL)
2658				$$.key = $3.key;
2659		}
2660		| DUPTO routespec pooltype {
2661			$$.host = $2;
2662			$$.rt = PF_DUPTO;
2663			$$.pool_opts = $3.type;
2664			if ($3.key != NULL)
2665				$$.key = $3.key;
2666		}
2667		;
2668
2669timeout_spec	: STRING number
2670		{
2671			if (pf->opts & PF_OPT_VERBOSE)
2672				printf("set timeout %s %u\n", $1, $2);
2673			if (check_rulestate(PFCTL_STATE_OPTION))
2674				YYERROR;
2675			if (pfctl_set_timeout(pf, $1, $2) != 0) {
2676				yyerror("unknown timeout %s", $1);
2677				YYERROR;
2678			}
2679		}
2680		;
2681
2682timeout_list	: timeout_list comma timeout_spec
2683		| timeout_spec
2684		;
2685
2686limit_spec	: STRING number
2687		{
2688			if (pf->opts & PF_OPT_VERBOSE)
2689				printf("set limit %s %u\n", $1, $2);
2690			if (check_rulestate(PFCTL_STATE_OPTION))
2691				YYERROR;
2692			if (pfctl_set_limit(pf, $1, $2) != 0) {
2693				yyerror("unable to set limit %s %u", $1, $2);
2694				YYERROR;
2695			}
2696		}
2697
2698limit_list	: limit_list comma limit_spec
2699		| limit_spec
2700		;
2701
2702comma		: ','
2703		| /* empty */
2704		;
2705
2706%%
2707
2708int
2709yyerror(char *fmt, ...)
2710{
2711	va_list		 ap;
2712	extern char	*infile;
2713
2714	errors = 1;
2715	va_start(ap, fmt);
2716	fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
2717	vfprintf(stderr, fmt, ap);
2718	fprintf(stderr, "\n");
2719	va_end(ap);
2720	return (0);
2721}
2722
2723int
2724disallow_table(struct node_host *h, char *fmt)
2725{
2726	for (; h != NULL; h = h->next)
2727		if (h->addr.type == PF_ADDR_TABLE) {
2728			yyerror(fmt, h->addr.v.tblname);
2729			return (1);
2730		}
2731	return (0);
2732}
2733
2734int
2735rule_consistent(struct pf_rule *r)
2736{
2737	int	problems = 0;
2738
2739	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
2740	    (r->src.port_op || r->dst.port_op)) {
2741		yyerror("port only applies to tcp/udp");
2742		problems++;
2743	}
2744	if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
2745	    (r->type || r->code)) {
2746		yyerror("icmp-type/code only applies to icmp");
2747		problems++;
2748	}
2749	if (!r->af && (r->type || r->code)) {
2750		yyerror("must indicate address family with icmp-type/code");
2751		problems++;
2752	}
2753	if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
2754	    (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
2755		yyerror("icmp version does not match address family");
2756		problems++;
2757	}
2758	if (r->keep_state == PF_STATE_MODULATE && r->proto &&
2759	    r->proto != IPPROTO_TCP) {
2760		yyerror("modulate state can only be applied to TCP rules");
2761		problems++;
2762	}
2763	if (r->allow_opts && r->action != PF_PASS) {
2764		yyerror("allow-opts can only be specified for pass rules");
2765		problems++;
2766	}
2767	if (!r->af && (r->src.addr.type == PF_ADDR_DYNIFTL ||
2768	    r->dst.addr.type == PF_ADDR_DYNIFTL)) {
2769		yyerror("dynamic addresses require address family "
2770		    "(inet/inet6)");
2771		problems++;
2772	}
2773	if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
2774	    r->dst.port_op || r->flagset || r->type || r->code)) {
2775		yyerror("fragments can be filtered only on IP header fields");
2776		problems++;
2777	}
2778	if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) {
2779		yyerror("return-rst can only be applied to TCP rules");
2780		problems++;
2781	}
2782	if (r->action == PF_DROP && r->keep_state) {
2783		yyerror("keep state on block rules doesn't make sense");
2784		problems++;
2785	}
2786	return (-problems);
2787}
2788
2789int
2790nat_consistent(struct pf_rule *r)
2791{
2792	int			 problems = 0;
2793	struct pf_pooladdr	*pa;
2794
2795	if (!r->af) {
2796		TAILQ_FOREACH(pa, &r->rpool.list, entries) {
2797			if (pa->addr.addr.type == PF_ADDR_DYNIFTL) {
2798				yyerror("dynamic addresses require "
2799				    "address family (inet/inet6)");
2800				problems++;
2801				break;
2802			}
2803		}
2804	}
2805	return (-problems);
2806}
2807
2808int
2809rdr_consistent(struct pf_rule *r)
2810{
2811	int			 problems = 0;
2812	struct pf_pooladdr	*pa;
2813
2814	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
2815	    (r->dst.port[0] || r->dst.port[1] || r->rpool.proxy_port[0])) {
2816		yyerror("port only applies to tcp/udp");
2817		problems++;
2818	}
2819	if (!r->af) {
2820		if (r->src.addr.type == PF_ADDR_DYNIFTL ||
2821		    r->dst.addr.type == PF_ADDR_DYNIFTL) {
2822			yyerror("dynamic addresses require address family "
2823			    "(inet/inet6)");
2824			problems++;
2825		} else {
2826			TAILQ_FOREACH(pa, &r->rpool.list, entries) {
2827				if (pa->addr.addr.type == PF_ADDR_DYNIFTL) {
2828					yyerror("dynamic addresses require "
2829					    "address family (inet/inet6)");
2830					problems++;
2831					break;
2832				}
2833			}
2834		}
2835	}
2836	return (-problems);
2837}
2838
2839struct keywords {
2840	const char	*k_name;
2841	int		 k_val;
2842};
2843
2844/* macro gore, but you should've seen the prior indentation nightmare... */
2845
2846#define FREE_LIST(T,r) \
2847	do { \
2848		T *p, *node = r; \
2849		while (node != NULL) { \
2850			p = node; \
2851			node = node->next; \
2852			free(p); \
2853		} \
2854	} while (0)
2855
2856#define LOOP_THROUGH(T,n,r,C) \
2857	do { \
2858		T *n; \
2859		if (r == NULL) { \
2860			r = calloc(1, sizeof(T)); \
2861			if (r == NULL) \
2862				err(1, "LOOP: calloc"); \
2863			r->next = NULL; \
2864		} \
2865		n = r; \
2866		while (n != NULL) { \
2867			do { \
2868				C; \
2869			} while (0); \
2870			n = n->next; \
2871		} \
2872	} while (0)
2873
2874void
2875expand_label_str(char *label, const char *srch, const char *repl)
2876{
2877	char tmp[PF_RULE_LABEL_SIZE] = "";
2878	char *p, *q;
2879
2880	p = q = label;
2881	while ((q = strstr(p, srch)) != NULL) {
2882		*q = '\0';
2883		if ((strlcat(tmp, p, sizeof(tmp)) >= sizeof(tmp)) ||
2884		    (strlcat(tmp, repl, sizeof(tmp)) >= sizeof(tmp)))
2885			err(1, "expand_label: label too long");
2886		q += strlen(srch);
2887		p = q;
2888	}
2889	if (strlcat(tmp, p, sizeof(tmp)) >= sizeof(tmp))
2890		err(1, "expand_label: label too long");
2891	strlcpy(label, tmp, PF_RULE_LABEL_SIZE);	/* always fits */
2892}
2893
2894void
2895expand_label_if(const char *name, char *label, const char *ifname)
2896{
2897	if (strstr(label, name) != NULL) {
2898		if (!*ifname)
2899			expand_label_str(label, name, "any");
2900		else
2901			expand_label_str(label, name, ifname);
2902	}
2903}
2904
2905void
2906expand_label_addr(const char *name, char *label, sa_family_t af,
2907    struct node_host *h)
2908{
2909	char tmp[64], tmp_not[66];
2910
2911	if (strstr(label, name) != NULL) {
2912		if (h->addr.type == PF_ADDR_DYNIFTL)
2913			snprintf(tmp, sizeof(tmp), "(%s)", h->addr.v.ifname);
2914		else if (!af || (PF_AZERO(&h->addr.v.a.addr, af) &&
2915		    PF_AZERO(&h->addr.v.a.mask, af)))
2916			snprintf(tmp, sizeof(tmp), "any");
2917		else {
2918			char	a[48];
2919			int	bits;
2920
2921			if (inet_ntop(af, &h->addr.v.a.addr, a, sizeof(a)) ==
2922			    NULL)
2923				snprintf(tmp, sizeof(tmp), "?");
2924			else {
2925				bits = unmask(&h->addr.v.a.mask, af);
2926				if ((af == AF_INET && bits < 32) ||
2927				    (af == AF_INET6 && bits < 128))
2928					snprintf(tmp, sizeof(tmp), "%s/%d",
2929					    a, bits);
2930				else
2931					snprintf(tmp, sizeof(tmp), "%s", a);
2932			}
2933		}
2934
2935		if (h->not) {
2936			snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp);
2937			expand_label_str(label, name, tmp_not);
2938		} else
2939			expand_label_str(label, name, tmp);
2940	}
2941}
2942
2943void
2944expand_label_port(const char *name, char *label, struct node_port *port)
2945{
2946	char	 a1[6], a2[6], op[13] = "";
2947
2948	if (strstr(label, name) != NULL) {
2949		snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0]));
2950		snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1]));
2951		if (!port->op)
2952			;
2953		else if (port->op == PF_OP_IRG)
2954			snprintf(op, sizeof(op), "%s><%s", a1, a2);
2955		else if (port->op == PF_OP_XRG)
2956			snprintf(op, sizeof(op), "%s<>%s", a1, a2);
2957		else if (port->op == PF_OP_EQ)
2958			snprintf(op, sizeof(op), "%s", a1);
2959		else if (port->op == PF_OP_NE)
2960			snprintf(op, sizeof(op), "!=%s", a1);
2961		else if (port->op == PF_OP_LT)
2962			snprintf(op, sizeof(op), "<%s", a1);
2963		else if (port->op == PF_OP_LE)
2964			snprintf(op, sizeof(op), "<=%s", a1);
2965		else if (port->op == PF_OP_GT)
2966			snprintf(op, sizeof(op), ">%s", a1);
2967		else if (port->op == PF_OP_GE)
2968			snprintf(op, sizeof(op), ">=%s", a1);
2969		expand_label_str(label, name, op);
2970	}
2971}
2972
2973void
2974expand_label_proto(const char *name, char *label, u_int8_t proto)
2975{
2976	struct protoent *pe;
2977	char n[4];
2978
2979	if (strstr(label, name) != NULL) {
2980		pe = getprotobynumber(proto);
2981		if (pe != NULL)
2982			expand_label_str(label, name, pe->p_name);
2983		else {
2984			snprintf(n, sizeof(n), "%u", proto);
2985			expand_label_str(label, name, n);
2986		}
2987	}
2988}
2989
2990void
2991expand_label_nr(const char *name, char *label)
2992{
2993	char n[11];
2994
2995	if (strstr(label, name) != NULL) {
2996		snprintf(n, sizeof(n), "%u", pf->rule_nr);
2997		expand_label_str(label, name, n);
2998	}
2999}
3000
3001void
3002expand_label(char *label, const char *ifname, sa_family_t af,
3003    struct node_host *src_host, struct node_port *src_port,
3004    struct node_host *dst_host, struct node_port *dst_port,
3005    u_int8_t proto)
3006{
3007	expand_label_if("$if", label, ifname);
3008	expand_label_addr("$srcaddr", label, af, src_host);
3009	expand_label_addr("$dstaddr", label, af, dst_host);
3010	expand_label_port("$srcport", label, src_port);
3011	expand_label_port("$dstport", label, dst_port);
3012	expand_label_proto("$proto", label, proto);
3013	expand_label_nr("$nr", label);
3014}
3015
3016int
3017expand_altq(struct pf_altq *a, struct node_if *interfaces,
3018    struct node_queue *nqueues, struct node_queue_bw bwspec)
3019{
3020	struct pf_altq		 pa, pb;
3021	char			 qname[PF_QNAME_SIZE];
3022	struct node_queue	*n;
3023	int			 errs = 0;
3024
3025	LOOP_THROUGH(struct node_if, interface, interfaces,
3026		memcpy(&pa, a, sizeof(struct pf_altq));
3027		if (strlcpy(pa.ifname, interface->ifname,
3028		    sizeof(pa.ifname)) >= sizeof(pa.ifname))
3029			errx(1, "expand_altq: strlcpy");
3030
3031		if (interface->not) {
3032			yyerror("altq on ! <interface> is not supported");
3033			errs++;
3034		} else {
3035			if (eval_pfaltq(pf, &pa, bwspec.bw_absolute,
3036			    bwspec.bw_percent))
3037				errs++;
3038			else
3039				if (pfctl_add_altq(pf, &pa))
3040					errs++;
3041
3042			if (pf->opts & PF_OPT_VERBOSE) {
3043				print_altq(&pf->paltq->altq, 0);
3044				if (nqueues && nqueues->tail) {
3045					printf("queue { ");
3046					LOOP_THROUGH(struct node_queue, queue,
3047					    nqueues,
3048						printf("%s ",
3049						    queue->queue);
3050					);
3051					printf("}");
3052				}
3053				printf("\n");
3054			}
3055
3056			if (pa.scheduler == ALTQT_CBQ) {
3057				/* now create a root queue */
3058				memset(&pb, 0, sizeof(struct pf_altq));
3059				if (strlcpy(qname, "root_", sizeof(qname)) >=
3060				    sizeof(qname))
3061					errx(1, "expand_altq: strlcpy");
3062				if (strlcat(qname, interface->ifname,
3063				    sizeof(qname)) >= sizeof(qname))
3064					errx(1, "expand_altq: strlcat");
3065				if (strlcpy(pb.qname, qname,
3066				    sizeof(pb.qname)) >= sizeof(pb.qname))
3067					errx(1, "expand_altq: strlcpy");
3068				if (strlcpy(pb.ifname, interface->ifname,
3069				    sizeof(pb.ifname)) >= sizeof(pb.ifname))
3070					errx(1, "expand_altq: strlcpy");
3071				pb.qlimit = pa.qlimit;
3072				pb.scheduler = pa.scheduler;
3073				pb.pq_u.cbq_opts = pa.pq_u.cbq_opts;
3074				if (eval_pfqueue(pf, &pb, pa.ifbandwidth, 0))
3075					errs++;
3076				else
3077					if (pfctl_add_altq(pf, &pb))
3078						errs++;
3079			}
3080
3081			LOOP_THROUGH(struct node_queue, queue, nqueues,
3082				n = calloc(1, sizeof(struct node_queue));
3083				if (n == NULL)
3084					err(1, "expand_altq: calloc");
3085				if (pa.scheduler == ALTQT_CBQ)
3086					if (strlcpy(n->parent, qname,
3087					    sizeof(n->parent)) >=
3088					    sizeof(n->parent))
3089						errx(1, "expand_altq: strlcpy");
3090				if (strlcpy(n->queue, queue->queue,
3091				    sizeof(n->queue)) >= sizeof(n->queue))
3092					errx(1, "expand_altq: strlcpy");
3093				if (strlcpy(n->ifname, interface->ifname,
3094				    sizeof(n->ifname)) >= sizeof(n->ifname))
3095					errx(1, "expand_altq: strlcpy");
3096				n->scheduler = pa.scheduler;
3097				n->next = NULL;
3098				n->tail = n;
3099				if (queues == NULL)
3100					queues = n;
3101				else {
3102					queues->tail->next = n;
3103					queues->tail = n;
3104				}
3105			);
3106		}
3107	);
3108	FREE_LIST(struct node_if, interfaces);
3109	FREE_LIST(struct node_queue, nqueues);
3110
3111	return (errs);
3112}
3113
3114int
3115expand_queue(struct pf_altq *a, struct node_queue *nqueues,
3116    struct node_queue_bw bwspec)
3117{
3118	struct node_queue	*n;
3119	u_int8_t		 added = 0;
3120	u_int8_t		 found = 0;
3121
3122	LOOP_THROUGH(struct node_queue, tqueue, queues,
3123		if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE)) {
3124			/* found ourselve in queues */
3125			found++;
3126
3127			if (a->scheduler != ALTQT_NONE &&
3128			    a->scheduler != tqueue->scheduler) {
3129				yyerror("exactly one scheduler type per "
3130				    "interface allowed");
3131				return (1);
3132			}
3133			a->scheduler = tqueue->scheduler;
3134
3135			/* scheduler dependent error checking */
3136			switch (a->scheduler) {
3137			case ALTQT_PRIQ:
3138				if (nqueues != NULL) {
3139					yyerror("priq queues cannot have "
3140					    "child queues");
3141					return (1);
3142				}
3143				if (bwspec.bw_absolute > 0 ||
3144				    bwspec.bw_percent < 100) {
3145					yyerror("priq doesn't take bandwidth");
3146					return (1);
3147				}
3148				break;
3149			default:
3150				break;
3151			}
3152
3153			LOOP_THROUGH(struct node_queue, queue, nqueues,
3154				n = calloc(1, sizeof(struct node_queue));
3155				if (n == NULL)
3156					err(1, "expand_queue: calloc");
3157				if (strlcpy(n->parent, a->qname,
3158				    sizeof(n->parent)) >= sizeof(n->parent))
3159					errx(1, "expand_queue: strlcpy");
3160				if (strlcpy(n->queue, queue->queue,
3161				    sizeof(n->queue)) >= sizeof(n->queue))
3162					errx(1, "expand_queue: strlcpy");
3163				if (strlcpy(n->ifname, tqueue->ifname,
3164				    sizeof(n->ifname)) >= sizeof(n->ifname))
3165					errx(1, "expand_queue: strlcpy");
3166				n->scheduler = a->scheduler;
3167				n->next = NULL;
3168				n->tail = n;
3169				if (queues == NULL)
3170					queues = n;
3171				else {
3172					queues->tail->next = n;
3173					queues->tail = n;
3174				}
3175			);
3176			if (strlcpy(a->ifname, tqueue->ifname,
3177			    sizeof(a->ifname)) >= sizeof(a->ifname))
3178				errx(1, "expand_queue: strlcpy");
3179			if (strlcpy(a->parent, tqueue->parent,
3180			    sizeof(a->parent)) >= sizeof(a->parent))
3181				errx(1, "expand_queue: strlcpy");
3182
3183			if (!eval_pfqueue(pf, a, bwspec.bw_absolute,
3184			    bwspec.bw_percent))
3185				if (!pfctl_add_altq(pf, a))
3186					added++;
3187
3188			if ((pf->opts & PF_OPT_VERBOSE) && found == 1) {
3189				print_altq(&pf->paltq->altq, 0);
3190				if (nqueues && nqueues->tail) {
3191					printf("{ ");
3192					LOOP_THROUGH(struct node_queue, queue,
3193					    nqueues,
3194						printf("%s ", queue->queue);
3195					);
3196					printf("}");
3197				}
3198				printf("\n");
3199			}
3200		}
3201	);
3202
3203	FREE_LIST(struct node_queue, nqueues);
3204
3205	if (!added) {
3206		yyerror("queue has no parent");
3207		return (1);
3208	} else
3209		return (0);
3210}
3211
3212void
3213expand_rule(struct pf_rule *r,
3214    struct node_if *interfaces, struct node_host *rpool_hosts,
3215    struct node_proto *protos, struct node_host *src_hosts,
3216    struct node_port *src_ports, struct node_host *dst_hosts,
3217    struct node_port *dst_ports, struct node_uid *uids,
3218    struct node_gid *gids, struct node_icmp *icmp_types)
3219{
3220	sa_family_t		 af = r->af;
3221	int			 added = 0, error = 0;
3222	char			 ifname[IF_NAMESIZE];
3223	char			 label[PF_RULE_LABEL_SIZE];
3224	struct pf_pooladdr	*pa;
3225	struct node_host	*h;
3226	u_int8_t		 flags, flagset;
3227
3228	if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label))
3229		errx(1, "expand_rule: strlcpy");
3230	flags = r->flags;
3231	flagset = r->flagset;
3232
3233	LOOP_THROUGH(struct node_if, interface, interfaces,
3234	LOOP_THROUGH(struct node_proto, proto, protos,
3235	LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
3236	LOOP_THROUGH(struct node_host, src_host, src_hosts,
3237	LOOP_THROUGH(struct node_port, src_port, src_ports,
3238	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
3239	LOOP_THROUGH(struct node_port, dst_port, dst_ports,
3240	LOOP_THROUGH(struct node_uid, uid, uids,
3241	LOOP_THROUGH(struct node_gid, gid, gids,
3242
3243		r->af = af;
3244		/* for link-local IPv6 address, interface must match up */
3245		if ((r->af && src_host->af && r->af != src_host->af) ||
3246		    (r->af && dst_host->af && r->af != dst_host->af) ||
3247		    (src_host->af && dst_host->af &&
3248		    src_host->af != dst_host->af) ||
3249		    (src_host->ifindex && dst_host->ifindex &&
3250		    src_host->ifindex != dst_host->ifindex) ||
3251		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
3252		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
3253		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
3254		    dst_host->ifindex != if_nametoindex(interface->ifname)))
3255			continue;
3256		if (!r->af && src_host->af)
3257			r->af = src_host->af;
3258		else if (!r->af && dst_host->af)
3259			r->af = dst_host->af;
3260
3261		if (if_indextoname(src_host->ifindex, ifname))
3262			memcpy(r->ifname, ifname, sizeof(r->ifname));
3263		else if (if_indextoname(dst_host->ifindex, ifname))
3264			memcpy(r->ifname, ifname, sizeof(r->ifname));
3265		else
3266			memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
3267
3268		if (strlcpy(r->label, label, sizeof(r->label)) >=
3269		    sizeof(r->label))
3270			errx(1, "expand_rule: strlcpy");
3271		expand_label(r->label, r->ifname, r->af, src_host, src_port,
3272		    dst_host, dst_port, proto->proto);
3273		r->qid = qname_to_qid(r->qname, r->ifname);
3274		r->ifnot = interface->not;
3275		r->proto = proto->proto;
3276		r->src.addr = src_host->addr;
3277		r->src.not = src_host->not;
3278		r->src.port[0] = src_port->port[0];
3279		r->src.port[1] = src_port->port[1];
3280		r->src.port_op = src_port->op;
3281		r->dst.addr = dst_host->addr;
3282		r->dst.not = dst_host->not;
3283		r->dst.port[0] = dst_port->port[0];
3284		r->dst.port[1] = dst_port->port[1];
3285		r->dst.port_op = dst_port->op;
3286		r->uid.op = uid->op;
3287		r->uid.uid[0] = uid->uid[0];
3288		r->uid.uid[1] = uid->uid[1];
3289		r->gid.op = gid->op;
3290		r->gid.gid[0] = gid->gid[0];
3291		r->gid.gid[1] = gid->gid[1];
3292		r->type = icmp_type->type;
3293		r->code = icmp_type->code;
3294
3295		if (r->proto && r->proto != IPPROTO_TCP) {
3296			r->flags = 0;
3297			r->flagset = 0;
3298		} else {
3299			r->flags = flags;
3300			r->flagset = flagset;
3301		}
3302		if (icmp_type->proto && r->proto != icmp_type->proto) {
3303			yyerror("icmp-type mismatch");
3304			error++;
3305		}
3306
3307		TAILQ_INIT(&r->rpool.list);
3308		for (h = rpool_hosts; h != NULL; h = h->next) {
3309			pa = calloc(1, sizeof(struct pf_pooladdr));
3310			if (pa == NULL)
3311				err(1, "expand_rule: calloc");
3312			pa->addr.addr = h->addr;
3313			if (h->ifname != NULL) {
3314				if (strlcpy(pa->ifname, h->ifname,
3315				    sizeof(pa->ifname)) >=
3316				    sizeof(pa->ifname))
3317					errx(1, "expand_rule: strlcpy");
3318			} else
3319				pa->ifname[0] = 0;
3320			TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries);
3321		}
3322
3323		if (rule_consistent(r) < 0 || error)
3324			yyerror("skipping filter rule due to errors");
3325		else {
3326			r->nr = pf->rule_nr++;
3327			pfctl_add_rule(pf, r);
3328			added++;
3329		}
3330
3331	)))))))));
3332
3333	FREE_LIST(struct node_if, interfaces);
3334	FREE_LIST(struct node_proto, protos);
3335	FREE_LIST(struct node_host, src_hosts);
3336	FREE_LIST(struct node_port, src_ports);
3337	FREE_LIST(struct node_host, dst_hosts);
3338	FREE_LIST(struct node_port, dst_ports);
3339	FREE_LIST(struct node_uid, uids);
3340	FREE_LIST(struct node_gid, gids);
3341	FREE_LIST(struct node_icmp, icmp_types);
3342	FREE_LIST(struct node_host, rpool_hosts);
3343
3344	if (!added)
3345		yyerror("rule expands to no valid combination");
3346}
3347
3348void
3349expand_nat(struct pf_rule *n,
3350    struct node_if *interfaces, struct node_proto *protos,
3351    struct node_host *src_hosts, struct node_port *src_ports,
3352    struct node_host *dst_hosts, struct node_port *dst_ports,
3353    struct node_host *rpool_hosts)
3354{
3355	char			 ifname[IF_NAMESIZE];
3356	struct pf_pooladdr	*pa;
3357	struct node_host	*h;
3358	sa_family_t		 af = n->af;
3359	int			 added = 0, error = 0;
3360
3361	LOOP_THROUGH(struct node_if, interface, interfaces,
3362	LOOP_THROUGH(struct node_proto, proto, protos,
3363	LOOP_THROUGH(struct node_host, src_host, src_hosts,
3364	LOOP_THROUGH(struct node_port, src_port, src_ports,
3365	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
3366	LOOP_THROUGH(struct node_port, dst_port, dst_ports,
3367
3368		n->af = af;
3369		/* for link-local IPv6 address, interface must match up */
3370		if ((n->af && src_host->af && n->af != src_host->af) ||
3371		    (n->af && dst_host->af && n->af != dst_host->af) ||
3372		    (src_host->af && dst_host->af &&
3373		    src_host->af != dst_host->af) ||
3374		    (src_host->ifindex && dst_host->ifindex &&
3375		    src_host->ifindex != dst_host->ifindex) ||
3376		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
3377		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
3378		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
3379		    dst_host->ifindex != if_nametoindex(interface->ifname)))
3380			continue;
3381		if (!n->af && src_host->af)
3382			n->af = src_host->af;
3383		else if (!n->af && dst_host->af)
3384			n->af = dst_host->af;
3385
3386		if (if_indextoname(src_host->ifindex, ifname))
3387			memcpy(n->ifname, ifname, sizeof(n->ifname));
3388		else if (if_indextoname(dst_host->ifindex, ifname))
3389			memcpy(n->ifname, ifname, sizeof(n->ifname));
3390		else
3391			memcpy(n->ifname, interface->ifname, sizeof(n->ifname));
3392
3393		n->ifnot = interface->not;
3394		n->proto = proto->proto;
3395		n->src.addr = src_host->addr;
3396		n->src.not = src_host->not;
3397		n->src.port[0] = src_port->port[0];
3398		n->src.port[1] = src_port->port[1];
3399		n->src.port_op = src_port->op;
3400		n->dst.addr = dst_host->addr;
3401		n->dst.not = dst_host->not;
3402		n->dst.port[0] = dst_port->port[0];
3403		n->dst.port[1] = dst_port->port[1];
3404		n->dst.port_op = dst_port->op;
3405
3406		TAILQ_INIT(&n->rpool.list);
3407		for (h = rpool_hosts; h != NULL; h = h->next) {
3408			pa = calloc(1, sizeof(struct pf_pooladdr));
3409			if (pa == NULL)
3410				err(1, "expand_nat: calloc");
3411			pa->addr.addr = h->addr;
3412			pa->ifname[0] = 0;
3413			TAILQ_INSERT_TAIL(&n->rpool.list, pa, entries);
3414		}
3415
3416		if (nat_consistent(n) < 0 || error)
3417			yyerror("skipping nat rule due to errors");
3418		else {
3419			pfctl_add_rule(pf, n);
3420			added++;
3421		}
3422
3423	))))));
3424
3425	FREE_LIST(struct node_if, interfaces);
3426	FREE_LIST(struct node_proto, protos);
3427	FREE_LIST(struct node_host, src_hosts);
3428	FREE_LIST(struct node_port, src_ports);
3429	FREE_LIST(struct node_host, dst_hosts);
3430	FREE_LIST(struct node_port, dst_ports);
3431	FREE_LIST(struct node_host, rpool_hosts);
3432
3433	if (!added)
3434		yyerror("nat rule expands to no valid combinations");
3435}
3436
3437void
3438expand_rdr(struct pf_rule *r, struct node_if *interfaces,
3439    struct node_proto *protos, struct node_host *src_hosts,
3440    struct node_host *dst_hosts, struct node_host *rpool_hosts)
3441{
3442	sa_family_t		 af = r->af;
3443	int			 added = 0, error = 0;
3444	char			 ifname[IF_NAMESIZE];
3445	struct pf_pooladdr	*pa;
3446	struct node_host	*h;
3447
3448	LOOP_THROUGH(struct node_if, interface, interfaces,
3449	LOOP_THROUGH(struct node_proto, proto, protos,
3450	LOOP_THROUGH(struct node_host, src_host, src_hosts,
3451	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
3452
3453		r->af = af;
3454		if ((r->af && src_host->af && r->af != src_host->af) ||
3455		    (r->af && dst_host->af && r->af != dst_host->af) ||
3456		    (src_host->af && dst_host->af &&
3457		    src_host->af != dst_host->af) ||
3458		    (src_host->ifindex && dst_host->ifindex &&
3459		    src_host->ifindex != dst_host->ifindex) ||
3460		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
3461		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
3462		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
3463		    dst_host->ifindex != if_nametoindex(interface->ifname)))
3464			continue;
3465
3466		if (!r->af && src_host->af)
3467			r->af = src_host->af;
3468		else if (!r->af && dst_host->af)
3469			r->af = dst_host->af;
3470
3471		if (if_indextoname(src_host->ifindex, ifname))
3472			memcpy(r->ifname, ifname, sizeof(r->ifname));
3473		else if (if_indextoname(dst_host->ifindex, ifname))
3474			memcpy(r->ifname, ifname, sizeof(r->ifname));
3475		else
3476			memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
3477
3478		r->ifnot = interface->not;
3479		r->proto = proto->proto;
3480		r->src.addr = src_host->addr;
3481		r->src.not = src_host->not;
3482		r->dst.addr = dst_host->addr;
3483		r->dst.not = dst_host->not;
3484
3485		TAILQ_INIT(&r->rpool.list);
3486		for (h = rpool_hosts; h != NULL; h = h->next) {
3487			pa = calloc(1, sizeof(struct pf_pooladdr));
3488			if (pa == NULL)
3489				err(1, "expand_rdr: calloc");
3490			pa->addr.addr = h->addr;
3491			pa->ifname[0] = 0;
3492			TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries);
3493		}
3494
3495		if (rdr_consistent(r) < 0 || error)
3496			yyerror("skipping rdr rule due to errors");
3497		else {
3498			pfctl_add_rule(pf, r);
3499			added++;
3500		}
3501
3502	))));
3503
3504	FREE_LIST(struct node_if, interfaces);
3505	FREE_LIST(struct node_proto, protos);
3506	FREE_LIST(struct node_host, src_hosts);
3507	FREE_LIST(struct node_host, dst_hosts);
3508	FREE_LIST(struct node_host, rpool_hosts);
3509
3510	if (!added)
3511		yyerror("rdr rule expands to no valid combination");
3512}
3513
3514#undef FREE_LIST
3515#undef LOOP_THROUGH
3516
3517int
3518check_rulestate(int desired_state)
3519{
3520	if (require_order && (rulestate > desired_state)) {
3521		yyerror("Rules must be in order: options, scrub, "
3522		    "queue, NAT, filter");
3523		return (1);
3524	}
3525	rulestate = desired_state;
3526	return (0);
3527}
3528
3529int
3530kw_cmp(const void *k, const void *e)
3531{
3532	return (strcmp(k, ((const struct keywords *)e)->k_name));
3533}
3534
3535int
3536lookup(char *s)
3537{
3538	/* this has to be sorted always */
3539	static const struct keywords keywords[] = {
3540		{ "all",		ALL},
3541		{ "allow-opts",		ALLOWOPTS},
3542		{ "altq",		ALTQ},
3543		{ "anchor",		ANCHOR},
3544		{ "antispoof",		ANTISPOOF},
3545		{ "any",		ANY},
3546		{ "bandwidth",		BANDWIDTH},
3547		{ "binat",		BINAT},
3548		{ "binat-anchor",	BINATANCHOR},
3549		{ "bitmask",		BITMASK},
3550		{ "block",		BLOCK},
3551		{ "block-policy",	BLOCKPOLICY},
3552		{ "borrow",		BORROW},
3553		{ "cbq",		CBQ},
3554		{ "code",		CODE},
3555		{ "control",		CONTROL},
3556		{ "crop",		FRAGCROP},
3557		{ "default",		DEFAULT},
3558		{ "drop",		DROP},
3559		{ "drop-ovl",		FRAGDROP},
3560		{ "dup-to",		DUPTO},
3561		{ "ecn",		ECN},
3562		{ "fastroute",		FASTROUTE},
3563		{ "file",		FILENAME},
3564		{ "flags",		FLAGS},
3565		{ "for",		FOR},
3566		{ "fragment",		FRAGMENT},
3567		{ "from",		FROM},
3568		{ "group",		GROUP},
3569		{ "icmp-type",		ICMPTYPE},
3570		{ "icmp6-type",		ICMP6TYPE},
3571		{ "in",			IN},
3572		{ "inet",		INET},
3573		{ "inet6",		INET6},
3574		{ "keep",		KEEP},
3575		{ "label",		LABEL},
3576		{ "limit",		LIMIT},
3577		{ "log",		LOG},
3578		{ "log-all",		LOGALL},
3579		{ "loginterface",	LOGINTERFACE},
3580		{ "max",		MAXIMUM},
3581		{ "max-mss",		MAXMSS},
3582		{ "min-ttl",		MINTTL},
3583		{ "modulate",		MODULATE},
3584		{ "nat",		NAT},
3585		{ "nat-anchor",		NATANCHOR},
3586		{ "no",			NO},
3587		{ "no-df",		NODF},
3588		{ "no-route",		NOROUTE},
3589		{ "on",			ON},
3590		{ "optimization",	OPTIMIZATION},
3591		{ "out",		OUT},
3592		{ "pass",		PASS},
3593		{ "port",		PORT},
3594		{ "priority",		PRIORITY},
3595		{ "priq",		PRIQ},
3596		{ "proto",		PROTO},
3597		{ "qlimit",		QLIMIT},
3598		{ "queue",		QUEUE},
3599		{ "quick",		QUICK},
3600		{ "random",		RANDOM},
3601		{ "rdr",		RDR},
3602		{ "rdr-anchor",		RDRANCHOR},
3603		{ "reassemble",		FRAGNORM},
3604		{ "red",		RED},
3605		{ "reply-to",		REPLYTO},
3606		{ "require-order",	REQUIREORDER},
3607		{ "return",		RETURN},
3608		{ "return-icmp",	RETURNICMP},
3609		{ "return-icmp6",	RETURNICMP6},
3610		{ "return-rst",		RETURNRST},
3611		{ "rio",		RIO},
3612		{ "round-robin",	ROUNDROBIN},
3613		{ "route-to",		ROUTETO},
3614		{ "scrub",		SCRUB},
3615		{ "set",		SET},
3616		{ "source-hash",	SOURCEHASH},
3617		{ "state",		STATE},
3618		{ "static-port",	STATICPORT},
3619		{ "table",		TABLE},
3620		{ "tbrsize",		TBRSIZE},
3621		{ "timeout",		TIMEOUT},
3622		{ "to",			TO},
3623		{ "tos",		TOS},
3624		{ "ttl",		TTL},
3625		{ "user",		USER},
3626		{ "yes",		YES},
3627	};
3628	const struct keywords	*p;
3629
3630	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
3631	    sizeof(keywords[0]), kw_cmp);
3632
3633	if (p) {
3634		if (debug > 1)
3635			fprintf(stderr, "%s: %d\n", s, p->k_val);
3636		return (p->k_val);
3637	} else {
3638		if (debug > 1)
3639			fprintf(stderr, "string: %s\n", s);
3640		return (STRING);
3641	}
3642}
3643
3644#define MAXPUSHBACK	128
3645
3646char	*parsebuf;
3647int	 parseindex;
3648char	 pushback_buffer[MAXPUSHBACK];
3649int	 pushback_index = 0;
3650
3651int
3652lgetc(FILE *f)
3653{
3654	int	c, next;
3655
3656	if (parsebuf) {
3657		/* Read character from the parsebuffer instead of input. */
3658		if (parseindex >= 0) {
3659			c = parsebuf[parseindex++];
3660			if (c != '\0')
3661				return (c);
3662			parsebuf = NULL;
3663		} else
3664			parseindex++;
3665	}
3666
3667	if (pushback_index)
3668		return (pushback_buffer[--pushback_index]);
3669
3670	while ((c = getc(f)) == '\\') {
3671		next = getc(f);
3672		if (next != '\n') {
3673			if (isspace(next))
3674				yyerror("whitespace after \\");
3675			ungetc(next, f);
3676			break;
3677		}
3678		yylval.lineno = lineno;
3679		lineno++;
3680	}
3681	if (c == '\t' || c == ' ') {
3682		/* Compress blanks to a single space. */
3683		do {
3684			c = getc(f);
3685		} while (c == '\t' || c == ' ');
3686		ungetc(c, f);
3687		c = ' ';
3688	}
3689
3690	return (c);
3691}
3692
3693int
3694lungetc(int c)
3695{
3696	if (c == EOF)
3697		return (EOF);
3698	if (parsebuf) {
3699		parseindex--;
3700		if (parseindex >= 0)
3701			return (c);
3702	}
3703	if (pushback_index < MAXPUSHBACK-1)
3704		return (pushback_buffer[pushback_index++] = c);
3705	else
3706		return (EOF);
3707}
3708
3709int
3710findeol(void)
3711{
3712	int	c;
3713
3714	parsebuf = NULL;
3715	pushback_index = 0;
3716
3717	/* skip to either EOF or the first real EOL */
3718	while (1) {
3719		c = lgetc(fin);
3720		if (c == '\n') {
3721			lineno++;
3722			break;
3723		}
3724		if (c == EOF)
3725			break;
3726	}
3727	return (ERROR);
3728}
3729
3730int
3731yylex(void)
3732{
3733	char	 buf[8096];
3734	char	*p, *val;
3735	int	 endc, c, next;
3736	int	 token;
3737
3738top:
3739	p = buf;
3740	while ((c = lgetc(fin)) == ' ')
3741		; /* nothing */
3742
3743	yylval.lineno = lineno;
3744	if (c == '#')
3745		while ((c = lgetc(fin)) != '\n' && c != EOF)
3746			; /* nothing */
3747	if (c == '$' && parsebuf == NULL) {
3748		while (1) {
3749			if ((c = lgetc(fin)) == EOF)
3750				return (0);
3751
3752			if (p + 1 >= buf + sizeof(buf) - 1) {
3753				yyerror("string too long");
3754				return (findeol());
3755			}
3756			if (isalnum(c) || c == '_') {
3757				*p++ = (char)c;
3758				continue;
3759			}
3760			*p = '\0';
3761			lungetc(c);
3762			break;
3763		}
3764		val = symget(buf);
3765		if (val == NULL) {
3766			yyerror("macro '%s' not defined", buf);
3767			return (findeol());
3768		}
3769		parsebuf = val;
3770		parseindex = 0;
3771		goto top;
3772	}
3773
3774	switch (c) {
3775	case '\'':
3776	case '"':
3777		endc = c;
3778		while (1) {
3779			if ((c = lgetc(fin)) == EOF)
3780				return (0);
3781			if (c == endc) {
3782				*p = '\0';
3783				break;
3784			}
3785			if (c == '\n') {
3786				lineno++;
3787				continue;
3788			}
3789			if (p + 1 >= buf + sizeof(buf) - 1) {
3790				yyerror("string too long");
3791				return (findeol());
3792			}
3793			*p++ = (char)c;
3794		}
3795		yylval.v.string = strdup(buf);
3796		if (yylval.v.string == NULL)
3797			err(1, "yylex: strdup");
3798		return (STRING);
3799	case '=':
3800		yylval.v.i = PF_OP_EQ;
3801		return (PORTUNARY);
3802	case '!':
3803		next = lgetc(fin);
3804		if (next == '=') {
3805			yylval.v.i = PF_OP_NE;
3806			return (PORTUNARY);
3807		}
3808		lungetc(next);
3809		break;
3810	case '<':
3811		next = lgetc(fin);
3812		if (next == '>') {
3813			yylval.v.i = PF_OP_XRG;
3814			return (PORTBINARY);
3815		} else if (next == '=') {
3816			yylval.v.i = PF_OP_LE;
3817		} else {
3818			yylval.v.i = PF_OP_LT;
3819			lungetc(next);
3820		}
3821		return (PORTUNARY);
3822		break;
3823	case '>':
3824		next = lgetc(fin);
3825		if (next == '<') {
3826			yylval.v.i = PF_OP_IRG;
3827			return (PORTBINARY);
3828		} else if (next == '=') {
3829			yylval.v.i = PF_OP_GE;
3830		} else {
3831			yylval.v.i = PF_OP_GT;
3832			lungetc(next);
3833		}
3834		return (PORTUNARY);
3835		break;
3836	case '-':
3837		next = lgetc(fin);
3838		if (next == '>')
3839			return (ARROW);
3840		lungetc(next);
3841		break;
3842	}
3843
3844#define allowed_in_string(x) \
3845	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
3846	x != '{' && x != '}' && x != '<' && x != '>' && \
3847	x != '!' && x != '=' && x != '/' && x != '#' && \
3848	x != ','))
3849
3850	if (isalnum(c) || c == ':' || c == '_') {
3851		do {
3852			*p++ = c;
3853			if ((unsigned)(p-buf) >= sizeof(buf)) {
3854				yyerror("string too long");
3855				return (findeol());
3856			}
3857		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
3858		lungetc(c);
3859		*p = '\0';
3860		token = lookup(buf);
3861		yylval.v.string = strdup(buf);
3862		if (yylval.v.string == NULL)
3863			err(1, "yylex: strdup");
3864		return (token);
3865	}
3866	if (c == '\n') {
3867		yylval.lineno = lineno;
3868		lineno++;
3869	}
3870	if (c == EOF)
3871		return (0);
3872	return (c);
3873}
3874
3875int
3876parse_rules(FILE *input, struct pfctl *xpf)
3877{
3878	struct sym	*sym;
3879
3880	fin = input;
3881	pf = xpf;
3882	lineno = 1;
3883	errors = 0;
3884	rulestate = PFCTL_STATE_NONE;
3885	yyparse();
3886
3887	/* Check which macros have not been used. */
3888	if (pf->opts & PF_OPT_VERBOSE2) {
3889		for (sym = symhead; sym; sym = sym->next)
3890			if (!sym->used)
3891				fprintf(stderr, "warning: macro '%s' not "
3892				    "used\n", sym->nam);
3893	}
3894	return (errors ? -1 : 0);
3895}
3896
3897/*
3898 * Over-designed efficiency is a French and German concept, so how about
3899 * we wait until they discover this ugliness and make it all fancy.
3900 */
3901int
3902symset(const char *nam, const char *val)
3903{
3904	struct sym	*sym;
3905
3906	sym = calloc(1, sizeof(*sym));
3907	if (sym == NULL)
3908		return (-1);
3909	sym->nam = strdup(nam);
3910	if (sym->nam == NULL) {
3911		free(sym);
3912		return (-1);
3913	}
3914	sym->val = strdup(val);
3915	if (sym->val == NULL) {
3916		free(sym->nam);
3917		free(sym);
3918		return (-1);
3919	}
3920	sym->next = symhead;
3921	sym->used = 0;
3922	symhead = sym;
3923	return (0);
3924}
3925
3926char *
3927symget(const char *nam)
3928{
3929	struct sym	*sym;
3930
3931	for (sym = symhead; sym; sym = sym->next)
3932		if (strcmp(nam, sym->nam) == 0) {
3933			sym->used = 1;
3934			return (sym->val);
3935		}
3936	return (NULL);
3937}
3938
3939void
3940decide_address_family(struct node_host *n, sa_family_t *af)
3941{
3942	sa_family_t	target_af = 0;
3943
3944	while (!*af && n != NULL) {
3945		if (n->af) {
3946			if (target_af == 0)
3947				target_af = n->af;
3948			if (target_af != n->af)
3949				return;
3950		}
3951		n = n->next;
3952	}
3953	if (!*af && target_af)
3954		*af = target_af;
3955}
3956
3957void
3958remove_invalid_hosts(struct node_host **nh, sa_family_t *af)
3959{
3960	struct node_host	*n = *nh, *prev = NULL;
3961
3962	while (n != NULL) {
3963		if (*af && n->af && n->af != *af) {
3964			/* unlink and free n */
3965			struct node_host *next = n->next;
3966
3967			/* adjust tail pointer */
3968			if (n == (*nh)->tail)
3969				(*nh)->tail = prev;
3970			/* adjust previous node's next pointer */
3971			if (prev == NULL)
3972				*nh = next;
3973			else
3974				prev->next = next;
3975			/* free node */
3976			if (n->ifname != NULL)
3977				free(n->ifname);
3978			free(n);
3979			n = next;
3980		} else {
3981			if (n->af && !*af)
3982				*af = n->af;
3983			prev = n;
3984			n = n->next;
3985		}
3986	}
3987
3988	if (!*af)
3989		yyerror("address family not given and translation "
3990		    "address expands to multiple address families");
3991	else if (*nh == NULL)
3992		yyerror("no translation address with matching address family "
3993		    "found.");
3994}
3995
3996int
3997atoul(char *s, u_long *ulvalp)
3998{
3999	u_long	 ulval;
4000	char	*ep;
4001
4002	errno = 0;
4003	ulval = strtoul(s, &ep, 0);
4004	if (s[0] == '\0' || *ep != '\0')
4005		return (-1);
4006	if (errno == ERANGE && ulval == ULONG_MAX)
4007		return (-1);
4008	*ulvalp = ulval;
4009	return (0);
4010}
4011
4012int
4013getservice(char *n)
4014{
4015	struct servent	*s;
4016	u_long		 ulval;
4017
4018	if (atoul(n, &ulval) == 0) {
4019		if (ulval > 65535) {
4020			yyerror("illegal port value %d", ulval);
4021			return (-1);
4022		}
4023		return (htons(ulval));
4024	} else {
4025		s = getservbyname(n, "tcp");
4026		if (s == NULL)
4027			s = getservbyname(n, "udp");
4028		if (s == NULL) {
4029			yyerror("unknown port %s", n);
4030			return (-1);
4031		}
4032		return (s->s_port);
4033	}
4034}
4035
4036u_int16_t
4037parseicmpspec(char *w, sa_family_t af)
4038{
4039	const struct icmpcodeent	*p;
4040	u_long				 ulval;
4041	u_int8_t			 icmptype;
4042
4043	if (af == AF_INET)
4044		icmptype = returnicmpdefault >> 8;
4045	else
4046		icmptype = returnicmp6default >> 8;
4047
4048	if (atoul(w, &ulval) == -1) {
4049		if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
4050			yyerror("unknown icmp code %s", w);
4051			return (0);
4052		}
4053		ulval = p->code;
4054	}
4055	return (icmptype << 8 | ulval);
4056}
4057