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