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