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