1/*	$NetBSD: parse.y,v 1.12 2009/06/16 05:16:52 minskim Exp $	*/
2/*	$OpenBSD: parse.y,v 1.519 2007/06/21 19:30:03 henning Exp $	*/
3
4/*
5 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
6 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
7 * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
8 * Copyright (c) 2002,2003 Henning Brauer. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30%{
31#include <sys/types.h>
32#include <sys/socket.h>
33#include <net/if.h>
34#include <netinet/in.h>
35#include <netinet/in_systm.h>
36#include <netinet/ip.h>
37#include <netinet/ip_icmp.h>
38#include <netinet/icmp6.h>
39#include <net/pfvar.h>
40#include <arpa/inet.h>
41#include <altq/altq.h>
42#include <altq/altq_cbq.h>
43#include <altq/altq_priq.h>
44#include <altq/altq_hfsc.h>
45
46#include <stdio.h>
47#include <stdlib.h>
48#include <netdb.h>
49#include <stdarg.h>
50#include <errno.h>
51#include <string.h>
52#include <ctype.h>
53#include <math.h>
54#include <err.h>
55#include <limits.h>
56#include <pwd.h>
57#include <grp.h>
58#include <md5.h>
59
60#include "pfctl_parser.h"
61#include "pfctl.h"
62
63#ifndef RT_TABLEID_MAX
64#define RT_TABLEID_MAX	255
65#endif /* !RT_TABLEID_MAX */
66
67static struct pfctl	*pf = NULL;
68static FILE		*fin = NULL;
69static int		 debug = 0;
70static int		 lineno = 1;
71static int		 errors = 0;
72static int		 rulestate = 0;
73static u_int16_t	 returnicmpdefault =
74			    (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
75static u_int16_t	 returnicmp6default =
76			    (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
77static int		 blockpolicy = PFRULE_DROP;
78static int		 require_order = 1;
79static int		 default_statelock;
80
81enum {
82	PFCTL_STATE_NONE,
83	PFCTL_STATE_OPTION,
84	PFCTL_STATE_SCRUB,
85	PFCTL_STATE_QUEUE,
86	PFCTL_STATE_NAT,
87	PFCTL_STATE_FILTER
88};
89
90struct node_proto {
91	u_int8_t		 proto;
92	struct node_proto	*next;
93	struct node_proto	*tail;
94};
95
96struct node_port {
97	u_int16_t		 port[2];
98	u_int8_t		 op;
99	struct node_port	*next;
100	struct node_port	*tail;
101};
102
103struct node_uid {
104	uid_t			 uid[2];
105	u_int8_t		 op;
106	struct node_uid		*next;
107	struct node_uid		*tail;
108};
109
110struct node_gid {
111	gid_t			 gid[2];
112	u_int8_t		 op;
113	struct node_gid		*next;
114	struct node_gid		*tail;
115};
116
117struct node_icmp {
118	u_int8_t		 code;
119	u_int8_t		 type;
120	u_int8_t		 proto;
121	struct node_icmp	*next;
122	struct node_icmp	*tail;
123};
124
125enum	{ PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
126	    PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN,
127	    PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES,
128	    PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK,
129	    PF_STATE_OPT_TIMEOUT };
130
131enum	{ PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
132
133struct node_state_opt {
134	int			 type;
135	union {
136		u_int32_t	 max_states;
137		u_int32_t	 max_src_states;
138		u_int32_t	 max_src_conn;
139		struct {
140			u_int32_t	limit;
141			u_int32_t	seconds;
142		}		 max_src_conn_rate;
143		struct {
144			u_int8_t	flush;
145			char		tblname[PF_TABLE_NAME_SIZE];
146		}		 overload;
147		u_int32_t	 max_src_nodes;
148		u_int8_t	 src_track;
149		u_int32_t	 statelock;
150		struct {
151			int		number;
152			u_int32_t	seconds;
153		}		 timeout;
154	}			 data;
155	struct node_state_opt	*next;
156	struct node_state_opt	*tail;
157};
158
159struct peer {
160	struct node_host	*host;
161	struct node_port	*port;
162};
163
164struct node_queue {
165	char			 queue[PF_QNAME_SIZE];
166	char			 parent[PF_QNAME_SIZE];
167	char			 ifname[IFNAMSIZ];
168	int			 scheduler;
169	struct node_queue	*next;
170	struct node_queue	*tail;
171}	*queues = NULL;
172
173struct node_qassign {
174	char		*qname;
175	char		*pqname;
176};
177
178struct filter_opts {
179	int			 marker;
180#define FOM_FLAGS	0x01
181#define FOM_ICMP	0x02
182#define FOM_TOS		0x04
183#define FOM_KEEP	0x08
184#define FOM_SRCTRACK	0x10
185	struct node_uid		*uid;
186	struct node_gid		*gid;
187	struct {
188		u_int8_t	 b1;
189		u_int8_t	 b2;
190		u_int16_t	 w;
191		u_int16_t	 w2;
192	} flags;
193	struct node_icmp	*icmpspec;
194	u_int32_t		 tos;
195	u_int32_t		 prob;
196	struct {
197		int			 action;
198		struct node_state_opt	*options;
199	} keep;
200	int			 fragment;
201	int			 allowopts;
202	char			*label;
203	struct node_qassign	 queues;
204	char			*tag;
205	char			*match_tag;
206	u_int8_t		 match_tag_not;
207	int			 rtableid;
208} filter_opts;
209
210struct antispoof_opts {
211	char			*label;
212	int			 rtableid;
213} antispoof_opts;
214
215struct scrub_opts {
216	int			marker;
217#define SOM_MINTTL	0x01
218#define SOM_MAXMSS	0x02
219#define SOM_FRAGCACHE	0x04
220	int			nodf;
221	int			minttl;
222	int			maxmss;
223	int			fragcache;
224	int			randomid;
225	int			reassemble_tcp;
226	int			rtableid;
227} scrub_opts;
228
229struct queue_opts {
230	int			marker;
231#define QOM_BWSPEC	0x01
232#define QOM_SCHEDULER	0x02
233#define QOM_PRIORITY	0x04
234#define QOM_TBRSIZE	0x08
235#define QOM_QLIMIT	0x10
236	struct node_queue_bw	queue_bwspec;
237	struct node_queue_opt	scheduler;
238	int			priority;
239	int			tbrsize;
240	int			qlimit;
241} queue_opts;
242
243struct table_opts {
244	int			flags;
245	int			init_addr;
246	struct node_tinithead	init_nodes;
247} table_opts;
248
249struct pool_opts {
250	int			 marker;
251#define POM_TYPE		0x01
252#define POM_STICKYADDRESS	0x02
253	u_int8_t		 opts;
254	int			 type;
255	int			 staticport;
256	struct pf_poolhashkey	*key;
257
258} pool_opts;
259
260
261struct node_hfsc_opts	hfsc_opts;
262
263int	yyerror(const char *, ...);
264int	disallow_table(struct node_host *, const char *);
265int	disallow_urpf_failed(struct node_host *, const char *);
266int	disallow_alias(struct node_host *, const char *);
267int	rule_consistent(struct pf_rule *, int);
268int	filter_consistent(struct pf_rule *, int);
269int	nat_consistent(struct pf_rule *);
270int	rdr_consistent(struct pf_rule *);
271int	process_tabledef(char *, struct table_opts *);
272int	yyparse(void);
273void	expand_label_str(char *, size_t, const char *, const char *);
274void	expand_label_if(const char *, char *, size_t, const char *);
275void	expand_label_addr(const char *, char *, size_t, u_int8_t,
276	    struct node_host *);
277void	expand_label_port(const char *, char *, size_t, struct node_port *);
278void	expand_label_proto(const char *, char *, size_t, u_int8_t);
279void	expand_label_nr(const char *, char *, size_t);
280void	expand_label(char *, size_t, const char *, u_int8_t, struct node_host *,
281	    struct node_port *, struct node_host *, struct node_port *,
282	    u_int8_t);
283void	expand_rule(struct pf_rule *, struct node_if *, struct node_host *,
284	    struct node_proto *, struct node_os*, struct node_host *,
285	    struct node_port *, struct node_host *, struct node_port *,
286	    struct node_uid *, struct node_gid *, struct node_icmp *,
287	    const char *);
288int	expand_altq(struct pf_altq *, struct node_if *, struct node_queue *,
289	    struct node_queue_bw bwspec, struct node_queue_opt *);
290int	expand_queue(struct pf_altq *, struct node_if *, struct node_queue *,
291	    struct node_queue_bw, struct node_queue_opt *);
292int	expand_skip_interface(struct node_if *);
293
294int	 check_rulestate(int);
295int	 kw_cmp(const void *, const void *);
296int	 lookup(char *);
297int	 lgetc(FILE *);
298int	 lungetc(int);
299int	 findeol(void);
300int	 yylex(void);
301int	 atoul(char *, u_long *);
302int	 getservice(char *);
303int	 rule_label(struct pf_rule *, char *);
304
305TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
306struct sym {
307	TAILQ_ENTRY(sym)	 entries;
308	int			 used;
309	int			 persist;
310	char			*nam;
311	char			*val;
312};
313
314
315int	 symset(const char *, const char *, int);
316char	*symget(const char *);
317
318void	 mv_rules(struct pf_ruleset *, struct pf_ruleset *);
319void	 decide_address_family(struct node_host *, sa_family_t *);
320void	 remove_invalid_hosts(struct node_host **, sa_family_t *);
321int	 invalid_redirect(struct node_host *, sa_family_t);
322u_int16_t parseicmpspec(char *, sa_family_t);
323
324TAILQ_HEAD(loadanchorshead, loadanchors)
325    loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead);
326
327struct loadanchors {
328	TAILQ_ENTRY(loadanchors)	 entries;
329	char				*anchorname;
330	char				*filename;
331};
332
333typedef struct {
334	union {
335		u_int32_t		 number;
336		int			 i;
337		char			*string;
338		int			 rtableid;
339		struct {
340			u_int8_t	 b1;
341			u_int8_t	 b2;
342			u_int16_t	 w;
343			u_int16_t	 w2;
344		}			 b;
345		struct range {
346			int		 a;
347			int		 b;
348			int		 t;
349		}			 range;
350		struct node_if		*interface;
351		struct node_proto	*proto;
352		struct node_icmp	*icmp;
353		struct node_host	*host;
354		struct node_os		*os;
355		struct node_port	*port;
356		struct node_uid		*uid;
357		struct node_gid		*gid;
358		struct node_state_opt	*state_opt;
359		struct peer		 peer;
360		struct {
361			struct peer	 src, dst;
362			struct node_os	*src_os;
363		}			 fromto;
364		struct {
365			struct node_host	*host;
366			u_int8_t		 rt;
367			u_int8_t		 pool_opts;
368			sa_family_t		 af;
369			struct pf_poolhashkey	*key;
370		}			 route;
371		struct redirection {
372			struct node_host	*host;
373			struct range		 rport;
374		}			*redirection;
375		struct {
376			int			 action;
377			struct node_state_opt	*options;
378		}			 keep_state;
379		struct {
380			u_int8_t	 log;
381			u_int8_t	 logif;
382			u_int8_t	 quick;
383		}			 logquick;
384		struct {
385			int		 neg;
386			char		*name;
387		}			 tagged;
388		struct pf_poolhashkey	*hashkey;
389		struct node_queue	*queue;
390		struct node_queue_opt	 queue_options;
391		struct node_queue_bw	 queue_bwspec;
392		struct node_qassign	 qassign;
393		struct filter_opts	 filter_opts;
394		struct antispoof_opts	 antispoof_opts;
395		struct queue_opts	 queue_opts;
396		struct scrub_opts	 scrub_opts;
397		struct table_opts	 table_opts;
398		struct pool_opts	 pool_opts;
399		struct node_hfsc_opts	 hfsc_opts;
400	} v;
401	int lineno;
402} YYSTYPE;
403
404#define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
405	(!((addr).iflags & PFI_AFLAG_NOALIAS) ||		 \
406	!isdigit((unsigned char)(addr).v.ifname[strlen((addr).v.ifname)-1])))
407
408%}
409
410%token	PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
411%token	RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
412%token	ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
413%token	MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
414%token	NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
415%token	REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
416%token	SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
417%token	REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
418%token	ANTISPOOF FOR
419%token	BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
420%token	ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
421%token	QUEUE PRIORITY QLIMIT RTABLE
422%token	LOAD RULESET_OPTIMIZATION
423%token	STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
424%token	MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH
425%token	TAGGED TAG IFBOUND FLOATING STATEPOLICY ROUTE
426%token	<v.string>		STRING
427%token	<v.i>			PORTBINARY
428%type	<v.interface>		interface if_list if_item_not if_item
429%type	<v.number>		number icmptype icmp6type uid gid
430%type	<v.number>		tos not yesno
431%type	<v.i>			no dir af fragcache optimizer
432%type	<v.i>			sourcetrack flush unaryop statelock
433%type	<v.b>			action nataction natpasslog scrubaction
434%type	<v.b>			flags flag blockspec
435%type	<v.range>		port rport
436%type	<v.hashkey>		hashkey
437%type	<v.proto>		proto proto_list proto_item
438%type	<v.icmp>		icmpspec
439%type	<v.icmp>		icmp_list icmp_item
440%type	<v.icmp>		icmp6_list icmp6_item
441%type	<v.fromto>		fromto
442%type	<v.peer>		ipportspec from to
443%type	<v.host>		ipspec xhost host dynaddr host_list
444%type	<v.host>		redir_host_list redirspec
445%type	<v.host>		route_host route_host_list routespec
446%type	<v.os>			os xos os_list
447%type	<v.port>		portspec port_list port_item
448%type	<v.uid>			uids uid_list uid_item
449%type	<v.gid>			gids gid_list gid_item
450%type	<v.route>		route
451%type	<v.redirection>		redirection redirpool
452%type	<v.string>		label string tag anchorname
453%type	<v.keep_state>		keep
454%type	<v.state_opt>		state_opt_spec state_opt_list state_opt_item
455%type	<v.state_opt>		opt_statelock
456%type	<v.logquick>		logquick quick log logopts logopt
457%type	<v.interface>		antispoof_ifspc antispoof_iflst antispoof_if
458%type	<v.qassign>		qname
459%type	<v.queue>		qassign qassign_list qassign_item
460%type	<v.queue_options>	scheduler
461%type	<v.number>		cbqflags_list cbqflags_item
462%type	<v.number>		priqflags_list priqflags_item
463%type	<v.hfsc_opts>		hfscopts_list hfscopts_item hfsc_opts
464%type	<v.queue_bwspec>	bandwidth
465%type	<v.filter_opts>		filter_opts filter_opt filter_opts_l
466%type	<v.antispoof_opts>	antispoof_opts antispoof_opt antispoof_opts_l
467%type	<v.queue_opts>		queue_opts queue_opt queue_opts_l
468%type	<v.scrub_opts>		scrub_opts scrub_opt scrub_opts_l
469%type	<v.table_opts>		table_opts table_opt table_opts_l
470%type	<v.pool_opts>		pool_opts pool_opt pool_opts_l
471%type	<v.tagged>		tagged
472%type	<v.rtableid>		rtable
473%%
474
475ruleset		: /* empty */
476		| ruleset '\n'
477		| ruleset option '\n'
478		| ruleset scrubrule '\n'
479		| ruleset natrule '\n'
480		| ruleset binatrule '\n'
481		| ruleset pfrule '\n'
482		| ruleset anchorrule '\n'
483		| ruleset loadrule '\n'
484		| ruleset altqif '\n'
485		| ruleset queuespec '\n'
486		| ruleset varset '\n'
487		| ruleset antispoof '\n'
488		| ruleset tabledef '\n'
489		| '{' fakeanchor '}' '\n';
490		| ruleset error '\n'		{ errors++; }
491		;
492
493/*
494 * apply to previouslys specified rule: must be careful to note
495 * what that is: pf or nat or binat or rdr
496 */
497fakeanchor	: fakeanchor '\n'
498		| fakeanchor anchorrule '\n'
499		| fakeanchor binatrule '\n'
500		| fakeanchor natrule '\n'
501		| fakeanchor pfrule '\n'
502		| fakeanchor error '\n'
503		;
504
505optimizer	: string	{
506			if (!strcmp($1, "none"))
507				$$ = 0;
508			else if (!strcmp($1, "basic"))
509				$$ = PF_OPTIMIZE_BASIC;
510			else if (!strcmp($1, "profile"))
511				$$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE;
512			else {
513				yyerror("unknown ruleset-optimization %s", $$);
514				YYERROR;
515			}
516		}
517		;
518
519option		: SET OPTIMIZATION STRING		{
520			if (check_rulestate(PFCTL_STATE_OPTION)) {
521				free($3);
522				YYERROR;
523			}
524			if (pfctl_set_optimization(pf, $3) != 0) {
525				yyerror("unknown optimization %s", $3);
526				free($3);
527				YYERROR;
528			}
529			free($3);
530		}
531		| SET RULESET_OPTIMIZATION optimizer {
532			if (!(pf->opts & PF_OPT_OPTIMIZE)) {
533				pf->opts |= PF_OPT_OPTIMIZE;
534				pf->optimize = $3;
535			}
536		}
537		| SET TIMEOUT timeout_spec
538		| SET TIMEOUT '{' timeout_list '}'
539		| SET LIMIT limit_spec
540		| SET LIMIT '{' limit_list '}'
541		| SET LOGINTERFACE STRING		{
542			if (check_rulestate(PFCTL_STATE_OPTION)) {
543				free($3);
544				YYERROR;
545			}
546			if (pfctl_set_logif(pf, $3) != 0) {
547				yyerror("error setting loginterface %s", $3);
548				free($3);
549				YYERROR;
550			}
551			free($3);
552		}
553		| SET HOSTID number {
554			if ($3 == 0) {
555				yyerror("hostid must be non-zero");
556				YYERROR;
557			}
558			if (pfctl_set_hostid(pf, $3) != 0) {
559				yyerror("error setting hostid %08x", $3);
560				YYERROR;
561			}
562		}
563		| SET BLOCKPOLICY DROP	{
564			if (pf->opts & PF_OPT_VERBOSE)
565				printf("set block-policy drop\n");
566			if (check_rulestate(PFCTL_STATE_OPTION))
567				YYERROR;
568			blockpolicy = PFRULE_DROP;
569		}
570		| SET BLOCKPOLICY RETURN {
571			if (pf->opts & PF_OPT_VERBOSE)
572				printf("set block-policy return\n");
573			if (check_rulestate(PFCTL_STATE_OPTION))
574				YYERROR;
575			blockpolicy = PFRULE_RETURN;
576		}
577		| SET REQUIREORDER yesno {
578			if (pf->opts & PF_OPT_VERBOSE)
579				printf("set require-order %s\n",
580				    $3 == 1 ? "yes" : "no");
581			require_order = $3;
582		}
583		| SET FINGERPRINTS STRING {
584			if (pf->opts & PF_OPT_VERBOSE)
585				printf("set fingerprints \"%s\"\n", $3);
586			if (check_rulestate(PFCTL_STATE_OPTION)) {
587				free($3);
588				YYERROR;
589			}
590			if (!pf->anchor->name[0]) {
591				if (pfctl_file_fingerprints(pf->dev,
592				    pf->opts, $3)) {
593					yyerror("error loading "
594					    "fingerprints %s", $3);
595					free($3);
596					YYERROR;
597				}
598			}
599			free($3);
600		}
601		| SET STATEPOLICY statelock {
602			if (pf->opts & PF_OPT_VERBOSE)
603				switch ($3) {
604				case 0:
605					printf("set state-policy floating\n");
606					break;
607				case PFRULE_IFBOUND:
608					printf("set state-policy if-bound\n");
609					break;
610				}
611			default_statelock = $3;
612		}
613		| SET DEBUG STRING {
614			if (check_rulestate(PFCTL_STATE_OPTION)) {
615				free($3);
616				YYERROR;
617			}
618			if (pfctl_set_debug(pf, $3) != 0) {
619				yyerror("error setting debuglevel %s", $3);
620				free($3);
621				YYERROR;
622			}
623			free($3);
624		}
625		| SET SKIP interface {
626			if (expand_skip_interface($3) != 0) {
627				yyerror("error setting skip interface(s)");
628				YYERROR;
629			}
630		}
631		;
632
633string		: string STRING				{
634			if (asprintf(&$$, "%s %s", $1, $2) == -1)
635				err(1, "string: asprintf");
636			free($1);
637			free($2);
638		}
639		| STRING
640		;
641
642varset		: STRING '=' string		{
643			if (pf->opts & PF_OPT_VERBOSE)
644				printf("%s = \"%s\"\n", $1, $3);
645			if (symset($1, $3, 0) == -1)
646				err(1, "cannot store variable %s", $1);
647			free($1);
648			free($3);
649		}
650		;
651
652anchorname	: STRING			{ $$ = $1; }
653		| /* empty */			{ $$ = NULL; }
654		;
655
656optnl		: optnl '\n'
657		|
658		;
659
660pfa_anchorlist	: pfrule optnl
661		| anchorrule optnl
662		| pfa_anchorlist pfrule optnl
663		| pfa_anchorlist anchorrule optnl
664		;
665
666pfa_anchor	: '{'
667		{
668			char ta[PF_ANCHOR_NAME_SIZE];
669			struct pf_ruleset *rs;
670
671			/* steping into a brace anchor */
672			pf->asd++;
673			pf->bn++;
674			pf->brace = 1;
675
676			/* create a holding ruleset in the root */
677			snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn);
678			rs = pf_find_or_create_ruleset(ta);
679			if (rs == NULL)
680				err(1, "pfa_anchor: pf_find_or_create_ruleset");
681			pf->astack[pf->asd] = rs->anchor;
682			pf->anchor = rs->anchor;
683		} '\n' pfa_anchorlist '}'
684		{
685			pf->alast = pf->anchor;
686			pf->asd--;
687			pf->anchor = pf->astack[pf->asd];
688		}
689		| /* empty */
690		;
691
692anchorrule	: ANCHOR anchorname dir quick interface af proto fromto
693		    filter_opts pfa_anchor
694		{
695			struct pf_rule	r;
696
697			if (check_rulestate(PFCTL_STATE_FILTER)) {
698				if ($2)
699					free($2);
700				YYERROR;
701			}
702
703			if ($2 && ($2[0] == '_' || strstr($2, "/_") != NULL)) {
704				free($2);
705				yyerror("anchor names beginning with '_' "
706				    "are reserved for internal use");
707				YYERROR;
708			}
709
710			memset(&r, 0, sizeof(r));
711			if (pf->astack[pf->asd + 1]) {
712				/* move inline rules into relative location */
713				pf_anchor_setup(&r,
714				    &pf->astack[pf->asd]->ruleset,
715				    $2 ? $2 : pf->alast->name);
716
717				if (r.anchor == NULL)
718					err(1, "anchorrule: unable to "
719					    "create ruleset");
720
721				if (pf->alast != r.anchor) {
722					if (r.anchor->match) {
723						yyerror("inline anchor '%s' "
724						    "already exists",
725						    r.anchor->name);
726						YYERROR;
727					}
728					mv_rules(&pf->alast->ruleset,
729					    &r.anchor->ruleset);
730				}
731				pf_remove_if_empty_ruleset(&pf->alast->ruleset);
732				pf->alast = r.anchor;
733			} else {
734				if (!$2) {
735					yyerror("anchors without explicit "
736					    "rules must specify a name");
737					YYERROR;
738				}
739			}
740			r.direction = $3;
741			r.quick = $4.quick;
742			r.af = $6;
743			r.prob = $9.prob;
744			r.rtableid = $9.rtableid;
745
746			if ($9.match_tag)
747				if (strlcpy(r.match_tagname, $9.match_tag,
748				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
749					yyerror("tag too long, max %u chars",
750					    PF_TAG_NAME_SIZE - 1);
751					YYERROR;
752				}
753			r.match_tag_not = $9.match_tag_not;
754
755			decide_address_family($8.src.host, &r.af);
756			decide_address_family($8.dst.host, &r.af);
757
758			expand_rule(&r, $5, NULL, $7, $8.src_os,
759			    $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
760			    0, 0, 0, pf->astack[pf->asd + 1] ?
761			    pf->alast->name : $2);
762			free($2);
763			pf->astack[pf->asd + 1] = NULL;
764		}
765		| NATANCHOR string interface af proto fromto rtable {
766			struct pf_rule	r;
767
768			if (check_rulestate(PFCTL_STATE_NAT)) {
769				free($2);
770				YYERROR;
771			}
772
773			memset(&r, 0, sizeof(r));
774			r.action = PF_NAT;
775			r.af = $4;
776			r.rtableid = $7;
777
778			decide_address_family($6.src.host, &r.af);
779			decide_address_family($6.dst.host, &r.af);
780
781			expand_rule(&r, $3, NULL, $5, $6.src_os,
782			    $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
783			    0, 0, 0, $2);
784			free($2);
785		}
786		| RDRANCHOR string interface af proto fromto rtable {
787			struct pf_rule	r;
788
789			if (check_rulestate(PFCTL_STATE_NAT)) {
790				free($2);
791				YYERROR;
792			}
793
794			memset(&r, 0, sizeof(r));
795			r.action = PF_RDR;
796			r.af = $4;
797			r.rtableid = $7;
798
799			decide_address_family($6.src.host, &r.af);
800			decide_address_family($6.dst.host, &r.af);
801
802			if ($6.src.port != NULL) {
803				yyerror("source port parameter not supported"
804				    " in rdr-anchor");
805				YYERROR;
806			}
807			if ($6.dst.port != NULL) {
808				if ($6.dst.port->next != NULL) {
809					yyerror("destination port list "
810					    "expansion not supported in "
811					    "rdr-anchor");
812					YYERROR;
813				} else if ($6.dst.port->op != PF_OP_EQ) {
814					yyerror("destination port operators"
815					    " not supported in rdr-anchor");
816					YYERROR;
817				}
818				r.dst.port[0] = $6.dst.port->port[0];
819				r.dst.port[1] = $6.dst.port->port[1];
820				r.dst.port_op = $6.dst.port->op;
821			}
822
823			expand_rule(&r, $3, NULL, $5, $6.src_os,
824			    $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
825			    0, 0, 0, $2);
826			free($2);
827		}
828		| BINATANCHOR string interface af proto fromto rtable {
829			struct pf_rule	r;
830
831			if (check_rulestate(PFCTL_STATE_NAT)) {
832				free($2);
833				YYERROR;
834			}
835
836			memset(&r, 0, sizeof(r));
837			r.action = PF_BINAT;
838			r.af = $4;
839			r.rtableid = $7;
840			if ($5 != NULL) {
841				if ($5->next != NULL) {
842					yyerror("proto list expansion"
843					    " not supported in binat-anchor");
844					YYERROR;
845				}
846				r.proto = $5->proto;
847				free($5);
848			}
849
850			if ($6.src.host != NULL || $6.src.port != NULL ||
851			    $6.dst.host != NULL || $6.dst.port != NULL) {
852				yyerror("fromto parameter not supported"
853				    " in binat-anchor");
854				YYERROR;
855			}
856
857			decide_address_family($6.src.host, &r.af);
858			decide_address_family($6.dst.host, &r.af);
859
860			pfctl_add_rule(pf, &r, $2);
861			free($2);
862		}
863		;
864
865loadrule	: LOAD ANCHOR string FROM string	{
866			struct loadanchors	*loadanchor;
867
868			if (strlen(pf->anchor->name) + 1 +
869			    strlen($3) >= MAXPATHLEN) {
870				yyerror("anchorname %s too long, max %u\n",
871				    $3, MAXPATHLEN - 1);
872				free($3);
873				YYERROR;
874			}
875			loadanchor = calloc(1, sizeof(struct loadanchors));
876			if (loadanchor == NULL)
877				err(1, "loadrule: calloc");
878			if ((loadanchor->anchorname = malloc(MAXPATHLEN)) ==
879			    NULL)
880				err(1, "loadrule: malloc");
881			if (pf->anchor->name[0])
882				snprintf(loadanchor->anchorname, MAXPATHLEN,
883				    "%s/%s", pf->anchor->name, $3);
884			else
885				strlcpy(loadanchor->anchorname, $3, MAXPATHLEN);
886			if ((loadanchor->filename = strdup($5)) == NULL)
887				err(1, "loadrule: strdup");
888
889			TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor,
890			    entries);
891
892			free($3);
893			free($5);
894		};
895
896scrubaction	: no SCRUB {
897			$$.b2 = $$.w = 0;
898			if ($1)
899				$$.b1 = PF_NOSCRUB;
900			else
901				$$.b1 = PF_SCRUB;
902		}
903		;
904
905scrubrule	: scrubaction dir logquick interface af proto fromto scrub_opts
906		{
907			struct pf_rule	r;
908
909			if (check_rulestate(PFCTL_STATE_SCRUB))
910				YYERROR;
911
912			memset(&r, 0, sizeof(r));
913
914			r.action = $1.b1;
915			r.direction = $2;
916
917			r.log = $3.log;
918			r.logif = $3.logif;
919			if ($3.quick) {
920				yyerror("scrub rules do not support 'quick'");
921				YYERROR;
922			}
923
924			r.af = $5;
925			if ($8.nodf)
926				r.rule_flag |= PFRULE_NODF;
927			if ($8.randomid)
928				r.rule_flag |= PFRULE_RANDOMID;
929			if ($8.reassemble_tcp) {
930				if (r.direction != PF_INOUT) {
931					yyerror("reassemble tcp rules can not "
932					    "specify direction");
933					YYERROR;
934				}
935				r.rule_flag |= PFRULE_REASSEMBLE_TCP;
936			}
937			if ($8.minttl)
938				r.min_ttl = $8.minttl;
939			if ($8.maxmss)
940				r.max_mss = $8.maxmss;
941			if ($8.fragcache)
942				r.rule_flag |= $8.fragcache;
943			r.rtableid = $8.rtableid;
944
945			expand_rule(&r, $4, NULL, $6, $7.src_os,
946			    $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
947			    NULL, NULL, NULL, "");
948		}
949		;
950
951scrub_opts	:	{
952				bzero(&scrub_opts, sizeof scrub_opts);
953				scrub_opts.rtableid = -1;
954			}
955		    scrub_opts_l
956			{ $$ = scrub_opts; }
957		| /* empty */ {
958			bzero(&scrub_opts, sizeof scrub_opts);
959			scrub_opts.rtableid = -1;
960			$$ = scrub_opts;
961		}
962		;
963
964scrub_opts_l	: scrub_opts_l scrub_opt
965		| scrub_opt
966		;
967
968scrub_opt	: NODF	{
969			if (scrub_opts.nodf) {
970				yyerror("no-df cannot be respecified");
971				YYERROR;
972			}
973			scrub_opts.nodf = 1;
974		}
975		| MINTTL number {
976			if (scrub_opts.marker & SOM_MINTTL) {
977				yyerror("min-ttl cannot be respecified");
978				YYERROR;
979			}
980			if ($2 > 255) {
981				yyerror("illegal min-ttl value %d", $2);
982				YYERROR;
983			}
984			scrub_opts.marker |= SOM_MINTTL;
985			scrub_opts.minttl = $2;
986		}
987		| MAXMSS number {
988			if (scrub_opts.marker & SOM_MAXMSS) {
989				yyerror("max-mss cannot be respecified");
990				YYERROR;
991			}
992			if ($2 > 65535) {
993				yyerror("illegal max-mss value %d", $2);
994				YYERROR;
995			}
996			scrub_opts.marker |= SOM_MAXMSS;
997			scrub_opts.maxmss = $2;
998		}
999		| fragcache {
1000			if (scrub_opts.marker & SOM_FRAGCACHE) {
1001				yyerror("fragcache cannot be respecified");
1002				YYERROR;
1003			}
1004			scrub_opts.marker |= SOM_FRAGCACHE;
1005			scrub_opts.fragcache = $1;
1006		}
1007		| REASSEMBLE STRING {
1008			if (strcasecmp($2, "tcp") != 0) {
1009				yyerror("scrub reassemble supports only tcp, "
1010				    "not '%s'", $2);
1011				free($2);
1012				YYERROR;
1013			}
1014			free($2);
1015			if (scrub_opts.reassemble_tcp) {
1016				yyerror("reassemble tcp cannot be respecified");
1017				YYERROR;
1018			}
1019			scrub_opts.reassemble_tcp = 1;
1020		}
1021		| RANDOMID {
1022			if (scrub_opts.randomid) {
1023				yyerror("random-id cannot be respecified");
1024				YYERROR;
1025			}
1026			scrub_opts.randomid = 1;
1027		}
1028		| RTABLE number				{
1029			if ($2 > RT_TABLEID_MAX || $2 < 0) {
1030				yyerror("invalid rtable id");
1031				YYERROR;
1032			}
1033			scrub_opts.rtableid = $2;
1034		}
1035		;
1036
1037fragcache	: FRAGMENT REASSEMBLE	{ $$ = 0; /* default */ }
1038		| FRAGMENT FRAGCROP	{ $$ = PFRULE_FRAGCROP; }
1039		| FRAGMENT FRAGDROP	{ $$ = PFRULE_FRAGDROP; }
1040		;
1041
1042antispoof	: ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
1043			struct pf_rule		 r;
1044			struct node_host	*h = NULL, *hh;
1045			struct node_if		*i, *j;
1046
1047			if (check_rulestate(PFCTL_STATE_FILTER))
1048				YYERROR;
1049
1050			for (i = $3; i; i = i->next) {
1051				bzero(&r, sizeof(r));
1052
1053				r.action = PF_DROP;
1054				r.direction = PF_IN;
1055				r.log = $2.log;
1056				r.logif = $2.logif;
1057				r.quick = $2.quick;
1058				r.af = $4;
1059				if (rule_label(&r, $5.label))
1060					YYERROR;
1061				r.rtableid = $5.rtableid;
1062				j = calloc(1, sizeof(struct node_if));
1063				if (j == NULL)
1064					err(1, "antispoof: calloc");
1065				if (strlcpy(j->ifname, i->ifname,
1066				    sizeof(j->ifname)) >= sizeof(j->ifname)) {
1067					free(j);
1068					yyerror("interface name too long");
1069					YYERROR;
1070				}
1071				j->not = 1;
1072				if (i->dynamic) {
1073					h = calloc(1, sizeof(*h));
1074					if (h == NULL)
1075						err(1, "address: calloc");
1076					h->addr.type = PF_ADDR_DYNIFTL;
1077					set_ipmask(h, 128);
1078					if (strlcpy(h->addr.v.ifname, i->ifname,
1079					    sizeof(h->addr.v.ifname)) >=
1080					    sizeof(h->addr.v.ifname)) {
1081						free(h);
1082						yyerror(
1083						    "interface name too long");
1084						YYERROR;
1085					}
1086					hh = malloc(sizeof(*hh));
1087					if (hh == NULL)
1088						 err(1, "address: malloc");
1089					bcopy(h, hh, sizeof(*hh));
1090					h->addr.iflags = PFI_AFLAG_NETWORK;
1091				} else {
1092					h = ifa_lookup(j->ifname,
1093					    PFI_AFLAG_NETWORK);
1094					hh = NULL;
1095				}
1096
1097				if (h != NULL)
1098					expand_rule(&r, j, NULL, NULL, NULL, h,
1099					    NULL, NULL, NULL, NULL, NULL,
1100					    NULL, "");
1101
1102				if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
1103					bzero(&r, sizeof(r));
1104
1105					r.action = PF_DROP;
1106					r.direction = PF_IN;
1107					r.log = $2.log;
1108					r.quick = $2.quick;
1109					r.af = $4;
1110					if (rule_label(&r, $5.label))
1111						YYERROR;
1112					r.rtableid = $5.rtableid;
1113					if (hh != NULL)
1114						h = hh;
1115					else
1116						h = ifa_lookup(i->ifname, 0);
1117					if (h != NULL)
1118						expand_rule(&r, NULL, NULL,
1119						    NULL, NULL, h, NULL, NULL,
1120						    NULL, NULL, NULL, NULL, "");
1121				} else
1122					free(hh);
1123			}
1124			free($5.label);
1125		}
1126		;
1127
1128antispoof_ifspc	: FOR antispoof_if		{ $$ = $2; }
1129		| FOR '{' antispoof_iflst '}'	{ $$ = $3; }
1130		;
1131
1132antispoof_iflst	: antispoof_if				{ $$ = $1; }
1133		| antispoof_iflst comma antispoof_if	{
1134			$1->tail->next = $3;
1135			$1->tail = $3;
1136			$$ = $1;
1137		}
1138		;
1139
1140antispoof_if  : if_item				{ $$ = $1; }
1141		| '(' if_item ')'		{
1142			$2->dynamic = 1;
1143			$$ = $2;
1144		}
1145		;
1146
1147antispoof_opts	:	{
1148				bzero(&antispoof_opts, sizeof antispoof_opts);
1149				antispoof_opts.rtableid = -1;
1150			}
1151		    antispoof_opts_l
1152			{ $$ = antispoof_opts; }
1153		| /* empty */	{
1154			bzero(&antispoof_opts, sizeof antispoof_opts);
1155			antispoof_opts.rtableid = -1;
1156			$$ = antispoof_opts;
1157		}
1158		;
1159
1160antispoof_opts_l	: antispoof_opts_l antispoof_opt
1161			| antispoof_opt
1162			;
1163
1164antispoof_opt	: label	{
1165			if (antispoof_opts.label) {
1166				yyerror("label cannot be redefined");
1167				YYERROR;
1168			}
1169			antispoof_opts.label = $1;
1170		}
1171		| RTABLE number				{
1172			if ($2 > RT_TABLEID_MAX || $2 < 0) {
1173				yyerror("invalid rtable id");
1174				YYERROR;
1175			}
1176			antispoof_opts.rtableid = $2;
1177		}
1178		;
1179
1180not		: '!'		{ $$ = 1; }
1181		| /* empty */	{ $$ = 0; }
1182		;
1183
1184tabledef	: TABLE '<' STRING '>' table_opts {
1185			struct node_host	 *h, *nh;
1186			struct node_tinit	 *ti, *nti;
1187
1188			if (strlen($3) >= PF_TABLE_NAME_SIZE) {
1189				yyerror("table name too long, max %d chars",
1190				    PF_TABLE_NAME_SIZE - 1);
1191				free($3);
1192				YYERROR;
1193			}
1194			if (pf->loadopt & PFCTL_FLAG_TABLE)
1195				if (process_tabledef($3, &$5)) {
1196					free($3);
1197					YYERROR;
1198				}
1199			free($3);
1200			for (ti = SIMPLEQ_FIRST(&$5.init_nodes);
1201			    ti != NULL; ti = nti) {
1202				if (ti->file)
1203					free(ti->file);
1204				for (h = ti->host; h != NULL; h = nh) {
1205					nh = h->next;
1206					free(h);
1207				}
1208				nti = SIMPLEQ_NEXT(ti, entries);
1209				free(ti);
1210			}
1211		}
1212		;
1213
1214table_opts	:	{
1215			bzero(&table_opts, sizeof table_opts);
1216			SIMPLEQ_INIT(&table_opts.init_nodes);
1217		}
1218		    table_opts_l
1219			{ $$ = table_opts; }
1220		| /* empty */
1221			{
1222			bzero(&table_opts, sizeof table_opts);
1223			SIMPLEQ_INIT(&table_opts.init_nodes);
1224			$$ = table_opts;
1225		}
1226		;
1227
1228table_opts_l	: table_opts_l table_opt
1229		| table_opt
1230		;
1231
1232table_opt	: STRING		{
1233			if (!strcmp($1, "const"))
1234				table_opts.flags |= PFR_TFLAG_CONST;
1235			else if (!strcmp($1, "persist"))
1236				table_opts.flags |= PFR_TFLAG_PERSIST;
1237			else {
1238				yyerror("invalid table option '%s'", $1);
1239				free($1);
1240				YYERROR;
1241			}
1242			free($1);
1243		}
1244		| '{' '}'		{ table_opts.init_addr = 1; }
1245		| '{' host_list '}'	{
1246			struct node_host	*n;
1247			struct node_tinit	*ti;
1248
1249			for (n = $2; n != NULL; n = n->next) {
1250				switch (n->addr.type) {
1251				case PF_ADDR_ADDRMASK:
1252					continue; /* ok */
1253				case PF_ADDR_DYNIFTL:
1254					yyerror("dynamic addresses are not "
1255					    "permitted inside tables");
1256					break;
1257				case PF_ADDR_TABLE:
1258					yyerror("tables cannot contain tables");
1259					break;
1260				case PF_ADDR_NOROUTE:
1261					yyerror("\"no-route\" is not permitted "
1262					    "inside tables");
1263					break;
1264				case PF_ADDR_URPFFAILED:
1265					yyerror("\"urpf-failed\" is not "
1266					    "permitted inside tables");
1267					break;
1268				default:
1269					yyerror("unknown address type %d",
1270					    n->addr.type);
1271				}
1272				YYERROR;
1273			}
1274			if (!(ti = calloc(1, sizeof(*ti))))
1275				err(1, "table_opt: calloc");
1276			ti->host = $2;
1277			SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
1278			    entries);
1279			table_opts.init_addr = 1;
1280		}
1281		| FILENAME STRING	{
1282			struct node_tinit	*ti;
1283
1284			if (!(ti = calloc(1, sizeof(*ti))))
1285				err(1, "table_opt: calloc");
1286			ti->file = $2;
1287			SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
1288			    entries);
1289			table_opts.init_addr = 1;
1290		}
1291		;
1292
1293altqif		: ALTQ interface queue_opts QUEUE qassign {
1294			struct pf_altq	a;
1295
1296			if (check_rulestate(PFCTL_STATE_QUEUE))
1297				YYERROR;
1298
1299			memset(&a, 0, sizeof(a));
1300			if ($3.scheduler.qtype == ALTQT_NONE) {
1301				yyerror("no scheduler specified!");
1302				YYERROR;
1303			}
1304			a.scheduler = $3.scheduler.qtype;
1305			a.qlimit = $3.qlimit;
1306			a.tbrsize = $3.tbrsize;
1307			if ($5 == NULL) {
1308				yyerror("no child queues specified");
1309				YYERROR;
1310			}
1311			if (expand_altq(&a, $2, $5, $3.queue_bwspec,
1312			    &$3.scheduler))
1313				YYERROR;
1314		}
1315		;
1316
1317queuespec	: QUEUE STRING interface queue_opts qassign {
1318			struct pf_altq	a;
1319
1320			if (check_rulestate(PFCTL_STATE_QUEUE)) {
1321				free($2);
1322				YYERROR;
1323			}
1324
1325			memset(&a, 0, sizeof(a));
1326
1327			if (strlcpy(a.qname, $2, sizeof(a.qname)) >=
1328			    sizeof(a.qname)) {
1329				yyerror("queue name too long (max "
1330				    "%d chars)", PF_QNAME_SIZE-1);
1331				free($2);
1332				YYERROR;
1333			}
1334			free($2);
1335			if ($4.tbrsize) {
1336				yyerror("cannot specify tbrsize for queue");
1337				YYERROR;
1338			}
1339			if ($4.priority > 255) {
1340				yyerror("priority out of range: max 255");
1341				YYERROR;
1342			}
1343			a.priority = $4.priority;
1344			a.qlimit = $4.qlimit;
1345			a.scheduler = $4.scheduler.qtype;
1346			if (expand_queue(&a, $3, $5, $4.queue_bwspec,
1347			    &$4.scheduler)) {
1348				yyerror("errors in queue definition");
1349				YYERROR;
1350			}
1351		}
1352		;
1353
1354queue_opts	:	{
1355			bzero(&queue_opts, sizeof queue_opts);
1356			queue_opts.priority = DEFAULT_PRIORITY;
1357			queue_opts.qlimit = DEFAULT_QLIMIT;
1358			queue_opts.scheduler.qtype = ALTQT_NONE;
1359			queue_opts.queue_bwspec.bw_percent = 100;
1360		}
1361		    queue_opts_l
1362			{ $$ = queue_opts; }
1363		| /* empty */ {
1364			bzero(&queue_opts, sizeof queue_opts);
1365			queue_opts.priority = DEFAULT_PRIORITY;
1366			queue_opts.qlimit = DEFAULT_QLIMIT;
1367			queue_opts.scheduler.qtype = ALTQT_NONE;
1368			queue_opts.queue_bwspec.bw_percent = 100;
1369			$$ = queue_opts;
1370		}
1371		;
1372
1373queue_opts_l	: queue_opts_l queue_opt
1374		| queue_opt
1375		;
1376
1377queue_opt	: BANDWIDTH bandwidth	{
1378			if (queue_opts.marker & QOM_BWSPEC) {
1379				yyerror("bandwidth cannot be respecified");
1380				YYERROR;
1381			}
1382			queue_opts.marker |= QOM_BWSPEC;
1383			queue_opts.queue_bwspec = $2;
1384		}
1385		| PRIORITY number	{
1386			if (queue_opts.marker & QOM_PRIORITY) {
1387				yyerror("priority cannot be respecified");
1388				YYERROR;
1389			}
1390			if ($2 > 255) {
1391				yyerror("priority out of range: max 255");
1392				YYERROR;
1393			}
1394			queue_opts.marker |= QOM_PRIORITY;
1395			queue_opts.priority = $2;
1396		}
1397		| QLIMIT number	{
1398			if (queue_opts.marker & QOM_QLIMIT) {
1399				yyerror("qlimit cannot be respecified");
1400				YYERROR;
1401			}
1402			if ($2 > 65535) {
1403				yyerror("qlimit out of range: max 65535");
1404				YYERROR;
1405			}
1406			queue_opts.marker |= QOM_QLIMIT;
1407			queue_opts.qlimit = $2;
1408		}
1409		| scheduler	{
1410			if (queue_opts.marker & QOM_SCHEDULER) {
1411				yyerror("scheduler cannot be respecified");
1412				YYERROR;
1413			}
1414			queue_opts.marker |= QOM_SCHEDULER;
1415			queue_opts.scheduler = $1;
1416		}
1417		| TBRSIZE number	{
1418			if (queue_opts.marker & QOM_TBRSIZE) {
1419				yyerror("tbrsize cannot be respecified");
1420				YYERROR;
1421			}
1422			if ($2 > 65535) {
1423				yyerror("tbrsize too big: max 65535");
1424				YYERROR;
1425			}
1426			queue_opts.marker |= QOM_TBRSIZE;
1427			queue_opts.tbrsize = $2;
1428		}
1429		;
1430
1431bandwidth	: STRING {
1432			double	 bps;
1433			char	*cp;
1434
1435			$$.bw_percent = 0;
1436
1437			bps = strtod($1, &cp);
1438			if (cp != NULL) {
1439				if (!strcmp(cp, "b"))
1440					; /* nothing */
1441				else if (!strcmp(cp, "Kb"))
1442					bps *= 1000;
1443				else if (!strcmp(cp, "Mb"))
1444					bps *= 1000 * 1000;
1445				else if (!strcmp(cp, "Gb"))
1446					bps *= 1000 * 1000 * 1000;
1447				else if (!strcmp(cp, "%")) {
1448					if (bps < 0 || bps > 100) {
1449						yyerror("bandwidth spec "
1450						    "out of range");
1451						free($1);
1452						YYERROR;
1453					}
1454					$$.bw_percent = bps;
1455					bps = 0;
1456				} else {
1457					yyerror("unknown unit %s", cp);
1458					free($1);
1459					YYERROR;
1460				}
1461			}
1462			free($1);
1463			$$.bw_absolute = (u_int32_t)bps;
1464		}
1465		;
1466
1467scheduler	: CBQ				{
1468			$$.qtype = ALTQT_CBQ;
1469			$$.data.cbq_opts.flags = 0;
1470		}
1471		| CBQ '(' cbqflags_list ')'	{
1472			$$.qtype = ALTQT_CBQ;
1473			$$.data.cbq_opts.flags = $3;
1474		}
1475		| PRIQ				{
1476			$$.qtype = ALTQT_PRIQ;
1477			$$.data.priq_opts.flags = 0;
1478		}
1479		| PRIQ '(' priqflags_list ')'	{
1480			$$.qtype = ALTQT_PRIQ;
1481			$$.data.priq_opts.flags = $3;
1482		}
1483		| HFSC				{
1484			$$.qtype = ALTQT_HFSC;
1485			bzero(&$$.data.hfsc_opts,
1486			    sizeof(struct node_hfsc_opts));
1487		}
1488		| HFSC '(' hfsc_opts ')'	{
1489			$$.qtype = ALTQT_HFSC;
1490			$$.data.hfsc_opts = $3;
1491		}
1492		;
1493
1494cbqflags_list	: cbqflags_item				{ $$ |= $1; }
1495		| cbqflags_list comma cbqflags_item	{ $$ |= $3; }
1496		;
1497
1498cbqflags_item	: STRING	{
1499			if (!strcmp($1, "default"))
1500				$$ = CBQCLF_DEFCLASS;
1501#ifdef CBQCLF_BORROW
1502			else if (!strcmp($1, "borrow"))
1503				$$ = CBQCLF_BORROW;
1504#endif
1505			else if (!strcmp($1, "red"))
1506				$$ = CBQCLF_RED;
1507			else if (!strcmp($1, "ecn"))
1508				$$ = CBQCLF_RED|CBQCLF_ECN;
1509			else if (!strcmp($1, "rio"))
1510				$$ = CBQCLF_RIO;
1511			else {
1512				yyerror("unknown cbq flag \"%s\"", $1);
1513				free($1);
1514				YYERROR;
1515			}
1516			free($1);
1517		}
1518		;
1519
1520priqflags_list	: priqflags_item			{ $$ |= $1; }
1521		| priqflags_list comma priqflags_item	{ $$ |= $3; }
1522		;
1523
1524priqflags_item	: STRING	{
1525			if (!strcmp($1, "default"))
1526				$$ = PRCF_DEFAULTCLASS;
1527			else if (!strcmp($1, "red"))
1528				$$ = PRCF_RED;
1529			else if (!strcmp($1, "ecn"))
1530				$$ = PRCF_RED|PRCF_ECN;
1531			else if (!strcmp($1, "rio"))
1532				$$ = PRCF_RIO;
1533			else {
1534				yyerror("unknown priq flag \"%s\"", $1);
1535				free($1);
1536				YYERROR;
1537			}
1538			free($1);
1539		}
1540		;
1541
1542hfsc_opts	:	{
1543				bzero(&hfsc_opts,
1544				    sizeof(struct node_hfsc_opts));
1545			}
1546		    hfscopts_list				{
1547			$$ = hfsc_opts;
1548		}
1549		;
1550
1551hfscopts_list	: hfscopts_item
1552		| hfscopts_list comma hfscopts_item
1553		;
1554
1555hfscopts_item	: LINKSHARE bandwidth				{
1556			if (hfsc_opts.linkshare.used) {
1557				yyerror("linkshare already specified");
1558				YYERROR;
1559			}
1560			hfsc_opts.linkshare.m2 = $2;
1561			hfsc_opts.linkshare.used = 1;
1562		}
1563		| LINKSHARE '(' bandwidth comma number comma bandwidth ')'
1564		    {
1565			if (hfsc_opts.linkshare.used) {
1566				yyerror("linkshare already specified");
1567				YYERROR;
1568			}
1569			hfsc_opts.linkshare.m1 = $3;
1570			hfsc_opts.linkshare.d = $5;
1571			hfsc_opts.linkshare.m2 = $7;
1572			hfsc_opts.linkshare.used = 1;
1573		}
1574		| REALTIME bandwidth				{
1575			if (hfsc_opts.realtime.used) {
1576				yyerror("realtime already specified");
1577				YYERROR;
1578			}
1579			hfsc_opts.realtime.m2 = $2;
1580			hfsc_opts.realtime.used = 1;
1581		}
1582		| REALTIME '(' bandwidth comma number comma bandwidth ')'
1583		    {
1584			if (hfsc_opts.realtime.used) {
1585				yyerror("realtime already specified");
1586				YYERROR;
1587			}
1588			hfsc_opts.realtime.m1 = $3;
1589			hfsc_opts.realtime.d = $5;
1590			hfsc_opts.realtime.m2 = $7;
1591			hfsc_opts.realtime.used = 1;
1592		}
1593		| UPPERLIMIT bandwidth				{
1594			if (hfsc_opts.upperlimit.used) {
1595				yyerror("upperlimit already specified");
1596				YYERROR;
1597			}
1598			hfsc_opts.upperlimit.m2 = $2;
1599			hfsc_opts.upperlimit.used = 1;
1600		}
1601		| UPPERLIMIT '(' bandwidth comma number comma bandwidth ')'
1602		    {
1603			if (hfsc_opts.upperlimit.used) {
1604				yyerror("upperlimit already specified");
1605				YYERROR;
1606			}
1607			hfsc_opts.upperlimit.m1 = $3;
1608			hfsc_opts.upperlimit.d = $5;
1609			hfsc_opts.upperlimit.m2 = $7;
1610			hfsc_opts.upperlimit.used = 1;
1611		}
1612		| STRING	{
1613			if (!strcmp($1, "default"))
1614				hfsc_opts.flags |= HFCF_DEFAULTCLASS;
1615			else if (!strcmp($1, "red"))
1616				hfsc_opts.flags |= HFCF_RED;
1617			else if (!strcmp($1, "ecn"))
1618				hfsc_opts.flags |= HFCF_RED|HFCF_ECN;
1619			else if (!strcmp($1, "rio"))
1620				hfsc_opts.flags |= HFCF_RIO;
1621			else {
1622				yyerror("unknown hfsc flag \"%s\"", $1);
1623				free($1);
1624				YYERROR;
1625			}
1626			free($1);
1627		}
1628		;
1629
1630qassign		: /* empty */		{ $$ = NULL; }
1631		| qassign_item		{ $$ = $1; }
1632		| '{' qassign_list '}'	{ $$ = $2; }
1633		;
1634
1635qassign_list	: qassign_item			{ $$ = $1; }
1636		| qassign_list comma qassign_item	{
1637			$1->tail->next = $3;
1638			$1->tail = $3;
1639			$$ = $1;
1640		}
1641		;
1642
1643qassign_item	: STRING			{
1644			$$ = calloc(1, sizeof(struct node_queue));
1645			if ($$ == NULL)
1646				err(1, "qassign_item: calloc");
1647			if (strlcpy($$->queue, $1, sizeof($$->queue)) >=
1648			    sizeof($$->queue)) {
1649				yyerror("queue name '%s' too long (max "
1650				    "%d chars)", $1, sizeof($$->queue)-1);
1651				free($1);
1652				free($$);
1653				YYERROR;
1654			}
1655			free($1);
1656			$$->next = NULL;
1657			$$->tail = $$;
1658		}
1659		;
1660
1661pfrule		: action dir logquick interface route af proto fromto
1662		    filter_opts
1663		{
1664			struct pf_rule		 r;
1665			struct node_state_opt	*o;
1666			struct node_proto	*proto;
1667			int			 srctrack = 0;
1668			int			 statelock = 0;
1669			int			 adaptive = 0;
1670
1671			if (check_rulestate(PFCTL_STATE_FILTER))
1672				YYERROR;
1673
1674			memset(&r, 0, sizeof(r));
1675
1676			r.action = $1.b1;
1677			switch ($1.b2) {
1678			case PFRULE_RETURNRST:
1679				r.rule_flag |= PFRULE_RETURNRST;
1680				r.return_ttl = $1.w;
1681				break;
1682			case PFRULE_RETURNICMP:
1683				r.rule_flag |= PFRULE_RETURNICMP;
1684				r.return_icmp = $1.w;
1685				r.return_icmp6 = $1.w2;
1686				break;
1687			case PFRULE_RETURN:
1688				r.rule_flag |= PFRULE_RETURN;
1689				r.return_icmp = $1.w;
1690				r.return_icmp6 = $1.w2;
1691				break;
1692			}
1693			r.direction = $2;
1694			r.log = $3.log;
1695			r.logif = $3.logif;
1696			r.quick = $3.quick;
1697			r.prob = $9.prob;
1698			r.rtableid = $9.rtableid;
1699
1700			r.af = $6;
1701			if ($9.tag)
1702				if (strlcpy(r.tagname, $9.tag,
1703				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
1704					yyerror("tag too long, max %u chars",
1705					    PF_TAG_NAME_SIZE - 1);
1706					YYERROR;
1707				}
1708			if ($9.match_tag)
1709				if (strlcpy(r.match_tagname, $9.match_tag,
1710				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
1711					yyerror("tag too long, max %u chars",
1712					    PF_TAG_NAME_SIZE - 1);
1713					YYERROR;
1714				}
1715			r.match_tag_not = $9.match_tag_not;
1716			if (rule_label(&r, $9.label))
1717				YYERROR;
1718			free($9.label);
1719			r.flags = $9.flags.b1;
1720			r.flagset = $9.flags.b2;
1721			if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
1722				yyerror("flags always false");
1723				YYERROR;
1724			}
1725			if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
1726				for (proto = $7; proto != NULL &&
1727				    proto->proto != IPPROTO_TCP;
1728				    proto = proto->next)
1729					;	/* nothing */
1730				if (proto == NULL && $7 != NULL) {
1731					if ($9.flags.b1 || $9.flags.b2)
1732						yyerror(
1733						    "flags only apply to tcp");
1734					if ($8.src_os)
1735						yyerror(
1736						    "OS fingerprinting only "
1737						    "apply to tcp");
1738					YYERROR;
1739				}
1740#if 0
1741				if (($9.flags.b1 & parse_flags("S")) == 0 &&
1742				    $8.src_os) {
1743					yyerror("OS fingerprinting requires "
1744					    "the SYN TCP flag (flags S/SA)");
1745					YYERROR;
1746				}
1747#endif
1748			}
1749
1750			r.tos = $9.tos;
1751			r.keep_state = $9.keep.action;
1752
1753			/* 'keep state' by default on pass rules. */
1754			if (!r.keep_state && !r.action &&
1755			    !($9.marker & FOM_KEEP))
1756				r.keep_state = PF_STATE_NORMAL;
1757
1758			o = $9.keep.options;
1759			while (o) {
1760				struct node_state_opt	*p = o;
1761
1762				switch (o->type) {
1763				case PF_STATE_OPT_MAX:
1764					if (r.max_states) {
1765						yyerror("state option 'max' "
1766						    "multiple definitions");
1767						YYERROR;
1768					}
1769					r.max_states = o->data.max_states;
1770					break;
1771				case PF_STATE_OPT_NOSYNC:
1772					if (r.rule_flag & PFRULE_NOSYNC) {
1773						yyerror("state option 'sync' "
1774						    "multiple definitions");
1775						YYERROR;
1776					}
1777					r.rule_flag |= PFRULE_NOSYNC;
1778					break;
1779				case PF_STATE_OPT_SRCTRACK:
1780					if (srctrack) {
1781						yyerror("state option "
1782						    "'source-track' "
1783						    "multiple definitions");
1784						YYERROR;
1785					}
1786					srctrack =  o->data.src_track;
1787					r.rule_flag |= PFRULE_SRCTRACK;
1788					break;
1789				case PF_STATE_OPT_MAX_SRC_STATES:
1790					if (r.max_src_states) {
1791						yyerror("state option "
1792						    "'max-src-states' "
1793						    "multiple definitions");
1794						YYERROR;
1795					}
1796					if (o->data.max_src_states == 0) {
1797						yyerror("'max-src-states' must "
1798						    "be > 0");
1799						YYERROR;
1800					}
1801					r.max_src_states =
1802					    o->data.max_src_states;
1803					r.rule_flag |= PFRULE_SRCTRACK;
1804					break;
1805				case PF_STATE_OPT_OVERLOAD:
1806					if (r.overload_tblname[0]) {
1807						yyerror("multiple 'overload' "
1808						    "table definitions");
1809						YYERROR;
1810					}
1811					if (strlcpy(r.overload_tblname,
1812					    o->data.overload.tblname,
1813					    PF_TABLE_NAME_SIZE) >=
1814					    PF_TABLE_NAME_SIZE) {
1815						yyerror("state option: "
1816						    "strlcpy");
1817						YYERROR;
1818					}
1819					r.flush = o->data.overload.flush;
1820					break;
1821				case PF_STATE_OPT_MAX_SRC_CONN:
1822					if (r.max_src_conn) {
1823						yyerror("state option "
1824						    "'max-src-conn' "
1825						    "multiple definitions");
1826						YYERROR;
1827					}
1828					if (o->data.max_src_conn == 0) {
1829						yyerror("'max-src-conn' "
1830						    "must be > 0");
1831						YYERROR;
1832					}
1833					r.max_src_conn =
1834					    o->data.max_src_conn;
1835					r.rule_flag |= PFRULE_SRCTRACK |
1836					    PFRULE_RULESRCTRACK;
1837					break;
1838				case PF_STATE_OPT_MAX_SRC_CONN_RATE:
1839					if (r.max_src_conn_rate.limit) {
1840						yyerror("state option "
1841						    "'max-src-conn-rate' "
1842						    "multiple definitions");
1843						YYERROR;
1844					}
1845					if (!o->data.max_src_conn_rate.limit ||
1846					    !o->data.max_src_conn_rate.seconds) {
1847						yyerror("'max-src-conn-rate' "
1848						    "values must be > 0");
1849						YYERROR;
1850					}
1851					if (o->data.max_src_conn_rate.limit >
1852					    PF_THRESHOLD_MAX) {
1853						yyerror("'max-src-conn-rate' "
1854						    "maximum rate must be < %u",
1855						    PF_THRESHOLD_MAX);
1856						YYERROR;
1857					}
1858					r.max_src_conn_rate.limit =
1859					    o->data.max_src_conn_rate.limit;
1860					r.max_src_conn_rate.seconds =
1861					    o->data.max_src_conn_rate.seconds;
1862					r.rule_flag |= PFRULE_SRCTRACK |
1863					    PFRULE_RULESRCTRACK;
1864					break;
1865				case PF_STATE_OPT_MAX_SRC_NODES:
1866					if (r.max_src_nodes) {
1867						yyerror("state option "
1868						    "'max-src-nodes' "
1869						    "multiple definitions");
1870						YYERROR;
1871					}
1872					if (o->data.max_src_nodes == 0) {
1873						yyerror("'max-src-nodes' must "
1874						    "be > 0");
1875						YYERROR;
1876					}
1877					r.max_src_nodes =
1878					    o->data.max_src_nodes;
1879					r.rule_flag |= PFRULE_SRCTRACK |
1880					    PFRULE_RULESRCTRACK;
1881					break;
1882				case PF_STATE_OPT_STATELOCK:
1883					if (statelock) {
1884						yyerror("state locking option: "
1885						    "multiple definitions");
1886						YYERROR;
1887					}
1888					statelock = 1;
1889					r.rule_flag |= o->data.statelock;
1890					break;
1891				case PF_STATE_OPT_TIMEOUT:
1892					if (o->data.timeout.number ==
1893					    PFTM_ADAPTIVE_START ||
1894					    o->data.timeout.number ==
1895					    PFTM_ADAPTIVE_END)
1896						adaptive = 1;
1897					if (r.timeout[o->data.timeout.number]) {
1898						yyerror("state timeout %s "
1899						    "multiple definitions",
1900						    pf_timeouts[o->data.
1901						    timeout.number].name);
1902						YYERROR;
1903					}
1904					r.timeout[o->data.timeout.number] =
1905					    o->data.timeout.seconds;
1906				}
1907				o = o->next;
1908				free(p);
1909			}
1910
1911			/* 'flags S/SA' by default on stateful rules */
1912			if (!r.action && !r.flags && !r.flagset &&
1913			    !$9.fragment && !($9.marker & FOM_FLAGS) &&
1914			    r.keep_state) {
1915				r.flags = parse_flags("S");
1916				r.flagset =  parse_flags("SA");
1917			}
1918			if (!adaptive && r.max_states) {
1919				r.timeout[PFTM_ADAPTIVE_START] =
1920				    (r.max_states / 10) * 6;
1921				r.timeout[PFTM_ADAPTIVE_END] =
1922				    (r.max_states / 10) * 12;
1923			}
1924			if (r.rule_flag & PFRULE_SRCTRACK) {
1925				if (srctrack == PF_SRCTRACK_GLOBAL &&
1926				    r.max_src_nodes) {
1927					yyerror("'max-src-nodes' is "
1928					    "incompatible with "
1929					    "'source-track global'");
1930					YYERROR;
1931				}
1932				if (srctrack == PF_SRCTRACK_GLOBAL &&
1933				    r.max_src_conn) {
1934					yyerror("'max-src-conn' is "
1935					    "incompatible with "
1936					    "'source-track global'");
1937					YYERROR;
1938				}
1939				if (srctrack == PF_SRCTRACK_GLOBAL &&
1940				    r.max_src_conn_rate.seconds) {
1941					yyerror("'max-src-conn-rate' is "
1942					    "incompatible with "
1943					    "'source-track global'");
1944					YYERROR;
1945				}
1946				if (r.timeout[PFTM_SRC_NODE] <
1947				    r.max_src_conn_rate.seconds)
1948					r.timeout[PFTM_SRC_NODE] =
1949					    r.max_src_conn_rate.seconds;
1950				r.rule_flag |= PFRULE_SRCTRACK;
1951				if (srctrack == PF_SRCTRACK_RULE)
1952					r.rule_flag |= PFRULE_RULESRCTRACK;
1953			}
1954			if (r.keep_state && !statelock)
1955				r.rule_flag |= default_statelock;
1956
1957			if ($9.fragment)
1958				r.rule_flag |= PFRULE_FRAGMENT;
1959			r.allow_opts = $9.allowopts;
1960
1961			decide_address_family($8.src.host, &r.af);
1962			decide_address_family($8.dst.host, &r.af);
1963
1964			if ($5.rt) {
1965				if (!r.direction) {
1966					yyerror("direction must be explicit "
1967					    "with rules that specify routing");
1968					YYERROR;
1969				}
1970				r.rt = $5.rt;
1971				r.rpool.opts = $5.pool_opts;
1972				if ($5.key != NULL)
1973					memcpy(&r.rpool.key, $5.key,
1974					    sizeof(struct pf_poolhashkey));
1975			}
1976			if (r.rt && r.rt != PF_FASTROUTE) {
1977				decide_address_family($5.host, &r.af);
1978				remove_invalid_hosts(&$5.host, &r.af);
1979				if ($5.host == NULL) {
1980					yyerror("no routing address with "
1981					    "matching address family found.");
1982					YYERROR;
1983				}
1984				if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
1985				    PF_POOL_NONE && ($5.host->next != NULL ||
1986				    $5.host->addr.type == PF_ADDR_TABLE ||
1987				    DYNIF_MULTIADDR($5.host->addr)))
1988					r.rpool.opts |= PF_POOL_ROUNDROBIN;
1989				if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
1990				    PF_POOL_ROUNDROBIN &&
1991				    disallow_table($5.host, "tables are only "
1992				    "supported in round-robin routing pools"))
1993					YYERROR;
1994				if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
1995				    PF_POOL_ROUNDROBIN &&
1996				    disallow_alias($5.host, "interface (%s) "
1997				    "is only supported in round-robin "
1998				    "routing pools"))
1999					YYERROR;
2000				if ($5.host->next != NULL) {
2001					if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
2002					    PF_POOL_ROUNDROBIN) {
2003						yyerror("r.rpool.opts must "
2004						    "be PF_POOL_ROUNDROBIN");
2005						YYERROR;
2006					}
2007				}
2008			}
2009			if ($9.queues.qname != NULL) {
2010				if (strlcpy(r.qname, $9.queues.qname,
2011				    sizeof(r.qname)) >= sizeof(r.qname)) {
2012					yyerror("rule qname too long (max "
2013					    "%d chars)", sizeof(r.qname)-1);
2014					YYERROR;
2015				}
2016				free($9.queues.qname);
2017			}
2018			if ($9.queues.pqname != NULL) {
2019				if (strlcpy(r.pqname, $9.queues.pqname,
2020				    sizeof(r.pqname)) >= sizeof(r.pqname)) {
2021					yyerror("rule pqname too long (max "
2022					    "%d chars)", sizeof(r.pqname)-1);
2023					YYERROR;
2024				}
2025				free($9.queues.pqname);
2026			}
2027
2028			expand_rule(&r, $4, $5.host, $7, $8.src_os,
2029			    $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
2030			    $9.uid, $9.gid, $9.icmpspec, "");
2031		}
2032		;
2033
2034opt_statelock	: statelock
2035		{
2036			$$ = calloc(1, sizeof(struct node_state_opt));
2037			if ($$ == NULL)
2038				err(EXIT_FAILURE, "opt_statelock: calloc");
2039			$$->type = PF_STATE_OPT_STATELOCK;
2040			$$->data.statelock = $1;
2041			$$->next = NULL;
2042			$$->tail = $$;
2043		}
2044		| /* empty */	{
2045			$$ = NULL;
2046		}
2047		;
2048
2049filter_opts	:	{
2050				bzero(&filter_opts, sizeof filter_opts);
2051				filter_opts.rtableid = -1;
2052			}
2053		    filter_opts_l
2054			{ $$ = filter_opts; }
2055		| /* empty */	{
2056			bzero(&filter_opts, sizeof filter_opts);
2057			filter_opts.rtableid = -1;
2058			$$ = filter_opts;
2059		}
2060		;
2061
2062filter_opts_l	: filter_opts_l filter_opt
2063		| filter_opt
2064		;
2065
2066filter_opt	: USER uids {
2067			if (filter_opts.uid)
2068				$2->tail->next = filter_opts.uid;
2069			filter_opts.uid = $2;
2070		}
2071		| GROUP gids {
2072			if (filter_opts.gid)
2073				$2->tail->next = filter_opts.gid;
2074			filter_opts.gid = $2;
2075		}
2076		| flags {
2077			if (filter_opts.marker & FOM_FLAGS) {
2078				yyerror("flags cannot be redefined");
2079				YYERROR;
2080			}
2081			filter_opts.marker |= FOM_FLAGS;
2082			filter_opts.flags.b1 |= $1.b1;
2083			filter_opts.flags.b2 |= $1.b2;
2084			filter_opts.flags.w |= $1.w;
2085			filter_opts.flags.w2 |= $1.w2;
2086		}
2087		| icmpspec {
2088			if (filter_opts.marker & FOM_ICMP) {
2089				yyerror("icmp-type cannot be redefined");
2090				YYERROR;
2091			}
2092			filter_opts.marker |= FOM_ICMP;
2093			filter_opts.icmpspec = $1;
2094		}
2095		| tos {
2096			if (filter_opts.marker & FOM_TOS) {
2097				yyerror("tos cannot be redefined");
2098				YYERROR;
2099			}
2100			filter_opts.marker |= FOM_TOS;
2101			filter_opts.tos = $1;
2102		}
2103		| keep {
2104			if (filter_opts.marker & FOM_KEEP) {
2105				yyerror("modulate or keep cannot be redefined");
2106				YYERROR;
2107			}
2108			filter_opts.marker |= FOM_KEEP;
2109			filter_opts.keep.action = $1.action;
2110			filter_opts.keep.options = $1.options;
2111		}
2112		| FRAGMENT {
2113			filter_opts.fragment = 1;
2114		}
2115		| ALLOWOPTS {
2116			filter_opts.allowopts = 1;
2117		}
2118		| label	{
2119			if (filter_opts.label) {
2120				yyerror("label cannot be redefined");
2121				YYERROR;
2122			}
2123			filter_opts.label = $1;
2124		}
2125		| qname	{
2126			if (filter_opts.queues.qname) {
2127				yyerror("queue cannot be redefined");
2128				YYERROR;
2129			}
2130			filter_opts.queues = $1;
2131		}
2132		| TAG string				{
2133			filter_opts.tag = $2;
2134		}
2135		| not TAGGED string			{
2136			filter_opts.match_tag = $3;
2137			filter_opts.match_tag_not = $1;
2138		}
2139		| PROBABILITY STRING			{
2140			char	*e;
2141			double	 p = strtod($2, &e);
2142
2143			if (*e == '%') {
2144				p *= 0.01;
2145				e++;
2146			}
2147			if (*e) {
2148				yyerror("invalid probability: %s", $2);
2149				free($2);
2150				YYERROR;
2151			}
2152			p = floor(p * (UINT_MAX+1.0) + 0.5);
2153			if (p < 1.0 || p >= (UINT_MAX+1.0)) {
2154				yyerror("invalid probability: %s", $2);
2155				free($2);
2156				YYERROR;
2157			}
2158			filter_opts.prob = (u_int32_t)p;
2159			free($2);
2160		}
2161		| RTABLE number				{
2162			if ($2 > RT_TABLEID_MAX || $2 < 0) {
2163				yyerror("invalid rtable id");
2164				YYERROR;
2165			}
2166			filter_opts.rtableid = $2;
2167		}
2168		;
2169
2170action		: PASS			{ $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
2171		| BLOCK blockspec	{ $$ = $2; $$.b1 = PF_DROP; }
2172		;
2173
2174blockspec	: /* empty */		{
2175			$$.b2 = blockpolicy;
2176			$$.w = returnicmpdefault;
2177			$$.w2 = returnicmp6default;
2178		}
2179		| DROP			{
2180			$$.b2 = PFRULE_DROP;
2181			$$.w = 0;
2182			$$.w2 = 0;
2183		}
2184		| RETURNRST		{
2185			$$.b2 = PFRULE_RETURNRST;
2186			$$.w = 0;
2187			$$.w2 = 0;
2188		}
2189		| RETURNRST '(' TTL number ')'	{
2190			if ($4 > 255) {
2191				yyerror("illegal ttl value %d", $4);
2192				YYERROR;
2193			}
2194			$$.b2 = PFRULE_RETURNRST;
2195			$$.w = $4;
2196			$$.w2 = 0;
2197		}
2198		| RETURNICMP		{
2199			$$.b2 = PFRULE_RETURNICMP;
2200			$$.w = returnicmpdefault;
2201			$$.w2 = returnicmp6default;
2202		}
2203		| RETURNICMP6		{
2204			$$.b2 = PFRULE_RETURNICMP;
2205			$$.w = returnicmpdefault;
2206			$$.w2 = returnicmp6default;
2207		}
2208		| RETURNICMP '(' STRING ')'	{
2209			$$.b2 = PFRULE_RETURNICMP;
2210			if (!($$.w = parseicmpspec($3, AF_INET))) {
2211				free($3);
2212				YYERROR;
2213			}
2214			free($3);
2215			$$.w2 = returnicmp6default;
2216		}
2217		| RETURNICMP6 '(' STRING ')'	{
2218			$$.b2 = PFRULE_RETURNICMP;
2219			$$.w = returnicmpdefault;
2220			if (!($$.w2 = parseicmpspec($3, AF_INET6))) {
2221				free($3);
2222				YYERROR;
2223			}
2224			free($3);
2225		}
2226		| RETURNICMP '(' STRING comma STRING ')' {
2227			$$.b2 = PFRULE_RETURNICMP;
2228			if (!($$.w = parseicmpspec($3, AF_INET)) ||
2229			    !($$.w2 = parseicmpspec($5, AF_INET6))) {
2230				free($3);
2231				free($5);
2232				YYERROR;
2233			}
2234			free($3);
2235			free($5);
2236		}
2237		| RETURN {
2238			$$.b2 = PFRULE_RETURN;
2239			$$.w = returnicmpdefault;
2240			$$.w2 = returnicmp6default;
2241		}
2242		;
2243
2244dir		: /* empty */			{ $$ = 0; }
2245		| IN				{ $$ = PF_IN; }
2246		| OUT				{ $$ = PF_OUT; }
2247		;
2248
2249quick		: /* empty */			{ $$.quick = 0; }
2250		| QUICK				{ $$.quick = 1; }
2251		;
2252
2253logquick	: /* empty */	{ $$.log = 0; $$.quick = 0; $$.logif = 0; }
2254		| log		{ $$ = $1; $$.quick = 0; }
2255		| QUICK		{ $$.quick = 1; $$.log = 0; $$.logif = 0; }
2256		| log QUICK	{ $$ = $1; $$.quick = 1; }
2257		| QUICK log	{ $$ = $2; $$.quick = 1; }
2258		;
2259
2260log		: LOG			{ $$.log = PF_LOG; $$.logif = 0; }
2261		| LOG '(' logopts ')'	{
2262			$$.log = PF_LOG | $3.log;
2263			$$.logif = $3.logif;
2264		}
2265		;
2266
2267logopts		: logopt			{ $$ = $1; }
2268		| logopts comma logopt		{
2269			$$.log = $1.log | $3.log;
2270			$$.logif = $3.logif;
2271			if ($$.logif == 0)
2272				$$.logif = $1.logif;
2273		}
2274		;
2275
2276logopt		: ALL		{ $$.log = PF_LOG_ALL; $$.logif = 0; }
2277		| USER		{ $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
2278		| GROUP		{ $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
2279		| TO string	{
2280			const char	*errstr = NULL; /* XXX gcc */
2281			u_int		 i;
2282
2283			$$.log = 0;
2284			if (strncmp($2, "pflog", 5)) {
2285				yyerror("%s: should be a pflog interface", $2);
2286				free($2);
2287				YYERROR;
2288			}
2289			i = strtonum($2 + 5, 0, 255, &errstr);
2290			if (errstr) {
2291				yyerror("%s: %s", $2, errstr);
2292				free($2);
2293				YYERROR;
2294			}
2295			free($2);
2296			$$.logif = i;
2297		}
2298		;
2299
2300interface	: /* empty */			{ $$ = NULL; }
2301		| ON if_item_not		{ $$ = $2; }
2302		| ON '{' if_list '}'		{ $$ = $3; }
2303		;
2304
2305if_list		: if_item_not			{ $$ = $1; }
2306		| if_list comma if_item_not	{
2307			$1->tail->next = $3;
2308			$1->tail = $3;
2309			$$ = $1;
2310		}
2311		;
2312
2313if_item_not	: not if_item			{ $$ = $2; $$->not = $1; }
2314		;
2315
2316if_item		: STRING			{
2317			struct node_host	*n;
2318
2319			$$ = calloc(1, sizeof(struct node_if));
2320			if ($$ == NULL)
2321				err(1, "if_item: calloc");
2322			if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >=
2323			    sizeof($$->ifname)) {
2324				free($1);
2325				free($$);
2326				yyerror("interface name too long");
2327				YYERROR;
2328			}
2329
2330			if ((n = ifa_exists($1)) != NULL)
2331				$$->ifa_flags = n->ifa_flags;
2332
2333			free($1);
2334			$$->not = 0;
2335			$$->next = NULL;
2336			$$->tail = $$;
2337		}
2338		;
2339
2340af		: /* empty */			{ $$ = 0; }
2341		| INET				{ $$ = AF_INET; }
2342		| INET6				{ $$ = AF_INET6; }
2343		;
2344
2345proto		: /* empty */			{ $$ = NULL; }
2346		| PROTO proto_item		{ $$ = $2; }
2347		| PROTO '{' proto_list '}'	{ $$ = $3; }
2348		;
2349
2350proto_list	: proto_item			{ $$ = $1; }
2351		| proto_list comma proto_item	{
2352			$1->tail->next = $3;
2353			$1->tail = $3;
2354			$$ = $1;
2355		}
2356		;
2357
2358proto_item	: STRING			{
2359			u_int8_t	pr;
2360			u_long		ulval;
2361
2362			if (atoul($1, &ulval) == 0) {
2363				if (ulval > 255) {
2364					yyerror("protocol outside range");
2365					free($1);
2366					YYERROR;
2367				}
2368				pr = (u_int8_t)ulval;
2369			} else {
2370				struct protoent	*p;
2371
2372				p = getprotobyname($1);
2373				if (p == NULL) {
2374					yyerror("unknown protocol %s", $1);
2375					free($1);
2376					YYERROR;
2377				}
2378				pr = p->p_proto;
2379			}
2380			free($1);
2381			if (pr == 0) {
2382				yyerror("proto 0 cannot be used");
2383				YYERROR;
2384			}
2385			$$ = calloc(1, sizeof(struct node_proto));
2386			if ($$ == NULL)
2387				err(1, "proto_item: calloc");
2388			$$->proto = pr;
2389			$$->next = NULL;
2390			$$->tail = $$;
2391		}
2392		;
2393
2394fromto		: ALL				{
2395			$$.src.host = NULL;
2396			$$.src.port = NULL;
2397			$$.dst.host = NULL;
2398			$$.dst.port = NULL;
2399			$$.src_os = NULL;
2400		}
2401		| from os to			{
2402			$$.src = $1;
2403			$$.src_os = $2;
2404			$$.dst = $3;
2405		}
2406		;
2407
2408os		: /* empty */			{ $$ = NULL; }
2409		| OS xos			{ $$ = $2; }
2410		| OS '{' os_list '}'		{ $$ = $3; }
2411		;
2412
2413xos		: STRING {
2414			$$ = calloc(1, sizeof(struct node_os));
2415			if ($$ == NULL)
2416				err(1, "os: calloc");
2417			$$->os = $1;
2418			$$->tail = $$;
2419		}
2420		;
2421
2422os_list		: xos				{ $$ = $1; }
2423		| os_list comma xos		{
2424			$1->tail->next = $3;
2425			$1->tail = $3;
2426			$$ = $1;
2427		}
2428		;
2429
2430from		: /* empty */			{
2431			$$.host = NULL;
2432			$$.port = NULL;
2433		}
2434		| FROM ipportspec		{
2435			$$ = $2;
2436		}
2437		;
2438
2439to		: /* empty */			{
2440			$$.host = NULL;
2441			$$.port = NULL;
2442		}
2443		| TO ipportspec		{
2444			if (disallow_urpf_failed($2.host, "\"urpf-failed\" is "
2445			    "not permitted in a destination address"))
2446				YYERROR;
2447			$$ = $2;
2448		}
2449		;
2450
2451ipportspec	: ipspec			{
2452			$$.host = $1;
2453			$$.port = NULL;
2454		}
2455		| ipspec PORT portspec		{
2456			$$.host = $1;
2457			$$.port = $3;
2458		}
2459		| PORT portspec			{
2460			$$.host = NULL;
2461			$$.port = $2;
2462		}
2463		;
2464
2465ipspec		: ANY				{ $$ = NULL; }
2466		| xhost				{ $$ = $1; }
2467		| '{' host_list '}'		{ $$ = $2; }
2468		;
2469
2470host_list	: ipspec			{ $$ = $1; }
2471		| host_list comma ipspec	{
2472			if ($3 == NULL)
2473				$$ = $1;
2474			else if ($1 == NULL)
2475				$$ = $3;
2476			else {
2477				$1->tail->next = $3;
2478				$1->tail = $3->tail;
2479				$$ = $1;
2480			}
2481		}
2482		;
2483
2484xhost		: not host			{
2485			struct node_host	*n;
2486
2487			for (n = $2; n != NULL; n = n->next)
2488				n->not = $1;
2489			$$ = $2;
2490		}
2491		| not NOROUTE			{
2492			$$ = calloc(1, sizeof(struct node_host));
2493			if ($$ == NULL)
2494				err(1, "xhost: calloc");
2495			$$->addr.type = PF_ADDR_NOROUTE;
2496			$$->next = NULL;
2497			$$->not = $1;
2498			$$->tail = $$;
2499		}
2500		| not URPFFAILED		{
2501			$$ = calloc(1, sizeof(struct node_host));
2502			if ($$ == NULL)
2503				err(1, "xhost: calloc");
2504			$$->addr.type = PF_ADDR_URPFFAILED;
2505			$$->next = NULL;
2506			$$->not = $1;
2507			$$->tail = $$;
2508		}
2509		;
2510
2511host		: STRING			{
2512			if (($$ = host($1)) == NULL)	{
2513				/* error. "any" is handled elsewhere */
2514				free($1);
2515				yyerror("could not parse host specification");
2516				YYERROR;
2517			}
2518			free($1);
2519
2520		}
2521		| STRING '/' number		{
2522			char	*buf;
2523
2524			if (asprintf(&buf, "%s/%u", $1, $3) == -1)
2525				err(1, "host: asprintf");
2526			free($1);
2527			if (($$ = host(buf)) == NULL)	{
2528				/* error. "any" is handled elsewhere */
2529				free(buf);
2530				yyerror("could not parse host specification");
2531				YYERROR;
2532			}
2533			free(buf);
2534		}
2535		| dynaddr
2536		| dynaddr '/' number		{
2537			struct node_host	*n;
2538
2539			$$ = $1;
2540			for (n = $1; n != NULL; n = n->next)
2541				set_ipmask(n, $3);
2542		}
2543		| '<' STRING '>'	{
2544			if (strlen($2) >= PF_TABLE_NAME_SIZE) {
2545				yyerror("table name '%s' too long", $2);
2546				free($2);
2547				YYERROR;
2548			}
2549			$$ = calloc(1, sizeof(struct node_host));
2550			if ($$ == NULL)
2551				err(1, "host: calloc");
2552			$$->addr.type = PF_ADDR_TABLE;
2553			if (strlcpy($$->addr.v.tblname, $2,
2554			    sizeof($$->addr.v.tblname)) >=
2555			    sizeof($$->addr.v.tblname))
2556				errx(1, "host: strlcpy");
2557			free($2);
2558			$$->next = NULL;
2559			$$->tail = $$;
2560		}
2561		| ROUTE	STRING		{
2562			$$ = calloc(1, sizeof(struct node_host));
2563			if ($$ == NULL) {
2564				free($2);
2565				err(1, "host: calloc");
2566			}
2567			$$->addr.type = PF_ADDR_RTLABEL;
2568			if (strlcpy($$->addr.v.rtlabelname, $2,
2569			    sizeof($$->addr.v.rtlabelname)) >=
2570			    sizeof($$->addr.v.rtlabelname)) {
2571				yyerror("route label too long, max %u chars",
2572				    sizeof($$->addr.v.rtlabelname) - 1);
2573				free($2);
2574				free($$);
2575				YYERROR;
2576			}
2577			$$->next = NULL;
2578			$$->tail = $$;
2579			free($2);
2580		}
2581		;
2582
2583number		: STRING			{
2584			u_long	ulval;
2585
2586			if (atoul($1, &ulval) == -1) {
2587				yyerror("%s is not a number", $1);
2588				free($1);
2589				YYERROR;
2590			} else
2591				$$ = ulval;
2592			free($1);
2593		}
2594		;
2595
2596dynaddr		: '(' STRING ')'		{
2597			int	 flags = 0;
2598			char	*p, *op;
2599
2600			op = $2;
2601			if (!isalpha((unsigned char)op[0])) {
2602				yyerror("invalid interface name '%s'", op);
2603				free(op);
2604				YYERROR;
2605			}
2606			while ((p = strrchr($2, ':')) != NULL) {
2607				if (!strcmp(p+1, "network"))
2608					flags |= PFI_AFLAG_NETWORK;
2609				else if (!strcmp(p+1, "broadcast"))
2610					flags |= PFI_AFLAG_BROADCAST;
2611				else if (!strcmp(p+1, "peer"))
2612					flags |= PFI_AFLAG_PEER;
2613				else if (!strcmp(p+1, "0"))
2614					flags |= PFI_AFLAG_NOALIAS;
2615				else {
2616					yyerror("interface %s has bad modifier",
2617					    $2);
2618					free(op);
2619					YYERROR;
2620				}
2621				*p = '\0';
2622			}
2623			if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) {
2624				free(op);
2625				yyerror("illegal combination of "
2626				    "interface modifiers");
2627				YYERROR;
2628			}
2629			$$ = calloc(1, sizeof(struct node_host));
2630			if ($$ == NULL)
2631				err(1, "address: calloc");
2632			$$->af = 0;
2633			set_ipmask($$, 128);
2634			$$->addr.type = PF_ADDR_DYNIFTL;
2635			$$->addr.iflags = flags;
2636			if (strlcpy($$->addr.v.ifname, $2,
2637			    sizeof($$->addr.v.ifname)) >=
2638			    sizeof($$->addr.v.ifname)) {
2639				free(op);
2640				free($$);
2641				yyerror("interface name too long");
2642				YYERROR;
2643			}
2644			free(op);
2645			$$->next = NULL;
2646			$$->tail = $$;
2647		}
2648		;
2649
2650portspec	: port_item			{ $$ = $1; }
2651		| '{' port_list '}'		{ $$ = $2; }
2652		;
2653
2654port_list	: port_item			{ $$ = $1; }
2655		| port_list comma port_item	{
2656			$1->tail->next = $3;
2657			$1->tail = $3;
2658			$$ = $1;
2659		}
2660		;
2661
2662port_item	: port				{
2663			$$ = calloc(1, sizeof(struct node_port));
2664			if ($$ == NULL)
2665				err(1, "port_item: calloc");
2666			$$->port[0] = $1.a;
2667			$$->port[1] = $1.b;
2668			if ($1.t)
2669				$$->op = PF_OP_RRG;
2670			else
2671				$$->op = PF_OP_EQ;
2672			$$->next = NULL;
2673			$$->tail = $$;
2674		}
2675		| unaryop port		{
2676			if ($2.t) {
2677				yyerror("':' cannot be used with an other "
2678				    "port operator");
2679				YYERROR;
2680			}
2681			$$ = calloc(1, sizeof(struct node_port));
2682			if ($$ == NULL)
2683				err(1, "port_item: calloc");
2684			$$->port[0] = $2.a;
2685			$$->port[1] = $2.b;
2686			$$->op = $1;
2687			$$->next = NULL;
2688			$$->tail = $$;
2689		}
2690		| port PORTBINARY port		{
2691			if ($1.t || $3.t) {
2692				yyerror("':' cannot be used with an other "
2693				    "port operator");
2694				YYERROR;
2695			}
2696			$$ = calloc(1, sizeof(struct node_port));
2697			if ($$ == NULL)
2698				err(1, "port_item: calloc");
2699			$$->port[0] = $1.a;
2700			$$->port[1] = $3.a;
2701			$$->op = $2;
2702			$$->next = NULL;
2703			$$->tail = $$;
2704		}
2705		;
2706
2707port		: STRING			{
2708			char	*p = strchr($1, ':');
2709
2710			if (p == NULL) {
2711				if (($$.a = getservice($1)) == -1) {
2712					free($1);
2713					YYERROR;
2714				}
2715				$$.b = $$.t = 0;
2716			} else {
2717				int port[2];
2718
2719				*p++ = 0;
2720				if ((port[0] = getservice($1)) == -1 ||
2721				    (port[1] = getservice(p)) == -1) {
2722					free($1);
2723					YYERROR;
2724				}
2725				$$.a = port[0];
2726				$$.b = port[1];
2727				$$.t = PF_OP_RRG;
2728			}
2729			free($1);
2730		}
2731		;
2732
2733uids		: uid_item			{ $$ = $1; }
2734		| '{' uid_list '}'		{ $$ = $2; }
2735		;
2736
2737uid_list	: uid_item			{ $$ = $1; }
2738		| uid_list comma uid_item	{
2739			$1->tail->next = $3;
2740			$1->tail = $3;
2741			$$ = $1;
2742		}
2743		;
2744
2745uid_item	: uid				{
2746			$$ = calloc(1, sizeof(struct node_uid));
2747			if ($$ == NULL)
2748				err(1, "uid_item: calloc");
2749			$$->uid[0] = $1;
2750			$$->uid[1] = $1;
2751			$$->op = PF_OP_EQ;
2752			$$->next = NULL;
2753			$$->tail = $$;
2754		}
2755		| unaryop uid			{
2756			if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
2757				yyerror("user unknown requires operator = or "
2758				    "!=");
2759				YYERROR;
2760			}
2761			$$ = calloc(1, sizeof(struct node_uid));
2762			if ($$ == NULL)
2763				err(1, "uid_item: calloc");
2764			$$->uid[0] = $2;
2765			$$->uid[1] = $2;
2766			$$->op = $1;
2767			$$->next = NULL;
2768			$$->tail = $$;
2769		}
2770		| uid PORTBINARY uid		{
2771			if ($1 == UID_MAX || $3 == UID_MAX) {
2772				yyerror("user unknown requires operator = or "
2773				    "!=");
2774				YYERROR;
2775			}
2776			$$ = calloc(1, sizeof(struct node_uid));
2777			if ($$ == NULL)
2778				err(1, "uid_item: calloc");
2779			$$->uid[0] = $1;
2780			$$->uid[1] = $3;
2781			$$->op = $2;
2782			$$->next = NULL;
2783			$$->tail = $$;
2784		}
2785		;
2786
2787uid		: STRING			{
2788			u_long	ulval;
2789
2790			if (atoul($1, &ulval) == -1) {
2791				if (!strcmp($1, "unknown"))
2792					$$ = UID_MAX;
2793				else {
2794					struct passwd	*pw;
2795
2796					if ((pw = getpwnam($1)) == NULL) {
2797						yyerror("unknown user %s", $1);
2798						free($1);
2799						YYERROR;
2800					}
2801					$$ = pw->pw_uid;
2802				}
2803			} else {
2804				if (ulval >= UID_MAX) {
2805					free($1);
2806					yyerror("illegal uid value %lu", ulval);
2807					YYERROR;
2808				}
2809				$$ = ulval;
2810			}
2811			free($1);
2812		}
2813		;
2814
2815gids		: gid_item			{ $$ = $1; }
2816		| '{' gid_list '}'		{ $$ = $2; }
2817		;
2818
2819gid_list	: gid_item			{ $$ = $1; }
2820		| gid_list comma gid_item	{
2821			$1->tail->next = $3;
2822			$1->tail = $3;
2823			$$ = $1;
2824		}
2825		;
2826
2827gid_item	: gid				{
2828			$$ = calloc(1, sizeof(struct node_gid));
2829			if ($$ == NULL)
2830				err(1, "gid_item: calloc");
2831			$$->gid[0] = $1;
2832			$$->gid[1] = $1;
2833			$$->op = PF_OP_EQ;
2834			$$->next = NULL;
2835			$$->tail = $$;
2836		}
2837		| unaryop gid			{
2838			if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
2839				yyerror("group unknown requires operator = or "
2840				    "!=");
2841				YYERROR;
2842			}
2843			$$ = calloc(1, sizeof(struct node_gid));
2844			if ($$ == NULL)
2845				err(1, "gid_item: calloc");
2846			$$->gid[0] = $2;
2847			$$->gid[1] = $2;
2848			$$->op = $1;
2849			$$->next = NULL;
2850			$$->tail = $$;
2851		}
2852		| gid PORTBINARY gid		{
2853			if ($1 == GID_MAX || $3 == GID_MAX) {
2854				yyerror("group unknown requires operator = or "
2855				    "!=");
2856				YYERROR;
2857			}
2858			$$ = calloc(1, sizeof(struct node_gid));
2859			if ($$ == NULL)
2860				err(1, "gid_item: calloc");
2861			$$->gid[0] = $1;
2862			$$->gid[1] = $3;
2863			$$->op = $2;
2864			$$->next = NULL;
2865			$$->tail = $$;
2866		}
2867		;
2868
2869gid		: STRING			{
2870			u_long	ulval;
2871
2872			if (atoul($1, &ulval) == -1) {
2873				if (!strcmp($1, "unknown"))
2874					$$ = GID_MAX;
2875				else {
2876					struct group	*grp;
2877
2878					if ((grp = getgrnam($1)) == NULL) {
2879						yyerror("unknown group %s", $1);
2880						free($1);
2881						YYERROR;
2882					}
2883					$$ = grp->gr_gid;
2884				}
2885			} else {
2886				if (ulval >= GID_MAX) {
2887					yyerror("illegal gid value %lu", ulval);
2888					free($1);
2889					YYERROR;
2890				}
2891				$$ = ulval;
2892			}
2893			free($1);
2894		}
2895		;
2896
2897flag		: STRING			{
2898			int	f;
2899
2900			if ((f = parse_flags($1)) < 0) {
2901				yyerror("bad flags %s", $1);
2902				free($1);
2903				YYERROR;
2904			}
2905			free($1);
2906			$$.b1 = f;
2907		}
2908		;
2909
2910flags		: FLAGS flag '/' flag	{ $$.b1 = $2.b1; $$.b2 = $4.b1; }
2911		| FLAGS '/' flag	{ $$.b1 = 0; $$.b2 = $3.b1; }
2912		| FLAGS ANY		{ $$.b1 = 0; $$.b2 = 0; }
2913		;
2914
2915icmpspec	: ICMPTYPE icmp_item		{ $$ = $2; }
2916		| ICMPTYPE '{' icmp_list '}'	{ $$ = $3; }
2917		| ICMP6TYPE icmp6_item		{ $$ = $2; }
2918		| ICMP6TYPE '{' icmp6_list '}'	{ $$ = $3; }
2919		;
2920
2921icmp_list	: icmp_item			{ $$ = $1; }
2922		| icmp_list comma icmp_item	{
2923			$1->tail->next = $3;
2924			$1->tail = $3;
2925			$$ = $1;
2926		}
2927		;
2928
2929icmp6_list	: icmp6_item			{ $$ = $1; }
2930		| icmp6_list comma icmp6_item	{
2931			$1->tail->next = $3;
2932			$1->tail = $3;
2933			$$ = $1;
2934		}
2935		;
2936
2937icmp_item	: icmptype		{
2938			$$ = calloc(1, sizeof(struct node_icmp));
2939			if ($$ == NULL)
2940				err(1, "icmp_item: calloc");
2941			$$->type = $1;
2942			$$->code = 0;
2943			$$->proto = IPPROTO_ICMP;
2944			$$->next = NULL;
2945			$$->tail = $$;
2946		}
2947		| icmptype CODE STRING	{
2948			const struct icmpcodeent	*p;
2949			u_long				 ulval;
2950
2951			if (atoul($3, &ulval) == 0) {
2952				if (ulval > 255) {
2953					free($3);
2954					yyerror("illegal icmp-code %lu", ulval);
2955					YYERROR;
2956				}
2957			} else {
2958				if ((p = geticmpcodebyname($1-1, $3,
2959				    AF_INET)) == NULL) {
2960					yyerror("unknown icmp-code %s", $3);
2961					free($3);
2962					YYERROR;
2963				}
2964				ulval = p->code;
2965			}
2966			free($3);
2967			$$ = calloc(1, sizeof(struct node_icmp));
2968			if ($$ == NULL)
2969				err(1, "icmp_item: calloc");
2970			$$->type = $1;
2971			$$->code = ulval + 1;
2972			$$->proto = IPPROTO_ICMP;
2973			$$->next = NULL;
2974			$$->tail = $$;
2975		}
2976		;
2977
2978icmp6_item	: icmp6type		{
2979			$$ = calloc(1, sizeof(struct node_icmp));
2980			if ($$ == NULL)
2981				err(1, "icmp_item: calloc");
2982			$$->type = $1;
2983			$$->code = 0;
2984			$$->proto = IPPROTO_ICMPV6;
2985			$$->next = NULL;
2986			$$->tail = $$;
2987		}
2988		| icmp6type CODE STRING	{
2989			const struct icmpcodeent	*p;
2990			u_long				 ulval;
2991
2992			if (atoul($3, &ulval) == 0) {
2993				if (ulval > 255) {
2994					yyerror("illegal icmp6-code %lu",
2995					    ulval);
2996					free($3);
2997					YYERROR;
2998				}
2999			} else {
3000				if ((p = geticmpcodebyname($1-1, $3,
3001				    AF_INET6)) == NULL) {
3002					yyerror("unknown icmp6-code %s", $3);
3003					free($3);
3004					YYERROR;
3005				}
3006				ulval = p->code;
3007			}
3008			free($3);
3009			$$ = calloc(1, sizeof(struct node_icmp));
3010			if ($$ == NULL)
3011				err(1, "icmp_item: calloc");
3012			$$->type = $1;
3013			$$->code = ulval + 1;
3014			$$->proto = IPPROTO_ICMPV6;
3015			$$->next = NULL;
3016			$$->tail = $$;
3017		}
3018		;
3019
3020icmptype	: STRING			{
3021			const struct icmptypeent	*p;
3022			u_long				 ulval;
3023
3024			if (atoul($1, &ulval) == 0) {
3025				if (ulval > 255) {
3026					yyerror("illegal icmp-type %lu", ulval);
3027					free($1);
3028					YYERROR;
3029				}
3030				$$ = ulval + 1;
3031			} else {
3032				if ((p = geticmptypebyname($1, AF_INET)) ==
3033				    NULL) {
3034					yyerror("unknown icmp-type %s", $1);
3035					free($1);
3036					YYERROR;
3037				}
3038				$$ = p->type + 1;
3039			}
3040			free($1);
3041		}
3042		;
3043
3044icmp6type	: STRING			{
3045			const struct icmptypeent	*p;
3046			u_long				 ulval;
3047
3048			if (atoul($1, &ulval) == 0) {
3049				if (ulval > 255) {
3050					yyerror("illegal icmp6-type %lu",
3051					    ulval);
3052					free($1);
3053					YYERROR;
3054				}
3055				$$ = ulval + 1;
3056			} else {
3057				if ((p = geticmptypebyname($1, AF_INET6)) ==
3058				    NULL) {
3059					yyerror("unknown icmp6-type %s", $1);
3060					free($1);
3061					YYERROR;
3062				}
3063				$$ = p->type + 1;
3064			}
3065			free($1);
3066		}
3067		;
3068
3069tos		: TOS STRING			{
3070			if (!strcmp($2, "lowdelay"))
3071				$$ = IPTOS_LOWDELAY;
3072			else if (!strcmp($2, "throughput"))
3073				$$ = IPTOS_THROUGHPUT;
3074			else if (!strcmp($2, "reliability"))
3075				$$ = IPTOS_RELIABILITY;
3076			else if ($2[0] == '0' && $2[1] == 'x')
3077				$$ = strtoul($2, NULL, 16);
3078			else
3079				$$ = strtoul($2, NULL, 10);
3080			if (!$$ || $$ > 255) {
3081				yyerror("illegal tos value %s", $2);
3082				free($2);
3083				YYERROR;
3084			}
3085			free($2);
3086		}
3087		;
3088
3089sourcetrack	: SOURCETRACK		{ $$ = PF_SRCTRACK; }
3090		| SOURCETRACK GLOBAL	{ $$ = PF_SRCTRACK_GLOBAL; }
3091		| SOURCETRACK RULE	{ $$ = PF_SRCTRACK_RULE; }
3092		;
3093
3094statelock	: IFBOUND {
3095			$$ = PFRULE_IFBOUND;
3096		}
3097		| FLOATING {
3098			$$ = 0;
3099		}
3100		;
3101
3102keep		: NO STATE			{
3103			$$.action = 0;
3104			$$.options = NULL;
3105		}
3106		| KEEP STATE state_opt_spec	{
3107			$$.action = PF_STATE_NORMAL;
3108			$$.options = $3;
3109		}
3110		| MODULATE STATE state_opt_spec {
3111			$$.action = PF_STATE_MODULATE;
3112			$$.options = $3;
3113		}
3114		| SYNPROXY STATE state_opt_spec {
3115			$$.action = PF_STATE_SYNPROXY;
3116			$$.options = $3;
3117		}
3118		;
3119
3120flush		: /* empty */			{ $$ = 0; }
3121		| FLUSH				{ $$ = PF_FLUSH; }
3122		| FLUSH GLOBAL			{
3123			$$ = PF_FLUSH | PF_FLUSH_GLOBAL;
3124		}
3125		;
3126
3127state_opt_spec	: '(' state_opt_list ')'	{ $$ = $2; }
3128		| /* empty */			{ $$ = NULL; }
3129		;
3130
3131state_opt_list	: state_opt_item		{ $$ = $1; }
3132		| state_opt_list comma state_opt_item {
3133			$1->tail->next = $3;
3134			$1->tail = $3;
3135			$$ = $1;
3136		}
3137		;
3138
3139state_opt_item	: MAXIMUM number		{
3140			$$ = calloc(1, sizeof(struct node_state_opt));
3141			if ($$ == NULL)
3142				err(1, "state_opt_item: calloc");
3143			$$->type = PF_STATE_OPT_MAX;
3144			$$->data.max_states = $2;
3145			$$->next = NULL;
3146			$$->tail = $$;
3147		}
3148		| NOSYNC				{
3149			$$ = calloc(1, sizeof(struct node_state_opt));
3150			if ($$ == NULL)
3151				err(1, "state_opt_item: calloc");
3152			$$->type = PF_STATE_OPT_NOSYNC;
3153			$$->next = NULL;
3154			$$->tail = $$;
3155		}
3156		| MAXSRCSTATES number			{
3157			$$ = calloc(1, sizeof(struct node_state_opt));
3158			if ($$ == NULL)
3159				err(1, "state_opt_item: calloc");
3160			$$->type = PF_STATE_OPT_MAX_SRC_STATES;
3161			$$->data.max_src_states = $2;
3162			$$->next = NULL;
3163			$$->tail = $$;
3164		}
3165		| MAXSRCCONN number			{
3166			$$ = calloc(1, sizeof(struct node_state_opt));
3167			if ($$ == NULL)
3168				err(1, "state_opt_item: calloc");
3169			$$->type = PF_STATE_OPT_MAX_SRC_CONN;
3170			$$->data.max_src_conn = $2;
3171			$$->next = NULL;
3172			$$->tail = $$;
3173		}
3174		| MAXSRCCONNRATE number '/' number	{
3175			$$ = calloc(1, sizeof(struct node_state_opt));
3176			if ($$ == NULL)
3177				err(1, "state_opt_item: calloc");
3178			$$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE;
3179			$$->data.max_src_conn_rate.limit = $2;
3180			$$->data.max_src_conn_rate.seconds = $4;
3181			$$->next = NULL;
3182			$$->tail = $$;
3183		}
3184		| OVERLOAD '<' STRING '>' flush		{
3185			if (strlen($3) >= PF_TABLE_NAME_SIZE) {
3186				yyerror("table name '%s' too long", $3);
3187				free($3);
3188				YYERROR;
3189			}
3190			$$ = calloc(1, sizeof(struct node_state_opt));
3191			if ($$ == NULL)
3192				err(1, "state_opt_item: calloc");
3193			if (strlcpy($$->data.overload.tblname, $3,
3194			    PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE)
3195				errx(1, "state_opt_item: strlcpy");
3196			free($3);
3197			$$->type = PF_STATE_OPT_OVERLOAD;
3198			$$->data.overload.flush = $5;
3199			$$->next = NULL;
3200			$$->tail = $$;
3201		}
3202		| MAXSRCNODES number			{
3203			$$ = calloc(1, sizeof(struct node_state_opt));
3204			if ($$ == NULL)
3205				err(1, "state_opt_item: calloc");
3206			$$->type = PF_STATE_OPT_MAX_SRC_NODES;
3207			$$->data.max_src_nodes = $2;
3208			$$->next = NULL;
3209			$$->tail = $$;
3210		}
3211		| sourcetrack {
3212			$$ = calloc(1, sizeof(struct node_state_opt));
3213			if ($$ == NULL)
3214				err(1, "state_opt_item: calloc");
3215			$$->type = PF_STATE_OPT_SRCTRACK;
3216			$$->data.src_track = $1;
3217			$$->next = NULL;
3218			$$->tail = $$;
3219		}
3220		| statelock {
3221			$$ = calloc(1, sizeof(struct node_state_opt));
3222			if ($$ == NULL)
3223				err(1, "state_opt_item: calloc");
3224			$$->type = PF_STATE_OPT_STATELOCK;
3225			$$->data.statelock = $1;
3226			$$->next = NULL;
3227			$$->tail = $$;
3228		}
3229		| STRING number			{
3230			int	i;
3231
3232			for (i = 0; pf_timeouts[i].name &&
3233			    strcmp(pf_timeouts[i].name, $1); ++i)
3234				;	/* nothing */
3235			if (!pf_timeouts[i].name) {
3236				yyerror("illegal timeout name %s", $1);
3237				free($1);
3238				YYERROR;
3239			}
3240			if (strchr(pf_timeouts[i].name, '.') == NULL) {
3241				yyerror("illegal state timeout %s", $1);
3242				free($1);
3243				YYERROR;
3244			}
3245			free($1);
3246			$$ = calloc(1, sizeof(struct node_state_opt));
3247			if ($$ == NULL)
3248				err(1, "state_opt_item: calloc");
3249			$$->type = PF_STATE_OPT_TIMEOUT;
3250			$$->data.timeout.number = pf_timeouts[i].timeout;
3251			$$->data.timeout.seconds = $2;
3252			$$->next = NULL;
3253			$$->tail = $$;
3254		}
3255		;
3256
3257label		: LABEL STRING			{
3258			$$ = $2;
3259		}
3260		;
3261
3262qname		: QUEUE STRING				{
3263			$$.qname = $2;
3264		}
3265		| QUEUE '(' STRING ')'			{
3266			$$.qname = $3;
3267		}
3268		| QUEUE '(' STRING comma STRING ')'	{
3269			$$.qname = $3;
3270			$$.pqname = $5;
3271		}
3272		;
3273
3274no		: /* empty */			{ $$ = 0; }
3275		| NO				{ $$ = 1; }
3276		;
3277
3278rport		: STRING			{
3279			char	*p = strchr($1, ':');
3280
3281			if (p == NULL) {
3282				if (($$.a = getservice($1)) == -1) {
3283					free($1);
3284					YYERROR;
3285				}
3286				$$.b = $$.t = 0;
3287			} else if (!strcmp(p+1, "*")) {
3288				*p = 0;
3289				if (($$.a = getservice($1)) == -1) {
3290					free($1);
3291					YYERROR;
3292				}
3293				$$.b = 0;
3294				$$.t = 1;
3295			} else {
3296				*p++ = 0;
3297				if (($$.a = getservice($1)) == -1 ||
3298				    ($$.b = getservice(p)) == -1) {
3299					free($1);
3300					YYERROR;
3301				}
3302				if ($$.a == $$.b)
3303					$$.b = 0;
3304				$$.t = 0;
3305			}
3306			free($1);
3307		}
3308		;
3309
3310redirspec	: host				{ $$ = $1; }
3311		| '{' redir_host_list '}'	{ $$ = $2; }
3312		;
3313
3314redir_host_list	: host				{ $$ = $1; }
3315		| redir_host_list comma host	{
3316			$1->tail->next = $3;
3317			$1->tail = $3->tail;
3318			$$ = $1;
3319		}
3320		;
3321
3322redirpool	: /* empty */			{ $$ = NULL; }
3323		| ARROW redirspec		{
3324			$$ = calloc(1, sizeof(struct redirection));
3325			if ($$ == NULL)
3326				err(1, "redirection: calloc");
3327			$$->host = $2;
3328			$$->rport.a = $$->rport.b = $$->rport.t = 0;
3329		}
3330		| ARROW redirspec PORT rport	{
3331			$$ = calloc(1, sizeof(struct redirection));
3332			if ($$ == NULL)
3333				err(1, "redirection: calloc");
3334			$$->host = $2;
3335			$$->rport = $4;
3336		}
3337		;
3338
3339hashkey		: /* empty */
3340		{
3341			$$ = calloc(1, sizeof(struct pf_poolhashkey));
3342			if ($$ == NULL)
3343				err(1, "hashkey: calloc");
3344			$$->key32[0] = arc4random();
3345			$$->key32[1] = arc4random();
3346			$$->key32[2] = arc4random();
3347			$$->key32[3] = arc4random();
3348		}
3349		| string
3350		{
3351			if (!strncmp($1, "0x", 2)) {
3352				if (strlen($1) != 34) {
3353					free($1);
3354					yyerror("hex key must be 128 bits "
3355						"(32 hex digits) long");
3356					YYERROR;
3357				}
3358				$$ = calloc(1, sizeof(struct pf_poolhashkey));
3359				if ($$ == NULL)
3360					err(1, "hashkey: calloc");
3361
3362				if (sscanf($1, "0x%8x%8x%8x%8x",
3363				    &$$->key32[0], &$$->key32[1],
3364				    &$$->key32[2], &$$->key32[3]) != 4) {
3365					free($$);
3366					free($1);
3367					yyerror("invalid hex key");
3368					YYERROR;
3369				}
3370			} else {
3371				MD5_CTX	context;
3372
3373				$$ = calloc(1, sizeof(struct pf_poolhashkey));
3374				if ($$ == NULL)
3375					err(1, "hashkey: calloc");
3376				MD5Init(&context);
3377				MD5Update(&context, (unsigned char *)$1,
3378				    strlen($1));
3379				MD5Final((unsigned char *)$$, &context);
3380				HTONL($$->key32[0]);
3381				HTONL($$->key32[1]);
3382				HTONL($$->key32[2]);
3383				HTONL($$->key32[3]);
3384			}
3385			free($1);
3386		}
3387		;
3388
3389pool_opts	:	{ bzero(&pool_opts, sizeof pool_opts); }
3390		    pool_opts_l
3391			{ $$ = pool_opts; }
3392		| /* empty */	{
3393			bzero(&pool_opts, sizeof pool_opts);
3394			$$ = pool_opts;
3395		}
3396		;
3397
3398pool_opts_l	: pool_opts_l pool_opt
3399		| pool_opt
3400		;
3401
3402pool_opt	: BITMASK	{
3403			if (pool_opts.type) {
3404				yyerror("pool type cannot be redefined");
3405				YYERROR;
3406			}
3407			pool_opts.type =  PF_POOL_BITMASK;
3408		}
3409		| RANDOM	{
3410			if (pool_opts.type) {
3411				yyerror("pool type cannot be redefined");
3412				YYERROR;
3413			}
3414			pool_opts.type = PF_POOL_RANDOM;
3415		}
3416		| SOURCEHASH hashkey {
3417			if (pool_opts.type) {
3418				yyerror("pool type cannot be redefined");
3419				YYERROR;
3420			}
3421			pool_opts.type = PF_POOL_SRCHASH;
3422			pool_opts.key = $2;
3423		}
3424		| ROUNDROBIN	{
3425			if (pool_opts.type) {
3426				yyerror("pool type cannot be redefined");
3427				YYERROR;
3428			}
3429			pool_opts.type = PF_POOL_ROUNDROBIN;
3430		}
3431		| STATICPORT	{
3432			if (pool_opts.staticport) {
3433				yyerror("static-port cannot be redefined");
3434				YYERROR;
3435			}
3436			pool_opts.staticport = 1;
3437		}
3438		| STICKYADDRESS	{
3439			if (filter_opts.marker & POM_STICKYADDRESS) {
3440				yyerror("sticky-address cannot be redefined");
3441				YYERROR;
3442			}
3443			pool_opts.marker |= POM_STICKYADDRESS;
3444			pool_opts.opts |= PF_POOL_STICKYADDR;
3445		}
3446		;
3447
3448redirection	: /* empty */			{ $$ = NULL; }
3449		| ARROW host			{
3450			$$ = calloc(1, sizeof(struct redirection));
3451			if ($$ == NULL)
3452				err(1, "redirection: calloc");
3453			$$->host = $2;
3454			$$->rport.a = $$->rport.b = $$->rport.t = 0;
3455		}
3456		| ARROW host PORT rport	{
3457			$$ = calloc(1, sizeof(struct redirection));
3458			if ($$ == NULL)
3459				err(1, "redirection: calloc");
3460			$$->host = $2;
3461			$$->rport = $4;
3462		}
3463		;
3464
3465natpasslog	: /* empty */	{ $$.b1 = $$.b2 = 0; $$.w2 = 0; }
3466		| PASS		{ $$.b1 = 1; $$.b2 = 0; $$.w2 = 0; }
3467		| PASS log	{ $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; }
3468		| log		{ $$.b1 = 0; $$.b2 = $1.log; $$.w2 = $1.logif; }
3469		;
3470
3471nataction	: no NAT natpasslog {
3472			if ($1 && $3.b1) {
3473				yyerror("\"pass\" not valid with \"no\"");
3474				YYERROR;
3475			}
3476			if ($1)
3477				$$.b1 = PF_NONAT;
3478			else
3479				$$.b1 = PF_NAT;
3480			$$.b2 = $3.b1;
3481			$$.w = $3.b2;
3482			$$.w2 = $3.w2;
3483		}
3484		| no RDR natpasslog {
3485			if ($1 && $3.b1) {
3486				yyerror("\"pass\" not valid with \"no\"");
3487				YYERROR;
3488			}
3489			if ($1)
3490				$$.b1 = PF_NORDR;
3491			else
3492				$$.b1 = PF_RDR;
3493			$$.b2 = $3.b1;
3494			$$.w = $3.b2;
3495			$$.w2 = $3.w2;
3496		}
3497		;
3498
3499natrule		: nataction interface af proto fromto tag tagged rtable
3500		    redirpool pool_opts opt_statelock
3501		{
3502			struct pf_rule	r;
3503
3504			if (check_rulestate(PFCTL_STATE_NAT))
3505				YYERROR;
3506
3507			memset(&r, 0, sizeof(r));
3508
3509			r.action = $1.b1;
3510			r.natpass = $1.b2;
3511			r.log = $1.w;
3512			r.logif = $1.w2;
3513			r.af = $3;
3514
3515			if (!r.af) {
3516				if ($5.src.host && $5.src.host->af &&
3517				    !$5.src.host->ifindex)
3518					r.af = $5.src.host->af;
3519				else if ($5.dst.host && $5.dst.host->af &&
3520				    !$5.dst.host->ifindex)
3521					r.af = $5.dst.host->af;
3522			}
3523
3524			if ($6 != NULL)
3525				if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) >=
3526				    PF_TAG_NAME_SIZE) {
3527					yyerror("tag too long, max %u chars",
3528					    PF_TAG_NAME_SIZE - 1);
3529					YYERROR;
3530				}
3531
3532			if ($7.name)
3533				if (strlcpy(r.match_tagname, $7.name,
3534				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
3535					yyerror("tag too long, max %u chars",
3536					    PF_TAG_NAME_SIZE - 1);
3537					YYERROR;
3538				}
3539			r.match_tag_not = $7.neg;
3540			r.rtableid = $8;
3541
3542			if (r.action == PF_NONAT || r.action == PF_NORDR) {
3543				if ($9 != NULL) {
3544					yyerror("translation rule with 'no' "
3545					    "does not need '->'");
3546					YYERROR;
3547				}
3548			} else {
3549				if ($9 == NULL || $9->host == NULL) {
3550					yyerror("translation rule requires '-> "
3551					    "address'");
3552					YYERROR;
3553				}
3554				if (!r.af && ! $9->host->ifindex)
3555					r.af = $9->host->af;
3556
3557				remove_invalid_hosts(&$9->host, &r.af);
3558				if (invalid_redirect($9->host, r.af))
3559					YYERROR;
3560				if (check_netmask($9->host, r.af))
3561					YYERROR;
3562
3563				r.rpool.proxy_port[0] = ntohs($9->rport.a);
3564
3565				switch (r.action) {
3566				case PF_RDR:
3567					if (!$9->rport.b && $9->rport.t &&
3568					    $5.dst.port != NULL) {
3569						r.rpool.proxy_port[1] =
3570						    ntohs($9->rport.a) +
3571						    (ntohs(
3572						    $5.dst.port->port[1]) -
3573						    ntohs(
3574						    $5.dst.port->port[0]));
3575					} else
3576						r.rpool.proxy_port[1] =
3577						    ntohs($9->rport.b);
3578					break;
3579				case PF_NAT:
3580					r.rpool.proxy_port[1] =
3581					    ntohs($9->rport.b);
3582					if (!r.rpool.proxy_port[0] &&
3583					    !r.rpool.proxy_port[1]) {
3584						r.rpool.proxy_port[0] =
3585						    PF_NAT_PROXY_PORT_LOW;
3586						r.rpool.proxy_port[1] =
3587						    PF_NAT_PROXY_PORT_HIGH;
3588					} else if (!r.rpool.proxy_port[1])
3589						r.rpool.proxy_port[1] =
3590						    r.rpool.proxy_port[0];
3591					break;
3592				default:
3593					break;
3594				}
3595
3596				r.rpool.opts = $10.type;
3597				if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
3598				    PF_POOL_NONE && ($9->host->next != NULL ||
3599				    $9->host->addr.type == PF_ADDR_TABLE ||
3600				    DYNIF_MULTIADDR($9->host->addr)))
3601					r.rpool.opts = PF_POOL_ROUNDROBIN;
3602				if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
3603				    PF_POOL_ROUNDROBIN &&
3604				    disallow_table($9->host, "tables are only "
3605				    "supported in round-robin redirection "
3606				    "pools"))
3607					YYERROR;
3608				if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
3609				    PF_POOL_ROUNDROBIN &&
3610				    disallow_alias($9->host, "interface (%s) "
3611				    "is only supported in round-robin "
3612				    "redirection pools"))
3613					YYERROR;
3614				if ($9->host->next != NULL) {
3615					if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
3616					    PF_POOL_ROUNDROBIN) {
3617						yyerror("only round-robin "
3618						    "valid for multiple "
3619						    "redirection addresses");
3620						YYERROR;
3621					}
3622				}
3623			}
3624
3625			if ($10.key != NULL)
3626				memcpy(&r.rpool.key, $10.key,
3627				    sizeof(struct pf_poolhashkey));
3628
3629			 if ($10.opts)
3630				r.rpool.opts |= $10.opts;
3631
3632			if ($10.staticport) {
3633				if (r.action != PF_NAT) {
3634					yyerror("the 'static-port' option is "
3635					    "only valid with nat rules");
3636					YYERROR;
3637				}
3638				if (r.rpool.proxy_port[0] !=
3639				    PF_NAT_PROXY_PORT_LOW &&
3640				    r.rpool.proxy_port[1] !=
3641				    PF_NAT_PROXY_PORT_HIGH) {
3642					yyerror("the 'static-port' option can't"
3643					    " be used when specifying a port"
3644					    " range");
3645					YYERROR;
3646				}
3647				r.rpool.proxy_port[0] = 0;
3648				r.rpool.proxy_port[1] = 0;
3649			}
3650
3651			if ($11 == NULL)
3652				r.rule_flag |= default_statelock;
3653			else {
3654				r.rule_flag |= $11->data.statelock;
3655				free($11);
3656			}
3657
3658			expand_rule(&r, $2, $9 == NULL ? NULL : $9->host, $4,
3659			    $5.src_os, $5.src.host, $5.src.port, $5.dst.host,
3660			    $5.dst.port, 0, 0, 0, "");
3661			free($9);
3662		}
3663		;
3664
3665binatrule	: no BINAT natpasslog interface af proto FROM host TO ipspec tag
3666		    tagged rtable redirection
3667		{
3668			struct pf_rule		binat;
3669			struct pf_pooladdr	*pa;
3670
3671			if (check_rulestate(PFCTL_STATE_NAT))
3672				YYERROR;
3673			if (disallow_urpf_failed($10, "\"urpf-failed\" is not "
3674			    "permitted as a binat destination"))
3675				YYERROR;
3676
3677			memset(&binat, 0, sizeof(binat));
3678
3679			if ($1 && $3.b1) {
3680				yyerror("\"pass\" not valid with \"no\"");
3681				YYERROR;
3682			}
3683			if ($1)
3684				binat.action = PF_NOBINAT;
3685			else
3686				binat.action = PF_BINAT;
3687			binat.natpass = $3.b1;
3688			binat.log = $3.b2;
3689			binat.logif = $3.w2;
3690			binat.af = $5;
3691			if (!binat.af && $8 != NULL && $8->af)
3692				binat.af = $8->af;
3693			if (!binat.af && $10 != NULL && $10->af)
3694				binat.af = $10->af;
3695
3696			if (!binat.af && $14 != NULL && $14->host)
3697				binat.af = $14->host->af;
3698			if (!binat.af) {
3699				yyerror("address family (inet/inet6) "
3700				    "undefined");
3701				YYERROR;
3702			}
3703
3704			if ($4 != NULL) {
3705				memcpy(binat.ifname, $4->ifname,
3706				    sizeof(binat.ifname));
3707				binat.ifnot = $4->not;
3708				free($4);
3709			}
3710
3711			if ($11 != NULL)
3712				if (strlcpy(binat.tagname, $11,
3713				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
3714					yyerror("tag too long, max %u chars",
3715					    PF_TAG_NAME_SIZE - 1);
3716					YYERROR;
3717				}
3718			if ($12.name)
3719				if (strlcpy(binat.match_tagname, $12.name,
3720				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
3721					yyerror("tag too long, max %u chars",
3722					    PF_TAG_NAME_SIZE - 1);
3723					YYERROR;
3724				}
3725			binat.match_tag_not = $12.neg;
3726			binat.rtableid = $13;
3727
3728			if ($6 != NULL) {
3729				binat.proto = $6->proto;
3730				free($6);
3731			}
3732
3733			if ($8 != NULL && disallow_table($8, "invalid use of "
3734			    "table <%s> as the source address of a binat rule"))
3735				YYERROR;
3736			if ($8 != NULL && disallow_alias($8, "invalid use of "
3737			    "interface (%s) as the source address of a binat "
3738			    "rule"))
3739				YYERROR;
3740			if ($14 != NULL && $14->host != NULL && disallow_table(
3741			    $14->host, "invalid use of table <%s> as the "
3742			    "redirect address of a binat rule"))
3743				YYERROR;
3744			if ($14 != NULL && $14->host != NULL && disallow_alias(
3745			    $14->host, "invalid use of interface (%s) as the "
3746			    "redirect address of a binat rule"))
3747				YYERROR;
3748
3749			if ($8 != NULL) {
3750				if ($8->next) {
3751					yyerror("multiple binat ip addresses");
3752					YYERROR;
3753				}
3754				if ($8->addr.type == PF_ADDR_DYNIFTL)
3755					$8->af = binat.af;
3756				if ($8->af != binat.af) {
3757					yyerror("binat ip versions must match");
3758					YYERROR;
3759				}
3760				if (check_netmask($8, binat.af))
3761					YYERROR;
3762				memcpy(&binat.src.addr, &$8->addr,
3763				    sizeof(binat.src.addr));
3764				free($8);
3765			}
3766			if ($10 != NULL) {
3767				if ($10->next) {
3768					yyerror("multiple binat ip addresses");
3769					YYERROR;
3770				}
3771				if ($10->af != binat.af && $10->af) {
3772					yyerror("binat ip versions must match");
3773					YYERROR;
3774				}
3775				if (check_netmask($10, binat.af))
3776					YYERROR;
3777				memcpy(&binat.dst.addr, &$10->addr,
3778				    sizeof(binat.dst.addr));
3779				binat.dst.neg = $10->not;
3780				free($10);
3781			}
3782
3783			if (binat.action == PF_NOBINAT) {
3784				if ($14 != NULL) {
3785					yyerror("'no binat' rule does not need"
3786					    " '->'");
3787					YYERROR;
3788				}
3789			} else {
3790				if ($14 == NULL || $14->host == NULL) {
3791					yyerror("'binat' rule requires"
3792					    " '-> address'");
3793					YYERROR;
3794				}
3795
3796				remove_invalid_hosts(&$14->host, &binat.af);
3797				if (invalid_redirect($14->host, binat.af))
3798					YYERROR;
3799				if ($14->host->next != NULL) {
3800					yyerror("binat rule must redirect to "
3801					    "a single address");
3802					YYERROR;
3803				}
3804				if (check_netmask($14->host, binat.af))
3805					YYERROR;
3806
3807				if (!PF_AZERO(&binat.src.addr.v.a.mask,
3808				    binat.af) &&
3809				    !PF_AEQ(&binat.src.addr.v.a.mask,
3810				    &$14->host->addr.v.a.mask, binat.af)) {
3811					yyerror("'binat' source mask and "
3812					    "redirect mask must be the same");
3813					YYERROR;
3814				}
3815
3816				TAILQ_INIT(&binat.rpool.list);
3817				pa = calloc(1, sizeof(struct pf_pooladdr));
3818				if (pa == NULL)
3819					err(1, "binat: calloc");
3820				pa->addr = $14->host->addr;
3821				pa->ifname[0] = 0;
3822				TAILQ_INSERT_TAIL(&binat.rpool.list,
3823				    pa, entries);
3824
3825				free($14);
3826			}
3827
3828			pfctl_add_rule(pf, &binat, "");
3829		}
3830		;
3831
3832tag		: /* empty */		{ $$ = NULL; }
3833		| TAG STRING		{ $$ = $2; }
3834		;
3835
3836tagged		: /* empty */		{ $$.neg = 0; $$.name = NULL; }
3837		| not TAGGED string	{ $$.neg = $1; $$.name = $3; }
3838		;
3839
3840rtable		: /* empty */		{ $$ = -1; }
3841		| RTABLE number		{
3842			if ($2 > RT_TABLEID_MAX || $2 < 0) {
3843				yyerror("invalid rtable id");
3844				YYERROR;
3845			}
3846			$$ = $2;
3847		}
3848		;
3849
3850route_host	: STRING			{
3851			$$ = calloc(1, sizeof(struct node_host));
3852			if ($$ == NULL)
3853				err(1, "route_host: calloc");
3854			$$->ifname = $1;
3855			set_ipmask($$, 128);
3856			$$->next = NULL;
3857			$$->tail = $$;
3858		}
3859		| '(' STRING host ')'		{
3860			$$ = $3;
3861			$$->ifname = $2;
3862		}
3863		;
3864
3865route_host_list	: route_host				{ $$ = $1; }
3866		| route_host_list comma route_host	{
3867			if ($1->af == 0)
3868				$1->af = $3->af;
3869			if ($1->af != $3->af) {
3870				yyerror("all pool addresses must be in the "
3871				    "same address family");
3872				YYERROR;
3873			}
3874			$1->tail->next = $3;
3875			$1->tail = $3->tail;
3876			$$ = $1;
3877		}
3878		;
3879
3880routespec	: route_host			{ $$ = $1; }
3881		| '{' route_host_list '}'	{ $$ = $2; }
3882		;
3883
3884route		: /* empty */			{
3885			$$.host = NULL;
3886			$$.rt = 0;
3887			$$.pool_opts = 0;
3888		}
3889		| FASTROUTE {
3890			$$.host = NULL;
3891			$$.rt = PF_FASTROUTE;
3892			$$.pool_opts = 0;
3893		}
3894		| ROUTETO routespec pool_opts {
3895			$$.host = $2;
3896			$$.rt = PF_ROUTETO;
3897			$$.pool_opts = $3.type | $3.opts;
3898			if ($3.key != NULL)
3899				$$.key = $3.key;
3900		}
3901		| REPLYTO routespec pool_opts {
3902			$$.host = $2;
3903			$$.rt = PF_REPLYTO;
3904			$$.pool_opts = $3.type | $3.opts;
3905			if ($3.key != NULL)
3906				$$.key = $3.key;
3907		}
3908		| DUPTO routespec pool_opts {
3909			$$.host = $2;
3910			$$.rt = PF_DUPTO;
3911			$$.pool_opts = $3.type | $3.opts;
3912			if ($3.key != NULL)
3913				$$.key = $3.key;
3914		}
3915		;
3916
3917timeout_spec	: STRING number
3918		{
3919			if (check_rulestate(PFCTL_STATE_OPTION)) {
3920				free($1);
3921				YYERROR;
3922			}
3923			if (pfctl_set_timeout(pf, $1, $2, 0) != 0) {
3924				yyerror("unknown timeout %s", $1);
3925				free($1);
3926				YYERROR;
3927			}
3928			free($1);
3929		}
3930		;
3931
3932timeout_list	: timeout_list comma timeout_spec
3933		| timeout_spec
3934		;
3935
3936limit_spec	: STRING number
3937		{
3938			if (check_rulestate(PFCTL_STATE_OPTION)) {
3939				free($1);
3940				YYERROR;
3941			}
3942			if (pfctl_set_limit(pf, $1, $2) != 0) {
3943				yyerror("unable to set limit %s %u", $1, $2);
3944				free($1);
3945				YYERROR;
3946			}
3947			free($1);
3948		}
3949		;
3950
3951limit_list	: limit_list comma limit_spec
3952		| limit_spec
3953		;
3954
3955comma		: ','
3956		| /* empty */
3957		;
3958
3959yesno		: NO			{ $$ = 0; }
3960		| STRING		{
3961			if (!strcmp($1, "yes"))
3962				$$ = 1;
3963			else {
3964				yyerror("invalid value '%s', expected 'yes' "
3965				    "or 'no'", $1);
3966				free($1);
3967				YYERROR;
3968			}
3969			free($1);
3970		}
3971		;
3972
3973unaryop		: '='		{ $$ = PF_OP_EQ; }
3974		| '!' '='	{ $$ = PF_OP_NE; }
3975		| '<' '='	{ $$ = PF_OP_LE; }
3976		| '<'		{ $$ = PF_OP_LT; }
3977		| '>' '='	{ $$ = PF_OP_GE; }
3978		| '>'		{ $$ = PF_OP_GT; }
3979		;
3980
3981%%
3982
3983int
3984yyerror(const char *fmt, ...)
3985{
3986	va_list		 ap;
3987	extern const char *infile;
3988
3989	errors = 1;
3990	va_start(ap, fmt);
3991	fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
3992	vfprintf(stderr, fmt, ap);
3993	fprintf(stderr, "\n");
3994	va_end(ap);
3995	return (0);
3996}
3997
3998int
3999disallow_table(struct node_host *h, const char *fmt)
4000{
4001	for (; h != NULL; h = h->next)
4002		if (h->addr.type == PF_ADDR_TABLE) {
4003			yyerror(fmt, h->addr.v.tblname);
4004			return (1);
4005		}
4006	return (0);
4007}
4008
4009int
4010disallow_urpf_failed(struct node_host *h, const char *fmt)
4011{
4012	for (; h != NULL; h = h->next)
4013		if (h->addr.type == PF_ADDR_URPFFAILED) {
4014			yyerror(fmt);
4015			return (1);
4016		}
4017	return (0);
4018}
4019
4020int
4021disallow_alias(struct node_host *h, const char *fmt)
4022{
4023	for (; h != NULL; h = h->next)
4024		if (DYNIF_MULTIADDR(h->addr)) {
4025			yyerror(fmt, h->addr.v.tblname);
4026			return (1);
4027		}
4028	return (0);
4029}
4030
4031int
4032rule_consistent(struct pf_rule *r, int anchor_call)
4033{
4034	int	problems = 0;
4035
4036	switch (r->action) {
4037	case PF_PASS:
4038	case PF_DROP:
4039	case PF_SCRUB:
4040	case PF_NOSCRUB:
4041		problems = filter_consistent(r, anchor_call);
4042		break;
4043	case PF_NAT:
4044	case PF_NONAT:
4045		problems = nat_consistent(r);
4046		break;
4047	case PF_RDR:
4048	case PF_NORDR:
4049		problems = rdr_consistent(r);
4050		break;
4051	case PF_BINAT:
4052	case PF_NOBINAT:
4053	default:
4054		break;
4055	}
4056	return (problems);
4057}
4058
4059int
4060filter_consistent(struct pf_rule *r, int anchor_call)
4061{
4062	int	problems = 0;
4063
4064	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
4065	    (r->src.port_op || r->dst.port_op)) {
4066		yyerror("port only applies to tcp/udp");
4067		problems++;
4068	}
4069	if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
4070	    (r->type || r->code)) {
4071		yyerror("icmp-type/code only applies to icmp");
4072		problems++;
4073	}
4074	if (!r->af && (r->type || r->code)) {
4075		yyerror("must indicate address family with icmp-type/code");
4076		problems++;
4077	}
4078	if (r->overload_tblname[0] &&
4079	    r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) {
4080		yyerror("'overload' requires 'max-src-conn' "
4081		    "or 'max-src-conn-rate'");
4082		problems++;
4083	}
4084	if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
4085	    (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
4086		yyerror("proto %s doesn't match address family %s",
4087		    r->proto == IPPROTO_ICMP ? "icmp" : "icmp6",
4088		    r->af == AF_INET ? "inet" : "inet6");
4089		problems++;
4090	}
4091	if (r->allow_opts && r->action != PF_PASS) {
4092		yyerror("allow-opts can only be specified for pass rules");
4093		problems++;
4094	}
4095	if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
4096	    r->dst.port_op || r->flagset || r->type || r->code)) {
4097		yyerror("fragments can be filtered only on IP header fields");
4098		problems++;
4099	}
4100	if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) {
4101		yyerror("return-rst can only be applied to TCP rules");
4102		problems++;
4103	}
4104	if (r->max_src_nodes && !(r->rule_flag & PFRULE_RULESRCTRACK)) {
4105		yyerror("max-src-nodes requires 'source-track rule'");
4106		problems++;
4107	}
4108	if (r->action == PF_DROP && r->keep_state) {
4109		yyerror("keep state on block rules doesn't make sense");
4110		problems++;
4111	}
4112	return (-problems);
4113}
4114
4115int
4116nat_consistent(struct pf_rule *r)
4117{
4118	return (0);	/* yeah! */
4119}
4120
4121int
4122rdr_consistent(struct pf_rule *r)
4123{
4124	int			 problems = 0;
4125
4126	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP) {
4127		if (r->src.port_op) {
4128			yyerror("src port only applies to tcp/udp");
4129			problems++;
4130		}
4131		if (r->dst.port_op) {
4132			yyerror("dst port only applies to tcp/udp");
4133			problems++;
4134		}
4135		if (r->rpool.proxy_port[0]) {
4136			yyerror("rpool port only applies to tcp/udp");
4137			problems++;
4138		}
4139	}
4140	if (r->dst.port_op &&
4141	    r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) {
4142		yyerror("invalid port operator for rdr destination port");
4143		problems++;
4144	}
4145	return (-problems);
4146}
4147
4148int
4149process_tabledef(char *name, struct table_opts *opts)
4150{
4151	struct pfr_buffer	 ab;
4152	struct node_tinit	*ti;
4153
4154	bzero(&ab, sizeof(ab));
4155	ab.pfrb_type = PFRB_ADDRS;
4156	SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) {
4157		if (ti->file)
4158			if (pfr_buf_load(&ab, ti->file, 0, append_addr)) {
4159				if (errno)
4160					yyerror("cannot load \"%s\": %s",
4161					    ti->file, strerror(errno));
4162				else
4163					yyerror("file \"%s\" contains bad data",
4164					    ti->file);
4165				goto _error;
4166			}
4167		if (ti->host)
4168			if (append_addr_host(&ab, ti->host, 0, 0)) {
4169				yyerror("cannot create address buffer: %s",
4170				    strerror(errno));
4171				goto _error;
4172			}
4173	}
4174	if (pf->opts & PF_OPT_VERBOSE)
4175		print_tabledef(name, opts->flags, opts->init_addr,
4176		    &opts->init_nodes);
4177	if (!(pf->opts & PF_OPT_NOACTION) &&
4178	    pfctl_define_table(name, opts->flags, opts->init_addr,
4179	    pf->anchor->name, &ab, pf->anchor->ruleset.tticket)) {
4180		yyerror("cannot define table %s: %s", name,
4181		    pfr_strerror(errno));
4182		goto _error;
4183	}
4184	pf->tdirty = 1;
4185	pfr_buf_clear(&ab);
4186	return (0);
4187_error:
4188	pfr_buf_clear(&ab);
4189	return (-1);
4190}
4191
4192struct keywords {
4193	const char	*k_name;
4194	int		 k_val;
4195};
4196
4197/* macro gore, but you should've seen the prior indentation nightmare... */
4198
4199#define FREE_LIST(T,r) \
4200	do { \
4201		T *p, *node = r; \
4202		while (node != NULL) { \
4203			p = node; \
4204			node = node->next; \
4205			free(p); \
4206		} \
4207	} while (0)
4208
4209#define LOOP_THROUGH(T,n,r,C) \
4210	do { \
4211		T *n; \
4212		if (r == NULL) { \
4213			r = calloc(1, sizeof(T)); \
4214			if (r == NULL) \
4215				err(1, "LOOP: calloc"); \
4216			r->next = NULL; \
4217		} \
4218		n = r; \
4219		while (n != NULL) { \
4220			do { \
4221				C; \
4222			} while (0); \
4223			n = n->next; \
4224		} \
4225	} while (0)
4226
4227void
4228expand_label_str(char *label, size_t len, const char *srch, const char *repl)
4229{
4230	char *tmp;
4231	char *p, *q;
4232
4233	if ((tmp = calloc(1, len)) == NULL)
4234		err(1, "expand_label_str: calloc");
4235	p = q = label;
4236	while ((q = strstr(p, srch)) != NULL) {
4237		*q = '\0';
4238		if ((strlcat(tmp, p, len) >= len) ||
4239		    (strlcat(tmp, repl, len) >= len))
4240			errx(1, "expand_label: label too long");
4241		q += strlen(srch);
4242		p = q;
4243	}
4244	if (strlcat(tmp, p, len) >= len)
4245		errx(1, "expand_label: label too long");
4246	strlcpy(label, tmp, len);	/* always fits */
4247	free(tmp);
4248}
4249
4250void
4251expand_label_if(const char *name, char *label, size_t len, const char *ifname)
4252{
4253	if (strstr(label, name) != NULL) {
4254		if (!*ifname)
4255			expand_label_str(label, len, name, "any");
4256		else
4257			expand_label_str(label, len, name, ifname);
4258	}
4259}
4260
4261void
4262expand_label_addr(const char *name, char *label, size_t len, sa_family_t af,
4263    struct node_host *h)
4264{
4265	char tmp[64], tmp_not[66];
4266
4267	if (strstr(label, name) != NULL) {
4268		switch (h->addr.type) {
4269		case PF_ADDR_DYNIFTL:
4270			snprintf(tmp, sizeof(tmp), "(%s)", h->addr.v.ifname);
4271			break;
4272		case PF_ADDR_TABLE:
4273			snprintf(tmp, sizeof(tmp), "<%s>", h->addr.v.tblname);
4274			break;
4275		case PF_ADDR_NOROUTE:
4276			snprintf(tmp, sizeof(tmp), "no-route");
4277			break;
4278		case PF_ADDR_URPFFAILED:
4279			snprintf(tmp, sizeof(tmp), "urpf-failed");
4280			break;
4281		case PF_ADDR_ADDRMASK:
4282			if (!af || (PF_AZERO(&h->addr.v.a.addr, af) &&
4283			    PF_AZERO(&h->addr.v.a.mask, af)))
4284				snprintf(tmp, sizeof(tmp), "any");
4285			else {
4286				char	a[48];
4287				int	bits;
4288
4289				if (inet_ntop(af, &h->addr.v.a.addr, a,
4290				    sizeof(a)) == NULL)
4291					snprintf(tmp, sizeof(tmp), "?");
4292				else {
4293					bits = unmask(&h->addr.v.a.mask, af);
4294					if ((af == AF_INET && bits < 32) ||
4295					    (af == AF_INET6 && bits < 128))
4296						snprintf(tmp, sizeof(tmp),
4297						    "%s/%d", a, bits);
4298					else
4299						snprintf(tmp, sizeof(tmp),
4300						    "%s", a);
4301				}
4302			}
4303			break;
4304		default:
4305			snprintf(tmp, sizeof(tmp), "?");
4306			break;
4307		}
4308
4309		if (h->not) {
4310			snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp);
4311			expand_label_str(label, len, name, tmp_not);
4312		} else
4313			expand_label_str(label, len, name, tmp);
4314	}
4315}
4316
4317void
4318expand_label_port(const char *name, char *label, size_t len,
4319    struct node_port *port)
4320{
4321	char	 a1[6], a2[6], op[13] = "";
4322
4323	if (strstr(label, name) != NULL) {
4324		snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0]));
4325		snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1]));
4326		if (!port->op)
4327			;
4328		else if (port->op == PF_OP_IRG)
4329			snprintf(op, sizeof(op), "%s><%s", a1, a2);
4330		else if (port->op == PF_OP_XRG)
4331			snprintf(op, sizeof(op), "%s<>%s", a1, a2);
4332		else if (port->op == PF_OP_EQ)
4333			snprintf(op, sizeof(op), "%s", a1);
4334		else if (port->op == PF_OP_NE)
4335			snprintf(op, sizeof(op), "!=%s", a1);
4336		else if (port->op == PF_OP_LT)
4337			snprintf(op, sizeof(op), "<%s", a1);
4338		else if (port->op == PF_OP_LE)
4339			snprintf(op, sizeof(op), "<=%s", a1);
4340		else if (port->op == PF_OP_GT)
4341			snprintf(op, sizeof(op), ">%s", a1);
4342		else if (port->op == PF_OP_GE)
4343			snprintf(op, sizeof(op), ">=%s", a1);
4344		expand_label_str(label, len, name, op);
4345	}
4346}
4347
4348void
4349expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto)
4350{
4351	struct protoent *pe;
4352	char n[4];
4353
4354	if (strstr(label, name) != NULL) {
4355		pe = getprotobynumber(proto);
4356		if (pe != NULL)
4357			expand_label_str(label, len, name, pe->p_name);
4358		else {
4359			snprintf(n, sizeof(n), "%u", proto);
4360			expand_label_str(label, len, name, n);
4361		}
4362	}
4363}
4364
4365void
4366expand_label_nr(const char *name, char *label, size_t len)
4367{
4368	char n[11];
4369
4370	if (strstr(label, name) != NULL) {
4371		snprintf(n, sizeof(n), "%u", pf->anchor->match);
4372		expand_label_str(label, len, name, n);
4373	}
4374}
4375
4376void
4377expand_label(char *label, size_t len, const char *ifname, sa_family_t af,
4378    struct node_host *src_host, struct node_port *src_port,
4379    struct node_host *dst_host, struct node_port *dst_port,
4380    u_int8_t proto)
4381{
4382	expand_label_if("$if", label, len, ifname);
4383	expand_label_addr("$srcaddr", label, len, af, src_host);
4384	expand_label_addr("$dstaddr", label, len, af, dst_host);
4385	expand_label_port("$srcport", label, len, src_port);
4386	expand_label_port("$dstport", label, len, dst_port);
4387	expand_label_proto("$proto", label, len, proto);
4388	expand_label_nr("$nr", label, len);
4389}
4390
4391int
4392expand_altq(struct pf_altq *a, struct node_if *interfaces,
4393    struct node_queue *nqueues, struct node_queue_bw bwspec,
4394    struct node_queue_opt *opts)
4395{
4396	struct pf_altq		 pa, pb;
4397	char			 qname[PF_QNAME_SIZE];
4398	struct node_queue	*n;
4399	struct node_queue_bw	 bw;
4400	int			 errs = 0;
4401
4402	if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
4403		FREE_LIST(struct node_if, interfaces);
4404		FREE_LIST(struct node_queue, nqueues);
4405		return (0);
4406	}
4407
4408	LOOP_THROUGH(struct node_if, interface, interfaces,
4409		memcpy(&pa, a, sizeof(struct pf_altq));
4410		if (strlcpy(pa.ifname, interface->ifname,
4411		    sizeof(pa.ifname)) >= sizeof(pa.ifname))
4412			errx(1, "expand_altq: strlcpy");
4413
4414		if (interface->not) {
4415			yyerror("altq on ! <interface> is not supported");
4416			errs++;
4417		} else {
4418			if (eval_pfaltq(pf, &pa, &bwspec, opts))
4419				errs++;
4420			else
4421				if (pfctl_add_altq(pf, &pa))
4422					errs++;
4423
4424			if (pf->opts & PF_OPT_VERBOSE) {
4425				print_altq(&pf->paltq->altq, 0,
4426				    &bwspec, opts);
4427				if (nqueues && nqueues->tail) {
4428					printf("queue { ");
4429					LOOP_THROUGH(struct node_queue, queue,
4430					    nqueues,
4431						printf("%s ",
4432						    queue->queue);
4433					);
4434					printf("}");
4435				}
4436				printf("\n");
4437			}
4438
4439			if (pa.scheduler == ALTQT_CBQ ||
4440			    pa.scheduler == ALTQT_HFSC) {
4441				/* now create a root queue */
4442				memset(&pb, 0, sizeof(struct pf_altq));
4443				if (strlcpy(qname, "root_", sizeof(qname)) >=
4444				    sizeof(qname))
4445					errx(1, "expand_altq: strlcpy");
4446				if (strlcat(qname, interface->ifname,
4447				    sizeof(qname)) >= sizeof(qname))
4448					errx(1, "expand_altq: strlcat");
4449				if (strlcpy(pb.qname, qname,
4450				    sizeof(pb.qname)) >= sizeof(pb.qname))
4451					errx(1, "expand_altq: strlcpy");
4452				if (strlcpy(pb.ifname, interface->ifname,
4453				    sizeof(pb.ifname)) >= sizeof(pb.ifname))
4454					errx(1, "expand_altq: strlcpy");
4455				pb.qlimit = pa.qlimit;
4456				pb.scheduler = pa.scheduler;
4457				bw.bw_absolute = pa.ifbandwidth;
4458				bw.bw_percent = 0;
4459				if (eval_pfqueue(pf, &pb, &bw, opts))
4460					errs++;
4461				else
4462					if (pfctl_add_altq(pf, &pb))
4463						errs++;
4464			}
4465
4466			LOOP_THROUGH(struct node_queue, queue, nqueues,
4467				n = calloc(1, sizeof(struct node_queue));
4468				if (n == NULL)
4469					err(1, "expand_altq: calloc");
4470				if (pa.scheduler == ALTQT_CBQ ||
4471				    pa.scheduler == ALTQT_HFSC)
4472					if (strlcpy(n->parent, qname,
4473					    sizeof(n->parent)) >=
4474					    sizeof(n->parent))
4475						errx(1, "expand_altq: strlcpy");
4476				if (strlcpy(n->queue, queue->queue,
4477				    sizeof(n->queue)) >= sizeof(n->queue))
4478					errx(1, "expand_altq: strlcpy");
4479				if (strlcpy(n->ifname, interface->ifname,
4480				    sizeof(n->ifname)) >= sizeof(n->ifname))
4481					errx(1, "expand_altq: strlcpy");
4482				n->scheduler = pa.scheduler;
4483				n->next = NULL;
4484				n->tail = n;
4485				if (queues == NULL)
4486					queues = n;
4487				else {
4488					queues->tail->next = n;
4489					queues->tail = n;
4490				}
4491			);
4492		}
4493	);
4494	FREE_LIST(struct node_if, interfaces);
4495	FREE_LIST(struct node_queue, nqueues);
4496
4497	return (errs);
4498}
4499
4500int
4501expand_queue(struct pf_altq *a, struct node_if *interfaces,
4502    struct node_queue *nqueues, struct node_queue_bw bwspec,
4503    struct node_queue_opt *opts)
4504{
4505	struct node_queue	*n, *nq;
4506	struct pf_altq		 pa;
4507	u_int8_t		 found = 0;
4508	u_int8_t		 errs = 0;
4509
4510	if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
4511		FREE_LIST(struct node_queue, nqueues);
4512		return (0);
4513	}
4514
4515	if (queues == NULL) {
4516		yyerror("queue %s has no parent", a->qname);
4517		FREE_LIST(struct node_queue, nqueues);
4518		return (1);
4519	}
4520
4521	LOOP_THROUGH(struct node_if, interface, interfaces,
4522		LOOP_THROUGH(struct node_queue, tqueue, queues,
4523			if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE) &&
4524			    (interface->ifname[0] == 0 ||
4525			    (!interface->not && !strncmp(interface->ifname,
4526			    tqueue->ifname, IFNAMSIZ)) ||
4527			    (interface->not && strncmp(interface->ifname,
4528			    tqueue->ifname, IFNAMSIZ)))) {
4529				/* found ourself in queues */
4530				found++;
4531
4532				memcpy(&pa, a, sizeof(struct pf_altq));
4533
4534				if (pa.scheduler != ALTQT_NONE &&
4535				    pa.scheduler != tqueue->scheduler) {
4536					yyerror("exactly one scheduler type "
4537					    "per interface allowed");
4538					errs++;
4539					goto out;
4540				}
4541				pa.scheduler = tqueue->scheduler;
4542
4543				/* scheduler dependent error checking */
4544				switch (pa.scheduler) {
4545				case ALTQT_PRIQ:
4546					if (nqueues != NULL) {
4547						yyerror("priq queues cannot "
4548						    "have child queues");
4549						errs++;
4550						goto out;
4551					}
4552					if (bwspec.bw_absolute > 0 ||
4553					    bwspec.bw_percent < 100) {
4554						yyerror("priq doesn't take "
4555						    "bandwidth");
4556						errs++;
4557						goto out;
4558					}
4559					break;
4560				default:
4561					break;
4562				}
4563
4564				if (strlcpy(pa.ifname, tqueue->ifname,
4565				    sizeof(pa.ifname)) >= sizeof(pa.ifname))
4566					errx(1, "expand_queue: strlcpy");
4567				if (strlcpy(pa.parent, tqueue->parent,
4568				    sizeof(pa.parent)) >= sizeof(pa.parent))
4569					errx(1, "expand_queue: strlcpy");
4570
4571				if (eval_pfqueue(pf, &pa, &bwspec, opts))
4572					errs++;
4573				else
4574					if (pfctl_add_altq(pf, &pa))
4575						errs++;
4576
4577				for (nq = nqueues; nq != NULL; nq = nq->next) {
4578					if (!strcmp(a->qname, nq->queue)) {
4579						yyerror("queue cannot have "
4580						    "itself as child");
4581						errs++;
4582						continue;
4583					}
4584					n = calloc(1,
4585					    sizeof(struct node_queue));
4586					if (n == NULL)
4587						err(1, "expand_queue: calloc");
4588					if (strlcpy(n->parent, a->qname,
4589					    sizeof(n->parent)) >=
4590					    sizeof(n->parent))
4591						errx(1, "expand_queue strlcpy");
4592					if (strlcpy(n->queue, nq->queue,
4593					    sizeof(n->queue)) >=
4594					    sizeof(n->queue))
4595						errx(1, "expand_queue strlcpy");
4596					if (strlcpy(n->ifname, tqueue->ifname,
4597					    sizeof(n->ifname)) >=
4598					    sizeof(n->ifname))
4599						errx(1, "expand_queue strlcpy");
4600					n->scheduler = tqueue->scheduler;
4601					n->next = NULL;
4602					n->tail = n;
4603					if (queues == NULL)
4604						queues = n;
4605					else {
4606						queues->tail->next = n;
4607						queues->tail = n;
4608					}
4609				}
4610				if ((pf->opts & PF_OPT_VERBOSE) && (
4611				    (found == 1 && interface->ifname[0] == 0) ||
4612				    (found > 0 && interface->ifname[0] != 0))) {
4613					print_queue(&pf->paltq->altq, 0,
4614					    &bwspec, interface->ifname[0] != 0,
4615					    opts);
4616					if (nqueues && nqueues->tail) {
4617						printf("{ ");
4618						LOOP_THROUGH(struct node_queue,
4619						    queue, nqueues,
4620							printf("%s ",
4621							    queue->queue);
4622						);
4623						printf("}");
4624					}
4625					printf("\n");
4626				}
4627			}
4628		);
4629	);
4630
4631out:
4632	FREE_LIST(struct node_queue, nqueues);
4633	FREE_LIST(struct node_if, interfaces);
4634
4635	if (!found) {
4636		yyerror("queue %s has no parent", a->qname);
4637		errs++;
4638	}
4639
4640	if (errs)
4641		return (1);
4642	else
4643		return (0);
4644}
4645
4646void
4647expand_rule(struct pf_rule *r,
4648    struct node_if *interfaces, struct node_host *rpool_hosts,
4649    struct node_proto *protos, struct node_os *src_oses,
4650    struct node_host *src_hosts, struct node_port *src_ports,
4651    struct node_host *dst_hosts, struct node_port *dst_ports,
4652    struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types,
4653    const char *anchor_call)
4654{
4655	sa_family_t		 af = r->af;
4656	int			 added = 0, error = 0;
4657	char			 ifname[IF_NAMESIZE];
4658	char			 label[PF_RULE_LABEL_SIZE];
4659	char			 tagname[PF_TAG_NAME_SIZE];
4660	char			 match_tagname[PF_TAG_NAME_SIZE];
4661	struct pf_pooladdr	*pa;
4662	struct node_host	*h;
4663	u_int8_t		 flags, flagset, keep_state;
4664
4665	if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label))
4666		errx(1, "expand_rule: strlcpy");
4667	if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
4668		errx(1, "expand_rule: strlcpy");
4669	if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
4670	    sizeof(match_tagname))
4671		errx(1, "expand_rule: strlcpy");
4672	flags = r->flags;
4673	flagset = r->flagset;
4674	keep_state = r->keep_state;
4675
4676	LOOP_THROUGH(struct node_if, interface, interfaces,
4677	LOOP_THROUGH(struct node_proto, proto, protos,
4678	LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
4679	LOOP_THROUGH(struct node_host, src_host, src_hosts,
4680	LOOP_THROUGH(struct node_port, src_port, src_ports,
4681	LOOP_THROUGH(struct node_os, src_os, src_oses,
4682	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
4683	LOOP_THROUGH(struct node_port, dst_port, dst_ports,
4684	LOOP_THROUGH(struct node_uid, uid, uids,
4685	LOOP_THROUGH(struct node_gid, gid, gids,
4686
4687		r->af = af;
4688		/* for link-local IPv6 address, interface must match up */
4689		if ((r->af && src_host->af && r->af != src_host->af) ||
4690		    (r->af && dst_host->af && r->af != dst_host->af) ||
4691		    (src_host->af && dst_host->af &&
4692		    src_host->af != dst_host->af) ||
4693		    (src_host->ifindex && dst_host->ifindex &&
4694		    src_host->ifindex != dst_host->ifindex) ||
4695		    (src_host->ifindex && *interface->ifname &&
4696		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
4697		    (dst_host->ifindex && *interface->ifname &&
4698		    dst_host->ifindex != if_nametoindex(interface->ifname)))
4699			continue;
4700		if (!r->af && src_host->af)
4701			r->af = src_host->af;
4702		else if (!r->af && dst_host->af)
4703			r->af = dst_host->af;
4704
4705		if (*interface->ifname)
4706			strlcpy(r->ifname, interface->ifname,
4707			    sizeof(r->ifname));
4708		else if (if_indextoname(src_host->ifindex, ifname))
4709			strlcpy(r->ifname, ifname, sizeof(r->ifname));
4710		else if (if_indextoname(dst_host->ifindex, ifname))
4711			strlcpy(r->ifname, ifname, sizeof(r->ifname));
4712		else
4713			memset(r->ifname, '\0', sizeof(r->ifname));
4714
4715		if (strlcpy(r->label, label, sizeof(r->label)) >=
4716		    sizeof(r->label))
4717			errx(1, "expand_rule: strlcpy");
4718		if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
4719		    sizeof(r->tagname))
4720			errx(1, "expand_rule: strlcpy");
4721		if (strlcpy(r->match_tagname, match_tagname,
4722		    sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
4723			errx(1, "expand_rule: strlcpy");
4724		expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af,
4725		    src_host, src_port, dst_host, dst_port, proto->proto);
4726		expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af,
4727		    src_host, src_port, dst_host, dst_port, proto->proto);
4728		expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname,
4729		    r->af, src_host, src_port, dst_host, dst_port,
4730		    proto->proto);
4731
4732		error += check_netmask(src_host, r->af);
4733		error += check_netmask(dst_host, r->af);
4734
4735		r->ifnot = interface->not;
4736		r->proto = proto->proto;
4737		r->src.addr = src_host->addr;
4738		r->src.neg = src_host->not;
4739		r->src.port[0] = src_port->port[0];
4740		r->src.port[1] = src_port->port[1];
4741		r->src.port_op = src_port->op;
4742		r->dst.addr = dst_host->addr;
4743		r->dst.neg = dst_host->not;
4744		r->dst.port[0] = dst_port->port[0];
4745		r->dst.port[1] = dst_port->port[1];
4746		r->dst.port_op = dst_port->op;
4747		r->uid.op = uid->op;
4748		r->uid.uid[0] = uid->uid[0];
4749		r->uid.uid[1] = uid->uid[1];
4750		r->gid.op = gid->op;
4751		r->gid.gid[0] = gid->gid[0];
4752		r->gid.gid[1] = gid->gid[1];
4753		r->type = icmp_type->type;
4754		r->code = icmp_type->code;
4755
4756		if ((keep_state == PF_STATE_MODULATE ||
4757		    keep_state == PF_STATE_SYNPROXY) &&
4758		    r->proto && r->proto != IPPROTO_TCP)
4759			r->keep_state = PF_STATE_NORMAL;
4760		else
4761			r->keep_state = keep_state;
4762
4763		if (r->proto && r->proto != IPPROTO_TCP) {
4764			r->flags = 0;
4765			r->flagset = 0;
4766		} else {
4767			r->flags = flags;
4768			r->flagset = flagset;
4769		}
4770		if (icmp_type->proto && r->proto != icmp_type->proto) {
4771			yyerror("icmp-type mismatch");
4772			error++;
4773		}
4774
4775		if (src_os && src_os->os) {
4776			r->os_fingerprint = pfctl_get_fingerprint(src_os->os);
4777			if ((pf->opts & PF_OPT_VERBOSE2) &&
4778			    r->os_fingerprint == PF_OSFP_NOMATCH)
4779				fprintf(stderr,
4780				    "warning: unknown '%s' OS fingerprint\n",
4781				    src_os->os);
4782		} else {
4783			r->os_fingerprint = PF_OSFP_ANY;
4784		}
4785
4786		TAILQ_INIT(&r->rpool.list);
4787		for (h = rpool_hosts; h != NULL; h = h->next) {
4788			pa = calloc(1, sizeof(struct pf_pooladdr));
4789			if (pa == NULL)
4790				err(1, "expand_rule: calloc");
4791			pa->addr = h->addr;
4792			if (h->ifname != NULL) {
4793				if (strlcpy(pa->ifname, h->ifname,
4794				    sizeof(pa->ifname)) >=
4795				    sizeof(pa->ifname))
4796					errx(1, "expand_rule: strlcpy");
4797			} else
4798				pa->ifname[0] = 0;
4799			TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries);
4800		}
4801
4802		if (rule_consistent(r, anchor_call[0]) < 0 || error)
4803			yyerror("skipping rule due to errors");
4804		else {
4805			r->nr = pf->astack[pf->asd]->match++;
4806			pfctl_add_rule(pf, r, anchor_call);
4807			added++;
4808		}
4809
4810	))))))))));
4811
4812	FREE_LIST(struct node_if, interfaces);
4813	FREE_LIST(struct node_proto, protos);
4814	FREE_LIST(struct node_host, src_hosts);
4815	FREE_LIST(struct node_port, src_ports);
4816	FREE_LIST(struct node_os, src_oses);
4817	FREE_LIST(struct node_host, dst_hosts);
4818	FREE_LIST(struct node_port, dst_ports);
4819	FREE_LIST(struct node_uid, uids);
4820	FREE_LIST(struct node_gid, gids);
4821	FREE_LIST(struct node_icmp, icmp_types);
4822	FREE_LIST(struct node_host, rpool_hosts);
4823
4824	if (!added)
4825		yyerror("rule expands to no valid combination");
4826}
4827
4828int
4829expand_skip_interface(struct node_if *interfaces)
4830{
4831	int	errs = 0;
4832
4833	if (!interfaces || (!interfaces->next && !interfaces->not &&
4834	    !strcmp(interfaces->ifname, "none"))) {
4835		if (pf->opts & PF_OPT_VERBOSE)
4836			printf("set skip on none\n");
4837		errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0);
4838		return (errs);
4839	}
4840
4841	if (pf->opts & PF_OPT_VERBOSE)
4842		printf("set skip on {");
4843	LOOP_THROUGH(struct node_if, interface, interfaces,
4844		if (pf->opts & PF_OPT_VERBOSE)
4845			printf(" %s", interface->ifname);
4846		if (interface->not) {
4847			yyerror("skip on ! <interface> is not supported");
4848			errs++;
4849		} else
4850			errs += pfctl_set_interface_flags(pf,
4851			    interface->ifname, PFI_IFLAG_SKIP, 1);
4852	);
4853	if (pf->opts & PF_OPT_VERBOSE)
4854		printf(" }\n");
4855
4856	FREE_LIST(struct node_if, interfaces);
4857
4858	if (errs)
4859		return (1);
4860	else
4861		return (0);
4862}
4863
4864#undef FREE_LIST
4865#undef LOOP_THROUGH
4866
4867int
4868check_rulestate(int desired_state)
4869{
4870	if (require_order && (rulestate > desired_state)) {
4871		yyerror("Rules must be in order: options, normalization, "
4872		    "queueing, translation, filtering");
4873		return (1);
4874	}
4875	rulestate = desired_state;
4876	return (0);
4877}
4878
4879int
4880kw_cmp(const void *k, const void *e)
4881{
4882	return (strcmp(k, ((const struct keywords *)e)->k_name));
4883}
4884
4885int
4886lookup(char *s)
4887{
4888	/* this has to be sorted always */
4889	static const struct keywords keywords[] = {
4890		{ "all",		ALL},
4891		{ "allow-opts",		ALLOWOPTS},
4892		{ "altq",		ALTQ},
4893		{ "anchor",		ANCHOR},
4894		{ "antispoof",		ANTISPOOF},
4895		{ "any",		ANY},
4896		{ "bandwidth",		BANDWIDTH},
4897		{ "binat",		BINAT},
4898		{ "binat-anchor",	BINATANCHOR},
4899		{ "bitmask",		BITMASK},
4900		{ "block",		BLOCK},
4901		{ "block-policy",	BLOCKPOLICY},
4902		{ "cbq",		CBQ},
4903		{ "code",		CODE},
4904		{ "crop",		FRAGCROP},
4905		{ "debug",		DEBUG},
4906		{ "drop",		DROP},
4907		{ "drop-ovl",		FRAGDROP},
4908		{ "dup-to",		DUPTO},
4909		{ "fastroute",		FASTROUTE},
4910		{ "file",		FILENAME},
4911		{ "fingerprints",	FINGERPRINTS},
4912		{ "flags",		FLAGS},
4913		{ "floating",		FLOATING},
4914		{ "flush",		FLUSH},
4915		{ "for",		FOR},
4916		{ "fragment",		FRAGMENT},
4917		{ "from",		FROM},
4918		{ "global",		GLOBAL},
4919		{ "group",		GROUP},
4920		{ "hfsc",		HFSC},
4921		{ "hostid",		HOSTID},
4922		{ "icmp-type",		ICMPTYPE},
4923		{ "icmp6-type",		ICMP6TYPE},
4924		{ "if-bound",		IFBOUND},
4925		{ "in",			IN},
4926		{ "inet",		INET},
4927		{ "inet6",		INET6},
4928		{ "keep",		KEEP},
4929		{ "label",		LABEL},
4930		{ "limit",		LIMIT},
4931		{ "linkshare",		LINKSHARE},
4932		{ "load",		LOAD},
4933		{ "log",		LOG},
4934		{ "loginterface",	LOGINTERFACE},
4935		{ "max",		MAXIMUM},
4936		{ "max-mss",		MAXMSS},
4937		{ "max-src-conn",	MAXSRCCONN},
4938		{ "max-src-conn-rate",	MAXSRCCONNRATE},
4939		{ "max-src-nodes",	MAXSRCNODES},
4940		{ "max-src-states",	MAXSRCSTATES},
4941		{ "min-ttl",		MINTTL},
4942		{ "modulate",		MODULATE},
4943		{ "nat",		NAT},
4944		{ "nat-anchor",		NATANCHOR},
4945		{ "no",			NO},
4946		{ "no-df",		NODF},
4947		{ "no-route",		NOROUTE},
4948		{ "no-sync",		NOSYNC},
4949		{ "on",			ON},
4950		{ "optimization",	OPTIMIZATION},
4951		{ "os",			OS},
4952		{ "out",		OUT},
4953		{ "overload",		OVERLOAD},
4954		{ "pass",		PASS},
4955		{ "port",		PORT},
4956		{ "priority",		PRIORITY},
4957		{ "priq",		PRIQ},
4958		{ "probability",	PROBABILITY},
4959		{ "proto",		PROTO},
4960		{ "qlimit",		QLIMIT},
4961		{ "queue",		QUEUE},
4962		{ "quick",		QUICK},
4963		{ "random",		RANDOM},
4964		{ "random-id",		RANDOMID},
4965		{ "rdr",		RDR},
4966		{ "rdr-anchor",		RDRANCHOR},
4967		{ "realtime",		REALTIME},
4968		{ "reassemble",		REASSEMBLE},
4969		{ "reply-to",		REPLYTO},
4970		{ "require-order",	REQUIREORDER},
4971		{ "return",		RETURN},
4972		{ "return-icmp",	RETURNICMP},
4973		{ "return-icmp6",	RETURNICMP6},
4974		{ "return-rst",		RETURNRST},
4975		{ "round-robin",	ROUNDROBIN},
4976		{ "route",		ROUTE},
4977		{ "route-to",		ROUTETO},
4978		{ "rtable",		RTABLE},
4979		{ "rule",		RULE},
4980		{ "ruleset-optimization",	RULESET_OPTIMIZATION},
4981		{ "scrub",		SCRUB},
4982		{ "set",		SET},
4983		{ "skip",		SKIP},
4984		{ "source-hash",	SOURCEHASH},
4985		{ "source-track",	SOURCETRACK},
4986		{ "state",		STATE},
4987		{ "state-policy",	STATEPOLICY},
4988		{ "static-port",	STATICPORT},
4989		{ "sticky-address",	STICKYADDRESS},
4990		{ "synproxy",		SYNPROXY},
4991		{ "table",		TABLE},
4992		{ "tag",		TAG},
4993		{ "tagged",		TAGGED},
4994		{ "tbrsize",		TBRSIZE},
4995		{ "timeout",		TIMEOUT},
4996		{ "to",			TO},
4997		{ "tos",		TOS},
4998		{ "ttl",		TTL},
4999		{ "upperlimit",		UPPERLIMIT},
5000		{ "urpf-failed",	URPFFAILED},
5001		{ "user",		USER},
5002	};
5003	const struct keywords	*p;
5004
5005	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
5006	    sizeof(keywords[0]), kw_cmp);
5007
5008	if (p) {
5009		if (debug > 1)
5010			fprintf(stderr, "%s: %d\n", s, p->k_val);
5011		return (p->k_val);
5012	} else {
5013		if (debug > 1)
5014			fprintf(stderr, "string: %s\n", s);
5015		return (STRING);
5016	}
5017}
5018
5019#define MAXPUSHBACK	128
5020
5021char	*parsebuf;
5022int	 parseindex;
5023char	 pushback_buffer[MAXPUSHBACK];
5024int	 pushback_index = 0;
5025
5026int
5027lgetc(FILE *f)
5028{
5029	int	c, next;
5030
5031	if (parsebuf) {
5032		/* Read character from the parsebuffer instead of input. */
5033		if (parseindex >= 0) {
5034			c = parsebuf[parseindex++];
5035			if (c != '\0')
5036				return (c);
5037			parsebuf = NULL;
5038		} else
5039			parseindex++;
5040	}
5041
5042	if (pushback_index)
5043		return (pushback_buffer[--pushback_index]);
5044
5045	while ((c = getc(f)) == '\\') {
5046		next = getc(f);
5047		if (next != '\n') {
5048			c = next;
5049			break;
5050		}
5051		yylval.lineno = lineno;
5052		lineno++;
5053	}
5054	if (c == '\t' || c == ' ') {
5055		/* Compress blanks to a single space. */
5056		do {
5057			c = getc(f);
5058		} while (c == '\t' || c == ' ');
5059		ungetc(c, f);
5060		c = ' ';
5061	}
5062
5063	return (c);
5064}
5065
5066int
5067lungetc(int c)
5068{
5069	if (c == EOF)
5070		return (EOF);
5071	if (parsebuf) {
5072		parseindex--;
5073		if (parseindex >= 0)
5074			return (c);
5075	}
5076	if (pushback_index < MAXPUSHBACK-1)
5077		return (pushback_buffer[pushback_index++] = c);
5078	else
5079		return (EOF);
5080}
5081
5082int
5083findeol(void)
5084{
5085	int	c;
5086
5087	parsebuf = NULL;
5088	pushback_index = 0;
5089
5090	/* skip to either EOF or the first real EOL */
5091	while (1) {
5092		c = lgetc(fin);
5093		if (c == '\n') {
5094			lineno++;
5095			break;
5096		}
5097		if (c == EOF)
5098			break;
5099	}
5100	return (ERROR);
5101}
5102
5103int
5104yylex(void)
5105{
5106	char	 buf[8096];
5107	char	*p, *val;
5108	int	 endc, c, next;
5109	int	 token;
5110
5111top:
5112	p = buf;
5113	while ((c = lgetc(fin)) == ' ')
5114		; /* nothing */
5115
5116	yylval.lineno = lineno;
5117	if (c == '#')
5118		while ((c = lgetc(fin)) != '\n' && c != EOF)
5119			; /* nothing */
5120	if (c == '$' && parsebuf == NULL) {
5121		while (1) {
5122			if ((c = lgetc(fin)) == EOF)
5123				return (0);
5124
5125			if (p + 1 >= buf + sizeof(buf) - 1) {
5126				yyerror("string too long");
5127				return (findeol());
5128			}
5129			if (isalnum(c) || c == '_') {
5130				*p++ = (char)c;
5131				continue;
5132			}
5133			*p = '\0';
5134			lungetc(c);
5135			break;
5136		}
5137		val = symget(buf);
5138		if (val == NULL) {
5139			yyerror("macro '%s' not defined", buf);
5140			return (findeol());
5141		}
5142		parsebuf = val;
5143		parseindex = 0;
5144		goto top;
5145	}
5146
5147	switch (c) {
5148	case '\'':
5149	case '"':
5150		endc = c;
5151		while (1) {
5152			if ((c = lgetc(fin)) == EOF)
5153				return (0);
5154			if (c == endc) {
5155				*p = '\0';
5156				break;
5157			}
5158			if (c == '\n') {
5159				lineno++;
5160				continue;
5161			}
5162			if (p + 1 >= buf + sizeof(buf) - 1) {
5163				yyerror("string too long");
5164				return (findeol());
5165			}
5166			*p++ = (char)c;
5167		}
5168		yylval.v.string = strdup(buf);
5169		if (yylval.v.string == NULL)
5170			err(1, "yylex: strdup");
5171		return (STRING);
5172	case '<':
5173		next = lgetc(fin);
5174		if (next == '>') {
5175			yylval.v.i = PF_OP_XRG;
5176			return (PORTBINARY);
5177		}
5178		lungetc(next);
5179		break;
5180	case '>':
5181		next = lgetc(fin);
5182		if (next == '<') {
5183			yylval.v.i = PF_OP_IRG;
5184			return (PORTBINARY);
5185		}
5186		lungetc(next);
5187		break;
5188	case '-':
5189		next = lgetc(fin);
5190		if (next == '>')
5191			return (ARROW);
5192		lungetc(next);
5193		break;
5194	}
5195
5196#define allowed_in_string(x) \
5197	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
5198	x != '{' && x != '}' && x != '<' && x != '>' && \
5199	x != '!' && x != '=' && x != '/' && x != '#' && \
5200	x != ','))
5201
5202	if (isalnum(c) || c == ':' || c == '_') {
5203		do {
5204			*p++ = c;
5205			if ((unsigned)(p-buf) >= sizeof(buf)) {
5206				yyerror("string too long");
5207				return (findeol());
5208			}
5209		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
5210		lungetc(c);
5211		*p = '\0';
5212		if ((token = lookup(buf)) == STRING)
5213			if ((yylval.v.string = strdup(buf)) == NULL)
5214				err(1, "yylex: strdup");
5215		return (token);
5216	}
5217	if (c == '\n') {
5218		yylval.lineno = lineno;
5219		lineno++;
5220	}
5221	if (c == EOF)
5222		return (0);
5223	return (c);
5224}
5225
5226int
5227parse_rules(FILE *input, struct pfctl *xpf)
5228{
5229	struct sym	*sym, *next;
5230
5231	fin = input;
5232	pf = xpf;
5233	lineno = 1;
5234	errors = 0;
5235	rulestate = PFCTL_STATE_NONE;
5236	returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
5237	returnicmp6default =
5238	    (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
5239	blockpolicy = PFRULE_DROP;
5240	require_order = 1;
5241
5242	yyparse();
5243
5244	/* Free macros and check which have not been used. */
5245	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
5246		next = TAILQ_NEXT(sym, entries);
5247		if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used)
5248			fprintf(stderr, "warning: macro '%s' not "
5249			    "used\n", sym->nam);
5250		free(sym->nam);
5251		free(sym->val);
5252		TAILQ_REMOVE(&symhead, sym, entries);
5253		free(sym);
5254	}
5255
5256	return (errors ? -1 : 0);
5257}
5258
5259/*
5260 * Over-designed efficiency is a French and German concept, so how about
5261 * we wait until they discover this ugliness and make it all fancy.
5262 */
5263int
5264symset(const char *nam, const char *val, int persist)
5265{
5266	struct sym	*sym;
5267
5268	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
5269	    sym = TAILQ_NEXT(sym, entries))
5270		;	/* nothing */
5271
5272	if (sym != NULL) {
5273		if (sym->persist == 1)
5274			return (0);
5275		else {
5276			free(sym->nam);
5277			free(sym->val);
5278			TAILQ_REMOVE(&symhead, sym, entries);
5279			free(sym);
5280		}
5281	}
5282	if ((sym = calloc(1, sizeof(*sym))) == NULL)
5283		return (-1);
5284
5285	sym->nam = strdup(nam);
5286	if (sym->nam == NULL) {
5287		free(sym);
5288		return (-1);
5289	}
5290	sym->val = strdup(val);
5291	if (sym->val == NULL) {
5292		free(sym->nam);
5293		free(sym);
5294		return (-1);
5295	}
5296	sym->used = 0;
5297	sym->persist = persist;
5298	TAILQ_INSERT_TAIL(&symhead, sym, entries);
5299	return (0);
5300}
5301
5302int
5303pfctl_cmdline_symset(char *s)
5304{
5305	char	*sym, *val;
5306	int	 ret;
5307
5308	if ((val = strrchr(s, '=')) == NULL)
5309		return (-1);
5310
5311	if ((sym = malloc(strlen(s) - strlen(val) + 1)) == NULL)
5312		err(1, "pfctl_cmdline_symset: malloc");
5313
5314	strlcpy(sym, s, strlen(s) - strlen(val) + 1);
5315
5316	ret = symset(sym, val + 1, 1);
5317	free(sym);
5318
5319	return (ret);
5320}
5321
5322char *
5323symget(const char *nam)
5324{
5325	struct sym	*sym;
5326
5327	TAILQ_FOREACH(sym, &symhead, entries)
5328		if (strcmp(nam, sym->nam) == 0) {
5329			sym->used = 1;
5330			return (sym->val);
5331		}
5332	return (NULL);
5333}
5334
5335void
5336mv_rules(struct pf_ruleset *src, struct pf_ruleset *dst)
5337{
5338	int i;
5339	struct pf_rule *r;
5340
5341	for (i = 0; i < PF_RULESET_MAX; ++i) {
5342		while ((r = TAILQ_FIRST(src->rules[i].active.ptr))
5343		    != NULL) {
5344			TAILQ_REMOVE(src->rules[i].active.ptr, r, entries);
5345			TAILQ_INSERT_TAIL(dst->rules[i].active.ptr, r, entries);
5346			dst->anchor->match++;
5347		}
5348		src->anchor->match = 0;
5349		while ((r = TAILQ_FIRST(src->rules[i].inactive.ptr))
5350		    != NULL) {
5351			TAILQ_REMOVE(src->rules[i].inactive.ptr, r, entries);
5352			TAILQ_INSERT_TAIL(dst->rules[i].inactive.ptr,
5353				r, entries);
5354		}
5355	}
5356}
5357
5358void
5359decide_address_family(struct node_host *n, sa_family_t *af)
5360{
5361	if (*af != 0 || n == NULL)
5362		return;
5363	*af = n->af;
5364	while ((n = n->next) != NULL) {
5365		if (n->af != *af) {
5366			*af = 0;
5367			return;
5368		}
5369	}
5370}
5371
5372void
5373remove_invalid_hosts(struct node_host **nh, sa_family_t *af)
5374{
5375	struct node_host	*n = *nh, *prev = NULL;
5376
5377	while (n != NULL) {
5378		if (*af && n->af && n->af != *af) {
5379			/* unlink and free n */
5380			struct node_host *next = n->next;
5381
5382			/* adjust tail pointer */
5383			if (n == (*nh)->tail)
5384				(*nh)->tail = prev;
5385			/* adjust previous node's next pointer */
5386			if (prev == NULL)
5387				*nh = next;
5388			else
5389				prev->next = next;
5390			/* free node */
5391			if (n->ifname != NULL)
5392				free(n->ifname);
5393			free(n);
5394			n = next;
5395		} else {
5396			if (n->af && !*af)
5397				*af = n->af;
5398			prev = n;
5399			n = n->next;
5400		}
5401	}
5402}
5403
5404int
5405invalid_redirect(struct node_host *nh, sa_family_t af)
5406{
5407	if (!af) {
5408		struct node_host *n;
5409
5410		/* tables and dyniftl are ok without an address family */
5411		for (n = nh; n != NULL; n = n->next) {
5412			if (n->addr.type != PF_ADDR_TABLE &&
5413			    n->addr.type != PF_ADDR_DYNIFTL) {
5414				yyerror("address family not given and "
5415				    "translation address expands to multiple "
5416				    "address families");
5417				return (1);
5418			}
5419		}
5420	}
5421	if (nh == NULL) {
5422		yyerror("no translation address with matching address family "
5423		    "found.");
5424		return (1);
5425	}
5426	return (0);
5427}
5428
5429int
5430atoul(char *s, u_long *ulvalp)
5431{
5432	u_long	 ulval;
5433	char	*ep;
5434
5435	errno = 0;
5436	ulval = strtoul(s, &ep, 0);
5437	if (s[0] == '\0' || *ep != '\0')
5438		return (-1);
5439	if (errno == ERANGE && ulval == ULONG_MAX)
5440		return (-1);
5441	*ulvalp = ulval;
5442	return (0);
5443}
5444
5445int
5446getservice(char *n)
5447{
5448	struct servent	*s;
5449	u_long		 ulval;
5450
5451	if (atoul(n, &ulval) == 0) {
5452		if (ulval > 65535) {
5453			yyerror("illegal port value %lu", ulval);
5454			return (-1);
5455		}
5456		return (htons(ulval));
5457	} else {
5458		s = getservbyname(n, "tcp");
5459		if (s == NULL)
5460			s = getservbyname(n, "udp");
5461		if (s == NULL) {
5462			yyerror("unknown port %s", n);
5463			return (-1);
5464		}
5465		return (s->s_port);
5466	}
5467}
5468
5469int
5470rule_label(struct pf_rule *r, char *s)
5471{
5472	if (s) {
5473		if (strlcpy(r->label, s, sizeof(r->label)) >=
5474		    sizeof(r->label)) {
5475			yyerror("rule label too long (max %d chars)",
5476			    sizeof(r->label)-1);
5477			return (-1);
5478		}
5479	}
5480	return (0);
5481}
5482
5483u_int16_t
5484parseicmpspec(char *w, sa_family_t af)
5485{
5486	const struct icmpcodeent	*p;
5487	u_long				 ulval;
5488	u_int8_t			 icmptype;
5489
5490	if (af == AF_INET)
5491		icmptype = returnicmpdefault >> 8;
5492	else
5493		icmptype = returnicmp6default >> 8;
5494
5495	if (atoul(w, &ulval) == -1) {
5496		if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
5497			yyerror("unknown icmp code %s", w);
5498			return (0);
5499		}
5500		ulval = p->code;
5501	}
5502	if (ulval > 255) {
5503		yyerror("invalid icmp code %lu", ulval);
5504		return (0);
5505	}
5506	return (icmptype << 8 | ulval);
5507}
5508
5509int
5510pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans)
5511{
5512	struct loadanchors	*la;
5513	FILE			*fin;
5514
5515	TAILQ_FOREACH(la, &loadanchorshead, entries) {
5516		if (pf->opts & PF_OPT_VERBOSE)
5517			fprintf(stderr, "\nLoading anchor %s from %s\n",
5518			    la->anchorname, la->filename);
5519		if ((fin = pfctl_fopen(la->filename, "r")) == NULL) {
5520			warn("%s", la->filename);
5521			continue;
5522		}
5523		if (pfctl_rules(dev, la->filename, fin, pf->opts, pf->optimize,
5524		    la->anchorname, trans) == -1)
5525			return (-1);
5526	}
5527
5528	return (0);
5529}
5530