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