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