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