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