xref: /freebsd/sbin/pfctl/parse.y (revision 2e0e45a516b93cc72771a5de8b87cd0a07a55f07)
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 #define PFIOC_USE_LATEST
34 
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/stat.h>
38 #ifdef __FreeBSD__
39 #include <sys/sysctl.h>
40 #endif
41 #include <net/if.h>
42 #include <netinet/in.h>
43 #include <netinet/in_systm.h>
44 #include <netinet/ip.h>
45 #include <netinet/ip_icmp.h>
46 #include <netinet/icmp6.h>
47 #include <net/pfvar.h>
48 #include <arpa/inet.h>
49 #include <net/altq/altq.h>
50 #include <net/altq/altq_cbq.h>
51 #include <net/altq/altq_codel.h>
52 #include <net/altq/altq_priq.h>
53 #include <net/altq/altq_hfsc.h>
54 #include <net/altq/altq_fairq.h>
55 
56 #include <assert.h>
57 #include <stdio.h>
58 #include <unistd.h>
59 #include <stdlib.h>
60 #include <netdb.h>
61 #include <stdarg.h>
62 #include <errno.h>
63 #include <string.h>
64 #include <ctype.h>
65 #include <math.h>
66 #include <err.h>
67 #include <limits.h>
68 #include <pwd.h>
69 #include <grp.h>
70 #include <md5.h>
71 
72 #include "pfctl_parser.h"
73 #include "pfctl.h"
74 
75 #define	ISSET(_v, _m)	((_v) & (_m))
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 	size_t			 ungetpos;
95 	size_t			 ungetsize;
96 	u_char			*ungetbuf;
97 	int			 eof_reached;
98 	int			 lineno;
99 	int			 errors;
100 } *file, *topfile;
101 struct file	*pushfile(const char *, int);
102 int		 popfile(void);
103 int		 check_file_secrecy(int, const char *);
104 int		 yyparse(void);
105 int		 yylex(void);
106 int		 yyerror(const char *, ...);
107 int		 kw_cmp(const void *, const void *);
108 int		 lookup(char *);
109 int		 igetc(void);
110 int		 lgetc(int);
111 void		 lungetc(int);
112 int		 findeol(void);
113 
114 static TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
115 struct sym {
116 	TAILQ_ENTRY(sym)	 entry;
117 	int			 used;
118 	int			 persist;
119 	char			*nam;
120 	char			*val;
121 };
122 int		 symset(const char *, const char *, int);
123 char		*symget(const char *);
124 
125 int		 atoul(char *, u_long *);
126 
127 enum {
128 	PFCTL_STATE_NONE,
129 	PFCTL_STATE_OPTION,
130 	PFCTL_STATE_ETHER,
131 	PFCTL_STATE_SCRUB,
132 	PFCTL_STATE_QUEUE,
133 	PFCTL_STATE_NAT,
134 	PFCTL_STATE_FILTER
135 };
136 
137 struct node_etherproto {
138 	u_int16_t		 proto;
139 	struct node_etherproto	*next;
140 	struct node_etherproto	*tail;
141 };
142 
143 struct node_proto {
144 	u_int8_t		 proto;
145 	struct node_proto	*next;
146 	struct node_proto	*tail;
147 };
148 
149 struct node_port {
150 	u_int16_t		 port[2];
151 	u_int8_t		 op;
152 	struct node_port	*next;
153 	struct node_port	*tail;
154 };
155 
156 struct node_uid {
157 	uid_t			 uid[2];
158 	u_int8_t		 op;
159 	struct node_uid		*next;
160 	struct node_uid		*tail;
161 };
162 
163 struct node_gid {
164 	gid_t			 gid[2];
165 	u_int8_t		 op;
166 	struct node_gid		*next;
167 	struct node_gid		*tail;
168 };
169 
170 struct node_icmp {
171 	uint16_t		 code;
172 	uint16_t		 type;
173 	u_int8_t		 proto;
174 	struct node_icmp	*next;
175 	struct node_icmp	*tail;
176 };
177 
178 enum	{ PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
179 	    PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN,
180 	    PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES,
181 	    PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK,
182 	    PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY,
183 	    PF_STATE_OPT_PFLOW, PF_STATE_OPT_ALLOW_RELATED,
184 	    PF_STATE_OPT_STATELIM, PF_STATE_OPT_SOURCELIM };
185 
186 enum	{ PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
187 
188 struct node_state_opt {
189 	int			 type;
190 	union {
191 		u_int32_t	 max_states;
192 		u_int32_t	 max_src_states;
193 		u_int32_t	 max_src_conn;
194 		struct {
195 			u_int32_t	limit;
196 			u_int32_t	seconds;
197 		}		 max_src_conn_rate;
198 		struct {
199 			u_int8_t	flush;
200 			char		tblname[PF_TABLE_NAME_SIZE];
201 		}		 overload;
202 		u_int32_t	 max_src_nodes;
203 		u_int8_t	 src_track;
204 		u_int32_t	 statelock;
205 		struct {
206 			int		number;
207 			u_int32_t	seconds;
208 		}		 timeout;
209 	}			 data;
210 	struct node_state_opt	*next;
211 	struct node_state_opt	*tail;
212 };
213 
214 struct peer {
215 	struct node_host	*host;
216 	struct node_port	*port;
217 };
218 
219 static struct node_queue {
220 	char			 queue[PF_QNAME_SIZE];
221 	char			 parent[PF_QNAME_SIZE];
222 	char			 ifname[IFNAMSIZ];
223 	int			 scheduler;
224 	struct node_queue	*next;
225 	struct node_queue	*tail;
226 }	*queues = NULL;
227 
228 struct node_qassign {
229 	char		*qname;
230 	char		*pqname;
231 };
232 
233 struct range {
234 	int		 a;
235 	int		 b;
236 	int		 t;
237 };
238 
239 static struct pool_opts {
240 	int			 marker;
241 #define POM_TYPE		0x01
242 #define POM_STICKYADDRESS	0x02
243 #define POM_ENDPI		0x04
244 #define POM_IPV6NH		0x08
245 	u_int8_t		 opts;
246 	int			 type;
247 	int			 staticport;
248 	struct pf_poolhashkey	*key;
249 	struct pf_mape_portset	 mape;
250 } pool_opts;
251 
252 struct redirspec {
253 	struct node_host	*host;
254 	struct range		 rport;
255 	struct pool_opts	 pool_opts;
256 	sa_family_t		 af;
257 	bool			 binat;
258 };
259 
260 struct limiterspec {
261 	uint32_t	id;
262 	int			limiter_action;
263 };
264 
265 static struct filter_opts {
266 	int			 marker;
267 #define FOM_FLAGS	0x0001
268 #define FOM_ICMP	0x0002
269 #define FOM_TOS		0x0004
270 #define FOM_KEEP	0x0008
271 #define FOM_SRCTRACK	0x0010
272 #define FOM_MINTTL	0x0020
273 #define FOM_MAXMSS	0x0040
274 #define FOM_AFTO	0x0080
275 #define FOM_SETTOS	0x0100
276 #define FOM_SCRUB_TCP	0x0200
277 #define FOM_SETPRIO	0x0400
278 #define FOM_ONCE	0x1000
279 #define FOM_PRIO	0x2000
280 #define FOM_SETDELAY	0x4000
281 #define FOM_FRAGCACHE	0x8000 /* does not exist in OpenBSD */
282 	struct node_uid		*uid;
283 	struct node_gid		*gid;
284 	struct node_if		*rcv;
285 	struct {
286 		u_int8_t	 b1;
287 		u_int8_t	 b2;
288 		u_int16_t	 w;
289 		u_int16_t	 w2;
290 	} flags;
291 	struct node_icmp	*icmpspec;
292 	u_int32_t		 tos;
293 	u_int32_t		 prob;
294 	u_int32_t		 ridentifier;
295 	struct limiterspec		 statelim;
296 	struct limiterspec		 sourcelim;
297 	struct {
298 		int			 action;
299 		struct node_state_opt	*options;
300 	} keep;
301 	int			 fragment;
302 	int			 allowopts;
303 	char			*label[PF_RULE_MAX_LABEL_COUNT];
304 	int			 labelcount;
305 	struct node_qassign	 queues;
306 	char			*tag;
307 	char			*match_tag;
308 	u_int8_t		 match_tag_not;
309 	u_int16_t		 dnpipe;
310 	u_int16_t		 dnrpipe;
311 	u_int32_t		 free_flags;
312 	u_int			 rtableid;
313 	u_int8_t		 prio;
314 	u_int8_t		 set_prio[2];
315 	struct {
316 		struct node_host	*addr;
317 		u_int16_t		port;
318 	}			 divert;
319 	struct redirspec	 *nat;
320 	struct redirspec	 *rdr;
321 	/* new-style scrub opts */
322 	int			 nodf;
323 	int			 minttl;
324 	int			 settos;
325 	int			 randomid;
326 	int			 max_mss;
327 	struct {
328 		uint32_t	limit;
329 		uint32_t	seconds;
330 	}			pktrate;
331 	int			 max_pkt_size;
332 } filter_opts;
333 
334 static struct antispoof_opts {
335 	char			*label[PF_RULE_MAX_LABEL_COUNT];
336 	int			 labelcount;
337 	u_int32_t		 ridentifier;
338 	u_int			 rtableid;
339 } antispoof_opts;
340 
341 static struct scrub_opts {
342 	int			 marker;
343 	int			 nodf;
344 	int			 minttl;
345 	int			 maxmss;
346 	int			 settos;
347 	int			 fragcache;
348 	int			 randomid;
349 	int			 reassemble_tcp;
350 	char			*match_tag;
351 	u_int8_t		 match_tag_not;
352 	u_int			 rtableid;
353 } scrub_opts;
354 
355 static struct queue_opts {
356 	int			marker;
357 #define QOM_BWSPEC	0x01
358 #define QOM_SCHEDULER	0x02
359 #define QOM_PRIORITY	0x04
360 #define QOM_TBRSIZE	0x08
361 #define QOM_QLIMIT	0x10
362 	struct node_queue_bw	queue_bwspec;
363 	struct node_queue_opt	scheduler;
364 	int			priority;
365 	unsigned int		tbrsize;
366 	int			qlimit;
367 } queue_opts;
368 
369 static struct table_opts {
370 	int			flags;
371 	int			init_addr;
372 	struct node_tinithead	init_nodes;
373 } table_opts;
374 
375 struct statelim_opts {
376 	unsigned int		 marker;
377 #define	STATELIM_M_ID		0x01
378 #define	STATELIM_M_LIMIT	0x02
379 #define	STATELIM_M_RATE		0x04
380 
381 	uint32_t		 id;
382 	char			 name[PF_STATELIM_NAME_LEN];
383 	unsigned int	 limit;
384 	struct {
385 		unsigned int	 limit;
386 		unsigned int	 seconds;
387 	} rate;
388 };
389 
390 static struct statelim_opts statelim_opts;
391 
392 struct sourcelim_opts {
393 	unsigned int		 marker;
394 #define	SOURCELIM_M_ID			0x01
395 #define	SOURCELIM_M_ENTRIES		0x02
396 #define	SOURCELIM_M_LIMIT		0x04
397 #define	SOURCELIM_M_RATE		0x08
398 #define	SOURCELIM_M_TABLE		0x10
399 #define	SOURCELIM_M_INET_MASK	0x20
400 #define	SOURCELIM_M_INET6_MASK	0x40
401 
402 	uint32_t			 id;
403 	unsigned int		 entries;
404 	unsigned int		 limit;
405 	struct {
406 		unsigned int	 limit;
407 		unsigned int	 seconds;
408 	} rate;
409 	struct {
410 		char			 name[PF_TABLE_NAME_SIZE];
411 		unsigned int	 above;
412 		unsigned int	 below;
413 	} table;
414 	unsigned int		 inet_mask;
415 	unsigned int		 inet6_mask;
416 };
417 
418 static struct sourcelim_opts sourcelim_opts;
419 
420 static struct codel_opts	 codel_opts;
421 static struct node_hfsc_opts	 hfsc_opts;
422 static struct node_fairq_opts	 fairq_opts;
423 static struct node_state_opt	*keep_state_defaults = NULL;
424 static struct pfctl_watermarks	 syncookie_opts;
425 
426 int		 validate_range(uint8_t, uint16_t, uint16_t);
427 int		 disallow_table(struct node_host *, const char *);
428 int		 disallow_urpf_failed(struct node_host *, const char *);
429 int		 disallow_alias(struct node_host *, const char *);
430 int		 rule_consistent(struct pfctl_rule *);
431 int		 filter_consistent(struct pfctl_rule *);
432 int		 nat_consistent(struct pfctl_rule *);
433 int		 rdr_consistent(struct pfctl_rule *);
434 int		 process_tabledef(char *, struct table_opts *, int);
435 void		 expand_label_str(char *, size_t, const char *, const char *);
436 void		 expand_label_if(const char *, char *, size_t, const char *);
437 void		 expand_label_addr(const char *, char *, size_t, sa_family_t,
438 		    struct pf_rule_addr *);
439 void		 expand_label_port(const char *, char *, size_t,
440 		    struct pf_rule_addr *);
441 void		 expand_label_proto(const char *, char *, size_t, u_int8_t);
442 void		 expand_label_nr(const char *, char *, size_t,
443 		    struct pfctl_rule *);
444 void		 expand_eth_rule(struct pfctl_eth_rule *,
445 		    struct node_if *, struct node_etherproto *,
446 		    struct node_mac *, struct node_mac *,
447 		    struct node_host *, struct node_host *, const char *,
448 		    const char *);
449 int		 apply_rdr_ports(struct pfctl_rule *r, struct pfctl_pool *, struct redirspec *);
450 int		 apply_nat_ports(struct pfctl_pool *, struct redirspec *);
451 int		 apply_redirspec(struct pfctl_pool *, struct redirspec *);
452 int		 check_binat_redirspec(struct node_host *, struct pfctl_rule *, sa_family_t);
453 void		 add_binat_rdr_rule(struct pfctl_rule *, struct redirspec *,
454 		 struct node_host *, struct pfctl_rule *, struct redirspec **,
455 		 struct node_host **);
456 void		 expand_rule(struct pfctl_rule *, bool, struct node_if *,
457 		    struct redirspec *, struct redirspec *, struct redirspec *,
458 		    struct node_proto *, struct node_os *, struct node_host *,
459 		    struct node_port *, struct node_host *, struct node_port *,
460 		    struct node_uid *, struct node_gid *, struct node_if *,
461 		    struct node_icmp *);
462 int		 expand_altq(struct pf_altq *, struct node_if *,
463 		    struct node_queue *, struct node_queue_bw bwspec,
464 		    struct node_queue_opt *);
465 int		 expand_queue(struct pf_altq *, struct node_if *,
466 		    struct node_queue *, struct node_queue_bw,
467 		    struct node_queue_opt *);
468 int		 expand_skip_interface(struct node_if *);
469 
470 int	 check_rulestate(int);
471 int	 getservice(char *);
472 int	 rule_label(struct pfctl_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
473 int	 eth_rule_label(struct pfctl_eth_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
474 int	 rt_tableid_max(void);
475 
476 void	 mv_rules(struct pfctl_ruleset *, struct pfctl_ruleset *);
477 void	 mv_eth_rules(struct pfctl_eth_ruleset *, struct pfctl_eth_ruleset *);
478 void	 mv_tables(struct pfctl *, struct pfr_ktablehead *,
479 		    struct pfctl_anchor *, struct pfctl_anchor *);
480 void	 decide_address_family(struct node_host *, sa_family_t *);
481 void	 remove_invalid_hosts(struct node_host **, sa_family_t *);
482 int	 invalid_redirect(struct node_host *, sa_family_t);
483 u_int16_t parseicmpspec(char *, sa_family_t);
484 int	 kw_casecmp(const void *, const void *);
485 int	 map_tos(char *string, int *);
486 int	 filteropts_to_rule(struct pfctl_rule *, struct filter_opts *);
487 struct node_mac* node_mac_from_string(const char *);
488 struct node_mac* node_mac_from_string_masklen(const char *, int);
489 struct node_mac* node_mac_from_string_mask(const char *, const char *);
490 static bool pfctl_setup_anchor(struct pfctl_rule *, struct pfctl *, char *);
491 
492 static TAILQ_HEAD(loadanchorshead, loadanchors)
493     loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead);
494 
495 struct loadanchors {
496 	TAILQ_ENTRY(loadanchors)	 entries;
497 	char				*anchorname;
498 	char				*filename;
499 };
500 
501 typedef struct {
502 	union {
503 		int64_t			 number;
504 		double			 probability;
505 		int			 i;
506 		char			*string;
507 		u_int			 rtableid;
508 		struct {
509 			u_int8_t	 b1;
510 			u_int8_t	 b2;
511 			u_int16_t	 w;
512 			u_int16_t	 w2;
513 		}			 b;
514 		struct range		 range;
515 		struct node_if		*interface;
516 		struct node_proto	*proto;
517 		struct node_etherproto	*etherproto;
518 		struct node_icmp	*icmp;
519 		struct node_host	*host;
520 		struct node_os		*os;
521 		struct node_port	*port;
522 		struct node_uid		*uid;
523 		struct node_gid		*gid;
524 		struct node_state_opt	*state_opt;
525 		struct peer		 peer;
526 		struct {
527 			struct peer	 src, dst;
528 			struct node_os	*src_os;
529 		}			 fromto;
530 		struct {
531 			struct node_mac	*src;
532 			struct node_mac	*dst;
533 		}			 etherfromto;
534 		struct node_mac		*mac;
535 		struct {
536 			struct node_mac	*mac;
537 		} etheraddr;
538 		char			*bridge_to;
539 		struct {
540 			struct redirspec	*redirspec;
541 			u_int8_t		 rt;
542 		}			 route;
543 		struct redirspec	*redirspec;
544 		struct {
545 			int			 action;
546 			struct node_state_opt	*options;
547 		}			 keep_state;
548 		struct {
549 			u_int8_t	 log;
550 			u_int8_t	 logif;
551 			u_int8_t	 quick;
552 		}			 logquick;
553 		struct {
554 			int		 neg;
555 			char		*name;
556 		}			 tagged;
557 		struct pf_poolhashkey	*hashkey;
558 		struct node_queue	*queue;
559 		struct node_queue_opt	 queue_options;
560 		struct node_queue_bw	 queue_bwspec;
561 		struct node_qassign	 qassign;
562 		struct filter_opts	 filter_opts;
563 		struct antispoof_opts	 antispoof_opts;
564 		struct queue_opts	 queue_opts;
565 		struct scrub_opts	 scrub_opts;
566 		struct table_opts	 table_opts;
567 		struct pool_opts	 pool_opts;
568 		struct node_hfsc_opts	 hfsc_opts;
569 		struct node_fairq_opts	 fairq_opts;
570 		struct codel_opts	 codel_opts;
571 		struct statelim_opts	*statelim_opts;
572 		struct sourcelim_opts	*sourcelim_opts;
573 		struct pfctl_watermarks	*watermarks;
574 		struct limiterspec		 limiterspec;
575 	} v;
576 	int lineno;
577 } YYSTYPE;
578 
579 #define PPORT_RANGE	1
580 #define PPORT_STAR	2
581 int	parseport(char *, struct range *r, int);
582 
583 #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
584 	(!((addr).iflags & PFI_AFLAG_NOALIAS) ||		 \
585 	!isdigit((addr).v.ifname[strlen((addr).v.ifname)-1])))
586 
587 %}
588 
589 %token	PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
590 %token	RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
591 %token	ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
592 %token	MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
593 %token	NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
594 %token	REASSEMBLE ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
595 %token	SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY FAILPOLICY
596 %token	RANDOMID REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
597 %token	ANTISPOOF FOR INCLUDE KEEPCOUNTERS SYNCOOKIES L3 MATCHES
598 %token	ETHER
599 %token	BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY MAPEPORTSET
600 %token	ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME
601 %token	UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL
602 %token	DNPIPE DNQUEUE RIDENTIFIER
603 %token	LOAD RULESET_OPTIMIZATION PRIO ONCE
604 %token	STICKYADDRESS ENDPI MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
605 %token	MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW ALLOW_RELATED
606 %token	TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS
607 %token	DIVERTTO DIVERTREPLY BRIDGE_TO RECEIVEDON NE LE GE AFTO NATTO RDRTO
608 %token	BINATTO MAXPKTRATE MAXPKTSIZE IPV6NH
609 %token	LIMITER ID RATE SOURCE ENTRIES ABOVE BELOW MASK NOMATCH
610 %token	<v.string>		STRING
611 %token	<v.number>		NUMBER
612 %token	<v.i>			PORTBINARY
613 %type	<v.interface>		interface if_list if_item_not if_item
614 %type	<v.number>		number icmptype icmp6type uid gid
615 %type	<v.number>		tos not yesno optnodf sourcelim_opt_below
616 %type	<v.probability>		probability
617 %type	<v.i>			no dir af fragcache optimizer syncookie_val
618 %type	<v.i>			sourcetrack flush unaryop statelock
619 %type	<v.i>			etherprotoval
620 %type	<v.b>			action nataction natpasslog scrubaction
621 %type	<v.b>			flags flag blockspec prio
622 %type	<v.range>		portplain portstar portrange
623 %type	<v.hashkey>		hashkey
624 %type	<v.proto>		proto proto_list proto_item
625 %type	<v.number>		protoval
626 %type	<v.icmp>		icmpspec
627 %type	<v.icmp>		icmp_list icmp_item
628 %type	<v.icmp>		icmp6_list icmp6_item
629 %type	<v.number>		reticmpspec reticmp6spec
630 %type	<v.fromto>		fromto l3fromto
631 %type	<v.peer>		ipportspec from to
632 %type	<v.host>		ipspec toipspec xhost host dynaddr host_list
633 %type	<v.host>		redir_host redir_host_list routespec
634 %type	<v.host>		route_host route_host_list
635 %type	<v.os>			os xos os_list
636 %type	<v.port>		portspec port_list port_item
637 %type	<v.uid>			uids uid_list uid_item
638 %type	<v.gid>			gids gid_list gid_item
639 %type	<v.route>		route
640 %type	<v.redirspec>		no_port_redirspec port_redirspec route_redirspec
641 %type	<v.redirspec>		binat_redirspec nat_redirspec
642 %type	<v.string>		label stringall tag anchorname
643 %type	<v.string>		string varstring numberstring
644 %type	<v.keep_state>		keep
645 %type	<v.state_opt>		state_opt_spec state_opt_list state_opt_item
646 %type	<v.logquick>		logquick quick log logopts logopt
647 %type	<v.interface>		antispoof_ifspc antispoof_iflst antispoof_if
648 %type	<v.qassign>		qname etherqname
649 %type	<v.queue>		qassign qassign_list qassign_item
650 %type	<v.queue_options>	scheduler
651 %type	<v.number>		cbqflags_list cbqflags_item
652 %type	<v.number>		priqflags_list priqflags_item
653 %type	<v.hfsc_opts>		hfscopts_list hfscopts_item hfsc_opts
654 %type	<v.fairq_opts>		fairqopts_list fairqopts_item fairq_opts
655 %type	<v.codel_opts>		codelopts_list codelopts_item codel_opts
656 %type	<v.queue_bwspec>	bandwidth
657 %type	<v.filter_opts>		filter_opts filter_opt filter_opts_l etherfilter_opts etherfilter_opt etherfilter_opts_l
658 %type	<v.filter_opts>		filter_sets filter_set filter_sets_l
659 %type	<v.antispoof_opts>	antispoof_opts antispoof_opt antispoof_opts_l
660 %type	<v.queue_opts>		queue_opts queue_opt queue_opts_l
661 %type	<v.scrub_opts>		scrub_opts scrub_opt scrub_opts_l
662 %type	<v.table_opts>		table_opts table_opt table_opts_l
663 %type	<v.pool_opts>		pool_opts pool_opt pool_opts_l
664 %type	<v.tagged>		tagged
665 %type	<v.rtableid>		rtable
666 %type	<v.watermarks>		syncookie_opts
667 %type	<v.etherproto>		etherproto etherproto_list etherproto_item
668 %type	<v.etherfromto>		etherfromto
669 %type	<v.etheraddr>		etherfrom etherto
670 %type	<v.bridge_to>		bridge
671 %type	<v.mac>			xmac mac mac_list macspec
672 %type	<v.string>			statelim_nm sourcelim_nm
673 %type	<v.number>			statelim_id sourcelim_id limiter_opt limiter_opt_spec
674 %type	<v.limiterspec>		statelim_filter_opt sourcelim_filter_opt
675 %type	<v.statelim_opts>	statelim_opts
676 %type	<v.sourcelim_opts>	sourcelim_opts
677 %%
678 
679 ruleset		: /* empty */
680 		| ruleset include '\n'
681 		| ruleset '\n'
682 		| ruleset option '\n'
683 		| ruleset statelim '\n'
684 		| ruleset sourcelim '\n'
685 		| ruleset etherrule '\n'
686 		| ruleset etheranchorrule '\n'
687 		| ruleset scrubrule '\n'
688 		| ruleset natrule '\n'
689 		| ruleset binatrule '\n'
690 		| ruleset pfrule '\n'
691 		| ruleset anchorrule '\n'
692 		| ruleset loadrule '\n'
693 		| ruleset altqif '\n'
694 		| ruleset queuespec '\n'
695 		| ruleset varset '\n'
696 		| ruleset antispoof '\n'
697 		| ruleset tabledef '\n'
698 		| '{' fakeanchor '}' '\n';
699 		| ruleset error '\n'		{ file->errors++; }
700 		;
701 
702 include		: INCLUDE STRING		{
703 			struct file	*nfile;
704 
705 			if ((nfile = pushfile($2, 0)) == NULL) {
706 				yyerror("failed to include file %s", $2);
707 				free($2);
708 				YYERROR;
709 			}
710 			free($2);
711 
712 			file = nfile;
713 			lungetc('\n');
714 		}
715 		;
716 
717 /*
718  * apply to previouslys specified rule: must be careful to note
719  * what that is: pf or nat or binat or rdr
720  */
721 fakeanchor	: fakeanchor '\n'
722 		| fakeanchor anchorrule '\n'
723 		| fakeanchor binatrule '\n'
724 		| fakeanchor natrule '\n'
725 		| fakeanchor pfrule '\n'
726 		| fakeanchor error '\n'
727 		;
728 
729 optimizer	: string	{
730 			if (!strcmp($1, "none"))
731 				$$ = 0;
732 			else if (!strcmp($1, "basic"))
733 				$$ = PF_OPTIMIZE_BASIC;
734 			else if (!strcmp($1, "profile"))
735 				$$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE;
736 			else {
737 				yyerror("unknown ruleset-optimization %s", $1);
738 				YYERROR;
739 			}
740 		}
741 		;
742 
743 optnodf		: /* empty */	{ $$ = 0; }
744 		| NODF		{ $$ = 1; }
745 		;
746 
747 option		: SET REASSEMBLE yesno optnodf		{
748 			if (check_rulestate(PFCTL_STATE_OPTION))
749 				YYERROR;
750 			pfctl_set_reassembly(pf, $3, $4);
751 		}
752 		| SET OPTIMIZATION STRING		{
753 			if (check_rulestate(PFCTL_STATE_OPTION)) {
754 				free($3);
755 				YYERROR;
756 			}
757 			if (pfctl_set_optimization(pf, $3) != 0) {
758 				yyerror("unknown optimization %s", $3);
759 				free($3);
760 				YYERROR;
761 			}
762 			free($3);
763 		}
764 		| SET RULESET_OPTIMIZATION optimizer {
765 			if (!(pf->opts & PF_OPT_OPTIMIZE)) {
766 				pf->opts |= PF_OPT_OPTIMIZE;
767 				pf->optimize = $3;
768 			}
769 		}
770 		| SET TIMEOUT timeout_spec
771 		| SET TIMEOUT '{' optnl timeout_list '}'
772 		| SET LIMIT limit_spec
773 		| SET LIMIT '{' optnl limit_list '}'
774 		| SET LOGINTERFACE stringall		{
775 			if (check_rulestate(PFCTL_STATE_OPTION)) {
776 				free($3);
777 				YYERROR;
778 			}
779 			if (pfctl_set_logif(pf, $3) != 0) {
780 				yyerror("error setting loginterface %s", $3);
781 				free($3);
782 				YYERROR;
783 			}
784 			free($3);
785 		}
786 		| SET HOSTID number {
787 			if ($3 == 0 || $3 > UINT_MAX) {
788 				yyerror("hostid must be non-zero");
789 				YYERROR;
790 			}
791 			pfctl_set_hostid(pf, $3);
792 		}
793 		| SET BLOCKPOLICY DROP	{
794 			if (pf->opts & PF_OPT_VERBOSE)
795 				printf("set block-policy drop\n");
796 			if (check_rulestate(PFCTL_STATE_OPTION))
797 				YYERROR;
798 			blockpolicy = PFRULE_DROP;
799 		}
800 		| SET BLOCKPOLICY RETURN {
801 			if (pf->opts & PF_OPT_VERBOSE)
802 				printf("set block-policy return\n");
803 			if (check_rulestate(PFCTL_STATE_OPTION))
804 				YYERROR;
805 			blockpolicy = PFRULE_RETURN;
806 		}
807 		| SET FAILPOLICY DROP	{
808 			if (pf->opts & PF_OPT_VERBOSE)
809 				printf("set fail-policy drop\n");
810 			if (check_rulestate(PFCTL_STATE_OPTION))
811 				YYERROR;
812 			failpolicy = PFRULE_DROP;
813 		}
814 		| SET FAILPOLICY RETURN {
815 			if (pf->opts & PF_OPT_VERBOSE)
816 				printf("set fail-policy return\n");
817 			if (check_rulestate(PFCTL_STATE_OPTION))
818 				YYERROR;
819 			failpolicy = PFRULE_RETURN;
820 		}
821 		| SET REQUIREORDER yesno {
822 			if (pf->opts & PF_OPT_VERBOSE)
823 				printf("set require-order %s\n",
824 				    $3 == 1 ? "yes" : "no");
825 			require_order = $3;
826 		}
827 		| SET FINGERPRINTS STRING {
828 			if (pf->opts & PF_OPT_VERBOSE)
829 				printf("set fingerprints \"%s\"\n", $3);
830 			if (check_rulestate(PFCTL_STATE_OPTION)) {
831 				free($3);
832 				YYERROR;
833 			}
834 			if (!pf->anchor->name[0]) {
835 				if (pfctl_file_fingerprints(pf->dev,
836 				    pf->opts, $3)) {
837 					yyerror("error loading "
838 					    "fingerprints %s", $3);
839 					free($3);
840 					YYERROR;
841 				}
842 			}
843 			free($3);
844 		}
845 		| SET STATEPOLICY statelock {
846 			if (pf->opts & PF_OPT_VERBOSE)
847 				switch ($3) {
848 				case 0:
849 					printf("set state-policy floating\n");
850 					break;
851 				case PFRULE_IFBOUND:
852 					printf("set state-policy if-bound\n");
853 					break;
854 				}
855 			default_statelock = $3;
856 		}
857 		| SET DEBUG STRING {
858 			if (check_rulestate(PFCTL_STATE_OPTION)) {
859 				free($3);
860 				YYERROR;
861 			}
862 			if (pfctl_do_set_debug(pf, $3) != 0) {
863 				yyerror("error setting debuglevel %s", $3);
864 				free($3);
865 				YYERROR;
866 			}
867 			free($3);
868 		}
869 		| SET SKIP interface {
870 			if (expand_skip_interface($3) != 0) {
871 				yyerror("error setting skip interface(s)");
872 				YYERROR;
873 			}
874 		}
875 		| SET STATEDEFAULTS state_opt_list {
876 			if (keep_state_defaults != NULL) {
877 				yyerror("cannot redefine state-defaults");
878 				YYERROR;
879 			}
880 			keep_state_defaults = $3;
881 		}
882 		| SET KEEPCOUNTERS {
883 			pf->keep_counters = true;
884 		}
885 		| SET SYNCOOKIES syncookie_val syncookie_opts {
886 			if (pfctl_cfg_syncookies(pf, $3, $4)) {
887 				yyerror("error setting syncookies");
888 				YYERROR;
889 			}
890 		}
891 		;
892 
893 syncookie_val  : STRING        {
894 			if (!strcmp($1, "never"))
895 				$$ = PFCTL_SYNCOOKIES_NEVER;
896 			else if (!strcmp($1, "adaptive"))
897 				$$ = PFCTL_SYNCOOKIES_ADAPTIVE;
898 			else if (!strcmp($1, "always"))
899 				$$ = PFCTL_SYNCOOKIES_ALWAYS;
900 			else {
901 				yyerror("illegal value for syncookies");
902 				YYERROR;
903 			}
904 		}
905 		;
906 syncookie_opts  : /* empty */                   { $$ = NULL; }
907 		| {
908 			memset(&syncookie_opts, 0, sizeof(syncookie_opts));
909 		  } '(' syncookie_opt_l ')'     { $$ = &syncookie_opts; }
910 		;
911 
912 syncookie_opt_l : syncookie_opt_l comma syncookie_opt
913 		| syncookie_opt
914 		;
915 
916 syncookie_opt   : STRING STRING {
917 			double   val;
918 			char    *cp;
919 
920 			val = strtod($2, &cp);
921 			if (cp == NULL || strcmp(cp, "%"))
922 				YYERROR;
923 			if (val <= 0 || val > 100) {
924 				yyerror("illegal percentage value");
925 				YYERROR;
926 			}
927 			if (!strcmp($1, "start")) {
928 				syncookie_opts.hi = val;
929 			} else if (!strcmp($1, "end")) {
930 				syncookie_opts.lo = val;
931 			} else {
932 				yyerror("illegal syncookie option");
933 				YYERROR;
934 			}
935 		}
936 		;
937 
938 stringall	: STRING	{ $$ = $1; }
939 		| ALL		{
940 			if (($$ = strdup("all")) == NULL) {
941 				err(1, "stringall: strdup");
942 			}
943 		}
944 		;
945 
946 string		: STRING string				{
947 			if (asprintf(&$$, "%s %s", $1, $2) == -1)
948 				err(1, "string: asprintf");
949 			free($1);
950 			free($2);
951 		}
952 		| STRING
953 		;
954 
955 varstring	: numberstring varstring 		{
956 			if (asprintf(&$$, "%s %s", $1, $2) == -1)
957 				err(1, "string: asprintf");
958 			free($1);
959 			free($2);
960 		}
961 		| numberstring
962 		;
963 
964 numberstring	: NUMBER				{
965 			char	*s;
966 			if (asprintf(&s, "%lld", (long long)$1) == -1) {
967 				yyerror("string: asprintf");
968 				YYERROR;
969 			}
970 			$$ = s;
971 		}
972 		| STRING
973 		;
974 
975 varset		: STRING '=' varstring	{
976 			char *s = $1;
977 			if (pf->opts & PF_OPT_VERBOSE)
978 				printf("%s = \"%s\"\n", $1, $3);
979 			while (*s++) {
980 				if (isspace((unsigned char)*s)) {
981 					yyerror("macro name cannot contain "
982 					   "whitespace");
983 					free($1);
984 					free($3);
985 					YYERROR;
986 				}
987 			}
988 			if (symset($1, $3, 0) == -1)
989 				err(1, "cannot store variable %s", $1);
990 			free($1);
991 			free($3);
992 		}
993 		;
994 
995 anchorname	: STRING			{
996 			if ($1[0] == '\0') {
997 				free($1);
998 				yyerror("anchor name must not be empty");
999 				YYERROR;
1000 			}
1001 			if (strlen(pf->anchor->path) + 1 +
1002 			    strlen($1) >= PATH_MAX) {
1003 				free($1);
1004 				yyerror("anchor name is longer than %u",
1005 				   PATH_MAX - 1);
1006 				YYERROR;
1007 			}
1008 			if ($1[0] == '_' || strstr($1, "/_") != NULL) {
1009 				free($1);
1010 				yyerror("anchor names beginning with '_' "
1011 				  "are reserved for internal use");
1012 				YYERROR;
1013 			}
1014 			$$ = $1;
1015 		}
1016 		| /* empty */			{ $$ = NULL; }
1017 		;
1018 
1019 pfa_anchorlist	: /* empty */
1020 		| pfa_anchorlist '\n'
1021 		| pfa_anchorlist tabledef '\n'
1022 		| pfa_anchorlist pfrule '\n'
1023 		| pfa_anchorlist anchorrule '\n'
1024 		| pfa_anchorlist include '\n'
1025 		;
1026 
1027 pfa_anchor	: '{'
1028 		{
1029 			char ta[PF_ANCHOR_NAME_SIZE];
1030 			struct pfctl_ruleset *rs;
1031 
1032 			/* stepping into a brace anchor */
1033 			if (pf->asd >= PFCTL_ANCHOR_STACK_DEPTH)
1034 				errx(1, "pfa_anchor: anchors too deep");
1035 			pf->asd++;
1036 			pf->bn++;
1037 
1038 			/*
1039 			* Anchor contents are parsed before the anchor rule
1040 			* production completes, so we don't know the real
1041 			* location yet. Create a holding ruleset in the root;
1042 			* contents will be moved afterwards.
1043 			*/
1044 			snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn);
1045 			rs = pf_find_or_create_ruleset(ta);
1046 			if (rs == NULL)
1047 				err(1, "pfa_anchor: pf_find_or_create_ruleset (%s)", ta);
1048 			pf->astack[pf->asd] = rs->anchor;
1049 			pf->anchor = rs->anchor;
1050 		} '\n' pfa_anchorlist '}'
1051 		{
1052 			pf->alast = pf->anchor;
1053 			pf->asd--;
1054 			pf->anchor = pf->astack[pf->asd];
1055 		}
1056 		| /* empty */
1057 		;
1058 
1059 anchorrule	: ANCHOR anchorname dir quick interface af proto fromto
1060 		    filter_opts pfa_anchor
1061 		{
1062 			struct pfctl_rule	r;
1063 			struct node_proto	*proto;
1064 
1065 			if (check_rulestate(PFCTL_STATE_FILTER)) {
1066 				if ($2)
1067 					free($2);
1068 				YYERROR;
1069 			}
1070 
1071 			pfctl_init_rule(&r);
1072 			if (! pfctl_setup_anchor(&r, pf, $2))
1073 				YYERROR;
1074 
1075 			r.direction = $3;
1076 			r.quick = $4.quick;
1077 			r.af = $6;
1078 
1079 			if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
1080 				for (proto = $7; proto != NULL &&
1081 				    proto->proto != IPPROTO_TCP;
1082 				    proto = proto->next)
1083 					;	/* nothing */
1084 				if (proto == NULL && $7 != NULL) {
1085 					if ($9.flags.b1 || $9.flags.b2)
1086 						yyerror(
1087 						    "flags only apply to tcp");
1088 					if ($8.src_os)
1089 						yyerror(
1090 						    "OS fingerprinting only "
1091 						    "applies to tcp");
1092 					YYERROR;
1093 				}
1094 			}
1095 
1096 			if (filteropts_to_rule(&r, &$9))
1097 				YYERROR;
1098 
1099 			if ($9.keep.action) {
1100 				yyerror("cannot specify state handling "
1101 				    "on anchors");
1102 				YYERROR;
1103 			}
1104 
1105 			decide_address_family($8.src.host, &r.af);
1106 			decide_address_family($8.dst.host, &r.af);
1107 
1108 			expand_rule(&r, false, $5, NULL, NULL, NULL,
1109 			    $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host,
1110 			    $8.dst.port, $9.uid, $9.gid, $9.rcv, $9.icmpspec);
1111 			free($2);
1112 			pf->astack[pf->asd + 1] = NULL;
1113 		}
1114 		| NATANCHOR string interface af proto fromto rtable {
1115 			struct pfctl_rule	r;
1116 
1117 			if (check_rulestate(PFCTL_STATE_NAT)) {
1118 				free($2);
1119 				YYERROR;
1120 			}
1121 
1122 			pfctl_init_rule(&r);
1123 			if (! pfctl_setup_anchor(&r, pf, $2))
1124 				YYERROR;
1125 
1126 			r.action = PF_NAT;
1127 			r.af = $4;
1128 			r.rtableid = $7;
1129 
1130 			decide_address_family($6.src.host, &r.af);
1131 			decide_address_family($6.dst.host, &r.af);
1132 
1133 			expand_rule(&r, false, $3, NULL, NULL, NULL,
1134 			    $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host,
1135 			    $6.dst.port, 0, 0, 0, 0);
1136 			free($2);
1137 		}
1138 		| RDRANCHOR string interface af proto fromto rtable {
1139 			struct pfctl_rule	r;
1140 
1141 			if (check_rulestate(PFCTL_STATE_NAT)) {
1142 				free($2);
1143 				YYERROR;
1144 			}
1145 
1146 			pfctl_init_rule(&r);
1147 			if (! pfctl_setup_anchor(&r, pf, $2))
1148 				YYERROR;
1149 
1150 			r.action = PF_RDR;
1151 			r.af = $4;
1152 			r.rtableid = $7;
1153 
1154 			decide_address_family($6.src.host, &r.af);
1155 			decide_address_family($6.dst.host, &r.af);
1156 
1157 			if ($6.src.port != NULL) {
1158 				yyerror("source port parameter not supported"
1159 				    " in rdr-anchor");
1160 				YYERROR;
1161 			}
1162 			if ($6.dst.port != NULL) {
1163 				if ($6.dst.port->next != NULL) {
1164 					yyerror("destination port list "
1165 					    "expansion not supported in "
1166 					    "rdr-anchor");
1167 					YYERROR;
1168 				} else if ($6.dst.port->op != PF_OP_EQ) {
1169 					yyerror("destination port operators"
1170 					    " not supported in rdr-anchor");
1171 					YYERROR;
1172 				}
1173 				r.dst.port[0] = $6.dst.port->port[0];
1174 				r.dst.port[1] = $6.dst.port->port[1];
1175 				r.dst.port_op = $6.dst.port->op;
1176 			}
1177 
1178 			expand_rule(&r, false, $3, NULL, NULL, NULL,
1179 			    $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host,
1180 			    $6.dst.port, 0, 0, 0, 0);
1181 			free($2);
1182 		}
1183 		| BINATANCHOR string interface af proto fromto rtable {
1184 			struct pfctl_rule	r;
1185 
1186 			if (check_rulestate(PFCTL_STATE_NAT)) {
1187 				free($2);
1188 				YYERROR;
1189 			}
1190 
1191 			pfctl_init_rule(&r);
1192 			if (! pfctl_setup_anchor(&r, pf, $2))
1193 				YYERROR;
1194 
1195 			r.action = PF_BINAT;
1196 			r.af = $4;
1197 			r.rtableid = $7;
1198 			if ($5 != NULL) {
1199 				if ($5->next != NULL) {
1200 					yyerror("proto list expansion"
1201 					    " not supported in binat-anchor");
1202 					YYERROR;
1203 				}
1204 				r.proto = $5->proto;
1205 				free($5);
1206 			}
1207 
1208 			if ($6.src.host != NULL || $6.src.port != NULL ||
1209 			    $6.dst.host != NULL || $6.dst.port != NULL) {
1210 				yyerror("fromto parameter not supported"
1211 				    " in binat-anchor");
1212 				YYERROR;
1213 			}
1214 
1215 			decide_address_family($6.src.host, &r.af);
1216 			decide_address_family($6.dst.host, &r.af);
1217 
1218 			pfctl_append_rule(pf, &r);
1219 			free($2);
1220 		}
1221 		;
1222 
1223 loadrule	: LOAD ANCHOR anchorname FROM string	{
1224 			struct loadanchors	*loadanchor;
1225 
1226 			if ($3 == NULL) {
1227 				yyerror("anchor name is missing");
1228 				YYERROR;
1229 			}
1230 			loadanchor = calloc(1, sizeof(struct loadanchors));
1231 			if (loadanchor == NULL)
1232 				err(1, "loadrule: calloc");
1233 			if ((loadanchor->anchorname = malloc(MAXPATHLEN)) ==
1234 			    NULL)
1235 				err(1, "loadrule: malloc");
1236 			if (pf->anchor->name[0])
1237 				snprintf(loadanchor->anchorname, MAXPATHLEN,
1238 				    "%s/%s", pf->anchor->path, $3);
1239 			else
1240 				strlcpy(loadanchor->anchorname, $3, MAXPATHLEN);
1241 			if ((loadanchor->filename = strdup($5)) == NULL)
1242 				err(1, "loadrule: strdup");
1243 
1244 			TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor,
1245 			    entries);
1246 
1247 			free($3);
1248 			free($5);
1249 		};
1250 
1251 scrubaction	: no SCRUB {
1252 			$$.b2 = $$.w = 0;
1253 			if ($1)
1254 				$$.b1 = PF_NOSCRUB;
1255 			else
1256 				$$.b1 = PF_SCRUB;
1257 		}
1258 		;
1259 
1260 etherrule	: ETHER action dir quick interface bridge etherproto etherfromto l3fromto etherfilter_opts
1261 		{
1262 			struct pfctl_eth_rule	r;
1263 
1264 			bzero(&r, sizeof(r));
1265 
1266 			if (check_rulestate(PFCTL_STATE_ETHER))
1267 				YYERROR;
1268 
1269 			r.action = $2.b1;
1270 			r.direction = $3;
1271 			r.quick = $4.quick;
1272 			if ($10.tag != NULL)
1273 				strlcpy(r.tagname, $10.tag, sizeof(r.tagname));
1274 			if ($10.match_tag)
1275 				if (strlcpy(r.match_tagname, $10.match_tag,
1276 				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
1277 					yyerror("tag too long, max %u chars",
1278 					    PF_TAG_NAME_SIZE - 1);
1279 					YYERROR;
1280 				}
1281 			r.match_tag_not = $10.match_tag_not;
1282 			if ($10.queues.qname != NULL)
1283 				strlcpy(r.qname, $10.queues.qname, sizeof(r.qname));
1284 			r.dnpipe = $10.dnpipe;
1285 			r.dnflags = $10.free_flags;
1286 			if (eth_rule_label(&r, $10.label))
1287 				YYERROR;
1288 			for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
1289 				free($10.label[i]);
1290 			r.ridentifier = $10.ridentifier;
1291 
1292 			expand_eth_rule(&r, $5, $7, $8.src, $8.dst,
1293 			    $9.src.host, $9.dst.host, $6, "");
1294 		}
1295 		;
1296 
1297 etherpfa_anchorlist	: /* empty */
1298 		| etherpfa_anchorlist '\n'
1299 		| etherpfa_anchorlist etherrule '\n'
1300 		| etherpfa_anchorlist etheranchorrule '\n'
1301 		;
1302 
1303 etherpfa_anchor	: '{'
1304 		{
1305 			char ta[PF_ANCHOR_NAME_SIZE];
1306 			struct pfctl_eth_ruleset *rs;
1307 
1308 			/* steping into a brace anchor */
1309 			if (pf->asd >= PFCTL_ANCHOR_STACK_DEPTH)
1310 				errx(1, "pfa_anchor: anchors too deep");
1311 			pf->asd++;
1312 			pf->bn++;
1313 
1314 			/* create a holding ruleset in the root */
1315 			snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn);
1316 			rs = pf_find_or_create_eth_ruleset(ta);
1317 			if (rs == NULL)
1318 				err(1, "etherpfa_anchor: pf_find_or_create_eth_ruleset");
1319 			pf->eastack[pf->asd] = rs->anchor;
1320 			pf->eanchor = rs->anchor;
1321 		} '\n' etherpfa_anchorlist '}'
1322 		{
1323 			pf->ealast = pf->eanchor;
1324 			pf->asd--;
1325 			pf->eanchor = pf->eastack[pf->asd];
1326 		}
1327 		| /* empty */
1328 		;
1329 
1330 etheranchorrule	: ETHER ANCHOR anchorname dir quick interface etherproto etherfromto l3fromto etherpfa_anchor
1331 		{
1332 			struct pfctl_eth_rule	r;
1333 
1334 			if (check_rulestate(PFCTL_STATE_ETHER)) {
1335 				free($3);
1336 				YYERROR;
1337 			}
1338 
1339 			if ($3 && ($3[0] == '_' || strstr($3, "/_") != NULL)) {
1340 				free($3);
1341 				yyerror("anchor names beginning with '_' "
1342 				    "are reserved for internal use");
1343 				YYERROR;
1344 			}
1345 
1346 			memset(&r, 0, sizeof(r));
1347 			if (pf->eastack[pf->asd + 1]) {
1348 				if ($3 && strchr($3, '/') != NULL) {
1349 					free($3);
1350 					yyerror("anchor paths containing '/' "
1351 					   "cannot be used for inline anchors.");
1352 					YYERROR;
1353 				}
1354 
1355 				/* Move inline rules into relative location. */
1356 				pfctl_eth_anchor_setup(pf, &r,
1357 				    &pf->eastack[pf->asd]->ruleset,
1358 				    $3 ? $3 : pf->ealast->name);
1359 				if (r.anchor == NULL)
1360 					err(1, "etheranchorrule: unable to "
1361 					    "create ruleset");
1362 
1363 				if (pf->ealast != r.anchor) {
1364 					if (r.anchor->match) {
1365 						yyerror("inline anchor '%s' "
1366 						    "already exists",
1367 						    r.anchor->name);
1368 						YYERROR;
1369 					}
1370 					mv_eth_rules(&pf->ealast->ruleset,
1371 					    &r.anchor->ruleset);
1372 				}
1373 				pf_remove_if_empty_eth_ruleset(&pf->ealast->ruleset);
1374 				pf->ealast = r.anchor;
1375 			} else {
1376 				if (!$3) {
1377 					yyerror("anchors without explicit "
1378 					    "rules must specify a name");
1379 					YYERROR;
1380 				}
1381 			}
1382 
1383 			r.direction = $4;
1384 			r.quick = $5.quick;
1385 
1386 			expand_eth_rule(&r, $6, $7, $8.src, $8.dst,
1387 			    $9.src.host, $9.dst.host, NULL,
1388 			    pf->eastack[pf->asd + 1] ? pf->ealast->name : $3);
1389 
1390 			free($3);
1391 			pf->eastack[pf->asd + 1] = NULL;
1392 		}
1393 		;
1394 
1395 etherfilter_opts	:	{
1396 				bzero(&filter_opts, sizeof filter_opts);
1397 			}
1398 		    etherfilter_opts_l
1399 			{ $$ = filter_opts; }
1400 		| /* empty */	{
1401 			bzero(&filter_opts, sizeof filter_opts);
1402 			$$ = filter_opts;
1403 		}
1404 		;
1405 
1406 etherfilter_opts_l	: etherfilter_opts_l etherfilter_opt
1407 			| etherfilter_opt
1408 
1409 etherfilter_opt	: etherqname	{
1410 			if (filter_opts.queues.qname) {
1411 				yyerror("queue cannot be redefined");
1412 				YYERROR;
1413 			}
1414 			filter_opts.queues = $1;
1415 		}
1416 		| RIDENTIFIER number {
1417 			filter_opts.ridentifier = $2;
1418 		}
1419 		| label	{
1420 			if (filter_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) {
1421 				yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT);
1422 				YYERROR;
1423 			}
1424 			filter_opts.label[filter_opts.labelcount++] = $1;
1425 		}
1426 		| TAG string				{
1427 			filter_opts.tag = $2;
1428 		}
1429 		| not TAGGED string			{
1430 			filter_opts.match_tag = $3;
1431 			filter_opts.match_tag_not = $1;
1432 		}
1433 		| DNPIPE number {
1434 			filter_opts.dnpipe = $2;
1435 			filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
1436 		}
1437 		| DNQUEUE number {
1438 			filter_opts.dnpipe = $2;
1439 			filter_opts.free_flags |= PFRULE_DN_IS_QUEUE;
1440 		}
1441 		;
1442 
1443 bridge		:	/* empty */		{
1444 			$$ = NULL;
1445 		}
1446 		| BRIDGE_TO STRING {
1447 			$$ = strdup($2);
1448 		}
1449 		;
1450 
1451 scrubrule	: scrubaction dir logquick interface af proto fromto scrub_opts
1452 		{
1453 			struct pfctl_rule	r;
1454 
1455 			if (check_rulestate(PFCTL_STATE_SCRUB))
1456 				YYERROR;
1457 
1458 			pfctl_init_rule(&r);
1459 
1460 			r.action = $1.b1;
1461 			r.direction = $2;
1462 
1463 			r.log = $3.log;
1464 			r.logif = $3.logif;
1465 			if ($3.quick) {
1466 				yyerror("scrub rules do not support 'quick'");
1467 				YYERROR;
1468 			}
1469 
1470 			r.af = $5;
1471 			if ($8.nodf)
1472 				r.rule_flag |= PFRULE_NODF;
1473 			if ($8.randomid)
1474 				r.rule_flag |= PFRULE_RANDOMID;
1475 			if ($8.reassemble_tcp) {
1476 				if (r.direction != PF_INOUT) {
1477 					yyerror("reassemble tcp rules can not "
1478 					    "specify direction");
1479 					YYERROR;
1480 				}
1481 				r.rule_flag |= PFRULE_REASSEMBLE_TCP;
1482 			}
1483 			if ($8.minttl)
1484 				r.min_ttl = $8.minttl;
1485 			if ($8.maxmss)
1486 				r.max_mss = $8.maxmss;
1487 			if ($8.marker & FOM_SETTOS) {
1488 				r.rule_flag |= PFRULE_SET_TOS;
1489 				r.set_tos = $8.settos;
1490 			}
1491 			if ($8.fragcache)
1492 				r.rule_flag |= $8.fragcache;
1493 			if ($8.match_tag)
1494 				if (strlcpy(r.match_tagname, $8.match_tag,
1495 				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
1496 					yyerror("tag too long, max %u chars",
1497 					    PF_TAG_NAME_SIZE - 1);
1498 					YYERROR;
1499 				}
1500 			r.match_tag_not = $8.match_tag_not;
1501 			r.rtableid = $8.rtableid;
1502 
1503 			expand_rule(&r, false, $4, NULL, NULL, NULL,
1504 			    $6, $7.src_os, $7.src.host, $7.src.port, $7.dst.host,
1505 			    $7.dst.port, NULL, NULL, NULL, NULL);
1506 		}
1507 		;
1508 
1509 scrub_opts	:	{
1510 				bzero(&scrub_opts, sizeof scrub_opts);
1511 				scrub_opts.rtableid = -1;
1512 			}
1513 		    scrub_opts_l
1514 			{ $$ = scrub_opts; }
1515 		| /* empty */ {
1516 			bzero(&scrub_opts, sizeof scrub_opts);
1517 			scrub_opts.rtableid = -1;
1518 			$$ = scrub_opts;
1519 		}
1520 		;
1521 
1522 scrub_opts_l	: scrub_opts_l comma scrub_opt
1523 		| scrub_opt
1524 		;
1525 
1526 scrub_opt	: NODF	{
1527 			if (scrub_opts.nodf) {
1528 				yyerror("no-df cannot be respecified");
1529 				YYERROR;
1530 			}
1531 			scrub_opts.nodf = 1;
1532 		}
1533 		| MINTTL NUMBER {
1534 			if (scrub_opts.marker & FOM_MINTTL) {
1535 				yyerror("min-ttl cannot be respecified");
1536 				YYERROR;
1537 			}
1538 			if ($2 < 0 || $2 > 255) {
1539 				yyerror("illegal min-ttl value %d", $2);
1540 				YYERROR;
1541 			}
1542 			scrub_opts.marker |= FOM_MINTTL;
1543 			scrub_opts.minttl = $2;
1544 		}
1545 		| MAXMSS NUMBER {
1546 			if (scrub_opts.marker & FOM_MAXMSS) {
1547 				yyerror("max-mss cannot be respecified");
1548 				YYERROR;
1549 			}
1550 			if ($2 < 0 || $2 > 65535) {
1551 				yyerror("illegal max-mss value %d", $2);
1552 				YYERROR;
1553 			}
1554 			scrub_opts.marker |= FOM_MAXMSS;
1555 			scrub_opts.maxmss = $2;
1556 		}
1557 		| SETTOS tos {
1558 			if (scrub_opts.marker & FOM_SETTOS) {
1559 				yyerror("set-tos cannot be respecified");
1560 				YYERROR;
1561 			}
1562 			scrub_opts.marker |= FOM_SETTOS;
1563 			scrub_opts.settos = $2;
1564 		}
1565 		| fragcache {
1566 			if (scrub_opts.marker & FOM_FRAGCACHE) {
1567 				yyerror("fragcache cannot be respecified");
1568 				YYERROR;
1569 			}
1570 			scrub_opts.marker |= FOM_FRAGCACHE;
1571 			scrub_opts.fragcache = $1;
1572 		}
1573 		| REASSEMBLE STRING {
1574 			if (strcasecmp($2, "tcp") != 0) {
1575 				yyerror("scrub reassemble supports only tcp, "
1576 				    "not '%s'", $2);
1577 				free($2);
1578 				YYERROR;
1579 			}
1580 			free($2);
1581 			if (scrub_opts.reassemble_tcp) {
1582 				yyerror("reassemble tcp cannot be respecified");
1583 				YYERROR;
1584 			}
1585 			scrub_opts.reassemble_tcp = 1;
1586 		}
1587 		| RANDOMID {
1588 			if (scrub_opts.randomid) {
1589 				yyerror("random-id cannot be respecified");
1590 				YYERROR;
1591 			}
1592 			scrub_opts.randomid = 1;
1593 		}
1594 		| RTABLE NUMBER				{
1595 			if ($2 < 0 || $2 > rt_tableid_max()) {
1596 				yyerror("invalid rtable id");
1597 				YYERROR;
1598 			}
1599 			scrub_opts.rtableid = $2;
1600 		}
1601 		| not TAGGED string			{
1602 			scrub_opts.match_tag = $3;
1603 			scrub_opts.match_tag_not = $1;
1604 		}
1605 		;
1606 
1607 fragcache	: FRAGMENT REASSEMBLE		{ $$ = 0; /* default */ }
1608 		| FRAGMENT NO REASSEMBLE	{ $$ = PFRULE_FRAGMENT_NOREASS; }
1609 		;
1610 
1611 antispoof	: ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
1612 			struct pfctl_rule	 r;
1613 			struct node_host	*h = NULL, *hh;
1614 			struct node_if		*i, *j;
1615 
1616 			if (check_rulestate(PFCTL_STATE_FILTER))
1617 				YYERROR;
1618 
1619 			for (i = $3; i; i = i->next) {
1620 				pfctl_init_rule(&r);
1621 
1622 				r.action = PF_DROP;
1623 				r.direction = PF_IN;
1624 				r.log = $2.log;
1625 				r.logif = $2.logif;
1626 				r.quick = $2.quick;
1627 				r.af = $4;
1628 				r.ridentifier = $5.ridentifier;
1629 				if (rule_label(&r, $5.label))
1630 					YYERROR;
1631 				r.rtableid = $5.rtableid;
1632 				j = calloc(1, sizeof(struct node_if));
1633 				if (j == NULL)
1634 					err(1, "antispoof: calloc");
1635 				if (strlcpy(j->ifname, i->ifname,
1636 				    sizeof(j->ifname)) >= sizeof(j->ifname)) {
1637 					free(j);
1638 					yyerror("interface name too long");
1639 					YYERROR;
1640 				}
1641 				j->not = 1;
1642 				if (i->dynamic) {
1643 					h = calloc(1, sizeof(*h));
1644 					if (h == NULL)
1645 						err(1, "address: calloc");
1646 					h->addr.type = PF_ADDR_DYNIFTL;
1647 					set_ipmask(h, 128);
1648 					if (strlcpy(h->addr.v.ifname, i->ifname,
1649 					    sizeof(h->addr.v.ifname)) >=
1650 					    sizeof(h->addr.v.ifname)) {
1651 						free(h);
1652 						yyerror(
1653 						    "interface name too long");
1654 						YYERROR;
1655 					}
1656 					hh = malloc(sizeof(*hh));
1657 					if (hh == NULL)
1658 						 err(1, "address: malloc");
1659 					bcopy(h, hh, sizeof(*hh));
1660 					h->addr.iflags = PFI_AFLAG_NETWORK;
1661 				} else {
1662 					h = ifa_lookup(j->ifname,
1663 					    PFI_AFLAG_NETWORK);
1664 					hh = NULL;
1665 				}
1666 
1667 				if (h != NULL)
1668 					expand_rule(&r, false, j, NULL, NULL,
1669 					    NULL, NULL, NULL, h, NULL, NULL,
1670 					    NULL, NULL, NULL, NULL, NULL);
1671 
1672 				if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
1673 					bzero(&r, sizeof(r));
1674 
1675 					r.action = PF_DROP;
1676 					r.direction = PF_IN;
1677 					r.log = $2.log;
1678 					r.logif = $2.logif;
1679 					r.quick = $2.quick;
1680 					r.af = $4;
1681 					r.ridentifier = $5.ridentifier;
1682 					if (rule_label(&r, $5.label))
1683 						YYERROR;
1684 					r.rtableid = $5.rtableid;
1685 					if (hh != NULL)
1686 						h = hh;
1687 					else
1688 						h = ifa_lookup(i->ifname, 0);
1689 					if (h != NULL)
1690 						expand_rule(&r, false, NULL,
1691 						    NULL, NULL, NULL, NULL,
1692 						    NULL, h, NULL, NULL, NULL,
1693 						    NULL, NULL, NULL, NULL);
1694 				} else
1695 					free(hh);
1696 			}
1697 			for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
1698 				free($5.label[i]);
1699 		}
1700 		;
1701 
1702 antispoof_ifspc	: FOR antispoof_if			{ $$ = $2; }
1703 		| FOR '{' optnl antispoof_iflst '}'	{ $$ = $4; }
1704 		;
1705 
1706 antispoof_iflst	: antispoof_if optnl			{ $$ = $1; }
1707 		| antispoof_iflst comma antispoof_if optnl {
1708 			$1->tail->next = $3;
1709 			$1->tail = $3;
1710 			$$ = $1;
1711 		}
1712 		;
1713 
1714 antispoof_if	: if_item				{ $$ = $1; }
1715 		| '(' if_item ')'			{
1716 			$2->dynamic = 1;
1717 			$$ = $2;
1718 		}
1719 		;
1720 
1721 antispoof_opts	:	{
1722 				bzero(&antispoof_opts, sizeof antispoof_opts);
1723 				antispoof_opts.rtableid = -1;
1724 			}
1725 		    antispoof_opts_l
1726 			{ $$ = antispoof_opts; }
1727 		| /* empty */	{
1728 			bzero(&antispoof_opts, sizeof antispoof_opts);
1729 			antispoof_opts.rtableid = -1;
1730 			$$ = antispoof_opts;
1731 		}
1732 		;
1733 
1734 antispoof_opts_l	: antispoof_opts_l antispoof_opt
1735 			| antispoof_opt
1736 			;
1737 
1738 antispoof_opt	: label	{
1739 			if (antispoof_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) {
1740 				yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT);
1741 				YYERROR;
1742 			}
1743 			antispoof_opts.label[antispoof_opts.labelcount++] = $1;
1744 		}
1745 		| RIDENTIFIER number {
1746 			antispoof_opts.ridentifier = $2;
1747 		}
1748 		| RTABLE NUMBER				{
1749 			if ($2 < 0 || $2 > rt_tableid_max()) {
1750 				yyerror("invalid rtable id");
1751 				YYERROR;
1752 			}
1753 			antispoof_opts.rtableid = $2;
1754 		}
1755 		;
1756 
1757 not		: '!'		{ $$ = 1; }
1758 		| /* empty */	{ $$ = 0; }
1759 		;
1760 
1761 tabledef	: TABLE '<' STRING '>' table_opts {
1762 			struct node_host	 *h, *nh;
1763 			struct node_tinit	 *ti, *nti;
1764 
1765 			if (strlen($3) >= PF_TABLE_NAME_SIZE) {
1766 				yyerror("table name too long, max %d chars",
1767 				    PF_TABLE_NAME_SIZE - 1);
1768 				free($3);
1769 				YYERROR;
1770 			}
1771 			if (pf->loadopt & PFCTL_FLAG_TABLE)
1772 				if (process_tabledef($3, &$5, pf->opts)) {
1773 					free($3);
1774 					YYERROR;
1775 				}
1776 			free($3);
1777 			for (ti = SIMPLEQ_FIRST(&$5.init_nodes);
1778 			    ti != SIMPLEQ_END(&$5.init_nodes); ti = nti) {
1779 				if (ti->file)
1780 					free(ti->file);
1781 				for (h = ti->host; h != NULL; h = nh) {
1782 					nh = h->next;
1783 					free(h);
1784 				}
1785 				nti = SIMPLEQ_NEXT(ti, entries);
1786 				free(ti);
1787 			}
1788 		}
1789 		;
1790 
1791 table_opts	:	{
1792 			bzero(&table_opts, sizeof table_opts);
1793 			SIMPLEQ_INIT(&table_opts.init_nodes);
1794 		}
1795 		    table_opts_l
1796 			{ $$ = table_opts; }
1797 		| /* empty */
1798 			{
1799 			bzero(&table_opts, sizeof table_opts);
1800 			SIMPLEQ_INIT(&table_opts.init_nodes);
1801 			$$ = table_opts;
1802 		}
1803 		;
1804 
1805 table_opts_l	: table_opts_l table_opt
1806 		| table_opt
1807 		;
1808 
1809 table_opt	: STRING		{
1810 			if (!strcmp($1, "const"))
1811 				table_opts.flags |= PFR_TFLAG_CONST;
1812 			else if (!strcmp($1, "persist"))
1813 				table_opts.flags |= PFR_TFLAG_PERSIST;
1814 			else if (!strcmp($1, "counters"))
1815 				table_opts.flags |= PFR_TFLAG_COUNTERS;
1816 			else {
1817 				yyerror("invalid table option '%s'", $1);
1818 				free($1);
1819 				YYERROR;
1820 			}
1821 			free($1);
1822 		}
1823 		| '{' optnl '}'		{ table_opts.init_addr = 1; }
1824 		| '{' optnl host_list '}'	{
1825 			struct node_host	*n;
1826 			struct node_tinit	*ti;
1827 
1828 			for (n = $3; n != NULL; n = n->next) {
1829 				switch (n->addr.type) {
1830 				case PF_ADDR_ADDRMASK:
1831 					continue; /* ok */
1832 				case PF_ADDR_RANGE:
1833 					yyerror("address ranges are not "
1834 					    "permitted inside tables");
1835 					break;
1836 				case PF_ADDR_DYNIFTL:
1837 					yyerror("dynamic addresses are not "
1838 					    "permitted inside tables");
1839 					break;
1840 				case PF_ADDR_TABLE:
1841 					yyerror("tables cannot contain tables");
1842 					break;
1843 				case PF_ADDR_NOROUTE:
1844 					yyerror("\"no-route\" is not permitted "
1845 					    "inside tables");
1846 					break;
1847 				case PF_ADDR_URPFFAILED:
1848 					yyerror("\"urpf-failed\" is not "
1849 					    "permitted inside tables");
1850 					break;
1851 				default:
1852 					yyerror("unknown address type %d",
1853 					    n->addr.type);
1854 				}
1855 				YYERROR;
1856 			}
1857 			if (!(ti = calloc(1, sizeof(*ti))))
1858 				err(1, "table_opt: calloc");
1859 			ti->host = $3;
1860 			SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
1861 			    entries);
1862 			table_opts.init_addr = 1;
1863 		}
1864 		| FILENAME STRING	{
1865 			struct node_tinit	*ti;
1866 
1867 			if (!(ti = calloc(1, sizeof(*ti))))
1868 				err(1, "table_opt: calloc");
1869 			ti->file = $2;
1870 			SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
1871 			    entries);
1872 			table_opts.init_addr = 1;
1873 		}
1874 		;
1875 
1876 altqif		: ALTQ interface queue_opts QUEUE qassign {
1877 			struct pf_altq	a;
1878 
1879 			if (check_rulestate(PFCTL_STATE_QUEUE))
1880 				YYERROR;
1881 
1882 			memset(&a, 0, sizeof(a));
1883 			if ($3.scheduler.qtype == ALTQT_NONE) {
1884 				yyerror("no scheduler specified!");
1885 				YYERROR;
1886 			}
1887 			a.scheduler = $3.scheduler.qtype;
1888 			a.qlimit = $3.qlimit;
1889 			a.tbrsize = $3.tbrsize;
1890 			if ($5 == NULL && $3.scheduler.qtype != ALTQT_CODEL) {
1891 				yyerror("no child queues specified");
1892 				YYERROR;
1893 			}
1894 			if (expand_altq(&a, $2, $5, $3.queue_bwspec,
1895 			    &$3.scheduler))
1896 				YYERROR;
1897 		}
1898 		;
1899 
1900 queuespec	: QUEUE STRING interface queue_opts qassign {
1901 			struct pf_altq	a;
1902 
1903 			if (check_rulestate(PFCTL_STATE_QUEUE)) {
1904 				free($2);
1905 				YYERROR;
1906 			}
1907 
1908 			memset(&a, 0, sizeof(a));
1909 
1910 			if (strlcpy(a.qname, $2, sizeof(a.qname)) >=
1911 			    sizeof(a.qname)) {
1912 				yyerror("queue name too long (max "
1913 				    "%d chars)", PF_QNAME_SIZE-1);
1914 				free($2);
1915 				YYERROR;
1916 			}
1917 			free($2);
1918 			if ($4.tbrsize) {
1919 				yyerror("cannot specify tbrsize for queue");
1920 				YYERROR;
1921 			}
1922 			if ($4.priority > 255) {
1923 				yyerror("priority out of range: max 255");
1924 				YYERROR;
1925 			}
1926 			a.priority = $4.priority;
1927 			a.qlimit = $4.qlimit;
1928 			a.scheduler = $4.scheduler.qtype;
1929 			if (expand_queue(&a, $3, $5, $4.queue_bwspec,
1930 			    &$4.scheduler)) {
1931 				yyerror("errors in queue definition");
1932 				YYERROR;
1933 			}
1934 		}
1935 		;
1936 
1937 queue_opts	:	{
1938 			bzero(&queue_opts, sizeof queue_opts);
1939 			queue_opts.priority = DEFAULT_PRIORITY;
1940 			queue_opts.qlimit = DEFAULT_QLIMIT;
1941 			queue_opts.scheduler.qtype = ALTQT_NONE;
1942 			queue_opts.queue_bwspec.bw_percent = 100;
1943 		}
1944 		    queue_opts_l
1945 			{ $$ = queue_opts; }
1946 		| /* empty */ {
1947 			bzero(&queue_opts, sizeof queue_opts);
1948 			queue_opts.priority = DEFAULT_PRIORITY;
1949 			queue_opts.qlimit = DEFAULT_QLIMIT;
1950 			queue_opts.scheduler.qtype = ALTQT_NONE;
1951 			queue_opts.queue_bwspec.bw_percent = 100;
1952 			$$ = queue_opts;
1953 		}
1954 		;
1955 
1956 queue_opts_l	: queue_opts_l queue_opt
1957 		| queue_opt
1958 		;
1959 
1960 queue_opt	: BANDWIDTH bandwidth	{
1961 			if (queue_opts.marker & QOM_BWSPEC) {
1962 				yyerror("bandwidth cannot be respecified");
1963 				YYERROR;
1964 			}
1965 			queue_opts.marker |= QOM_BWSPEC;
1966 			queue_opts.queue_bwspec = $2;
1967 		}
1968 		| PRIORITY NUMBER	{
1969 			if (queue_opts.marker & QOM_PRIORITY) {
1970 				yyerror("priority cannot be respecified");
1971 				YYERROR;
1972 			}
1973 			if ($2 < 0 || $2 > 255) {
1974 				yyerror("priority out of range: max 255");
1975 				YYERROR;
1976 			}
1977 			queue_opts.marker |= QOM_PRIORITY;
1978 			queue_opts.priority = $2;
1979 		}
1980 		| QLIMIT NUMBER	{
1981 			if (queue_opts.marker & QOM_QLIMIT) {
1982 				yyerror("qlimit cannot be respecified");
1983 				YYERROR;
1984 			}
1985 			if ($2 < 0 || $2 > 65535) {
1986 				yyerror("qlimit out of range: max 65535");
1987 				YYERROR;
1988 			}
1989 			queue_opts.marker |= QOM_QLIMIT;
1990 			queue_opts.qlimit = $2;
1991 		}
1992 		| scheduler	{
1993 			if (queue_opts.marker & QOM_SCHEDULER) {
1994 				yyerror("scheduler cannot be respecified");
1995 				YYERROR;
1996 			}
1997 			queue_opts.marker |= QOM_SCHEDULER;
1998 			queue_opts.scheduler = $1;
1999 		}
2000 		| TBRSIZE NUMBER	{
2001 			if (queue_opts.marker & QOM_TBRSIZE) {
2002 				yyerror("tbrsize cannot be respecified");
2003 				YYERROR;
2004 			}
2005 			if ($2 < 0 || $2 > UINT_MAX) {
2006 				yyerror("tbrsize too big: max %u", UINT_MAX);
2007 				YYERROR;
2008 			}
2009 			queue_opts.marker |= QOM_TBRSIZE;
2010 			queue_opts.tbrsize = $2;
2011 		}
2012 		;
2013 
2014 bandwidth	: STRING {
2015 			double	 bps;
2016 			char	*cp;
2017 
2018 			$$.bw_percent = 0;
2019 
2020 			bps = strtod($1, &cp);
2021 			if (cp != NULL) {
2022 				if (strlen(cp) > 1) {
2023 					char *cu = cp + 1;
2024 					if (!strcmp(cu, "Bit") ||
2025 					    !strcmp(cu, "B") ||
2026 					    !strcmp(cu, "bit") ||
2027 					    !strcmp(cu, "b")) {
2028 						*cu = 0;
2029 					}
2030 				}
2031 				if (!strcmp(cp, "b"))
2032 					; /* nothing */
2033 				else if (!strcmp(cp, "K"))
2034 					bps *= 1000;
2035 				else if (!strcmp(cp, "M"))
2036 					bps *= 1000 * 1000;
2037 				else if (!strcmp(cp, "G"))
2038 					bps *= 1000 * 1000 * 1000;
2039 				else if (!strcmp(cp, "%")) {
2040 					if (bps < 0 || bps > 100) {
2041 						yyerror("bandwidth spec "
2042 						    "out of range");
2043 						free($1);
2044 						YYERROR;
2045 					}
2046 					$$.bw_percent = bps;
2047 					bps = 0;
2048 				} else {
2049 					yyerror("unknown unit %s", cp);
2050 					free($1);
2051 					YYERROR;
2052 				}
2053 			}
2054 			free($1);
2055 			$$.bw_absolute = (u_int64_t)bps;
2056 		}
2057 		| NUMBER {
2058 			if ($1 < 0 || $1 >= LLONG_MAX) {
2059 				yyerror("bandwidth number too big");
2060 				YYERROR;
2061 			}
2062 			$$.bw_percent = 0;
2063 			$$.bw_absolute = $1;
2064 		}
2065 		;
2066 
2067 scheduler	: CBQ				{
2068 			$$.qtype = ALTQT_CBQ;
2069 			$$.data.cbq_opts.flags = 0;
2070 		}
2071 		| CBQ '(' cbqflags_list ')'	{
2072 			$$.qtype = ALTQT_CBQ;
2073 			$$.data.cbq_opts.flags = $3;
2074 		}
2075 		| PRIQ				{
2076 			$$.qtype = ALTQT_PRIQ;
2077 			$$.data.priq_opts.flags = 0;
2078 		}
2079 		| PRIQ '(' priqflags_list ')'	{
2080 			$$.qtype = ALTQT_PRIQ;
2081 			$$.data.priq_opts.flags = $3;
2082 		}
2083 		| HFSC				{
2084 			$$.qtype = ALTQT_HFSC;
2085 			bzero(&$$.data.hfsc_opts,
2086 			    sizeof(struct node_hfsc_opts));
2087 		}
2088 		| HFSC '(' hfsc_opts ')'	{
2089 			$$.qtype = ALTQT_HFSC;
2090 			$$.data.hfsc_opts = $3;
2091 		}
2092 		| FAIRQ				{
2093 			$$.qtype = ALTQT_FAIRQ;
2094 			bzero(&$$.data.fairq_opts,
2095 				sizeof(struct node_fairq_opts));
2096 		}
2097 		| FAIRQ '(' fairq_opts ')'      {
2098 			$$.qtype = ALTQT_FAIRQ;
2099 			$$.data.fairq_opts = $3;
2100 		}
2101 		| CODEL				{
2102 			$$.qtype = ALTQT_CODEL;
2103 			bzero(&$$.data.codel_opts,
2104 				sizeof(struct codel_opts));
2105 		}
2106 		| CODEL '(' codel_opts ')'	{
2107 			$$.qtype = ALTQT_CODEL;
2108 			$$.data.codel_opts = $3;
2109 		}
2110 		;
2111 
2112 cbqflags_list	: cbqflags_item				{ $$ |= $1; }
2113 		| cbqflags_list comma cbqflags_item	{ $$ |= $3; }
2114 		;
2115 
2116 cbqflags_item	: STRING	{
2117 			if (!strcmp($1, "default"))
2118 				$$ = CBQCLF_DEFCLASS;
2119 			else if (!strcmp($1, "borrow"))
2120 				$$ = CBQCLF_BORROW;
2121 			else if (!strcmp($1, "red"))
2122 				$$ = CBQCLF_RED;
2123 			else if (!strcmp($1, "ecn"))
2124 				$$ = CBQCLF_RED|CBQCLF_ECN;
2125 			else if (!strcmp($1, "rio"))
2126 				$$ = CBQCLF_RIO;
2127 			else if (!strcmp($1, "codel"))
2128 				$$ = CBQCLF_CODEL;
2129 			else {
2130 				yyerror("unknown cbq flag \"%s\"", $1);
2131 				free($1);
2132 				YYERROR;
2133 			}
2134 			free($1);
2135 		}
2136 		;
2137 
2138 priqflags_list	: priqflags_item			{ $$ |= $1; }
2139 		| priqflags_list comma priqflags_item	{ $$ |= $3; }
2140 		;
2141 
2142 priqflags_item	: STRING	{
2143 			if (!strcmp($1, "default"))
2144 				$$ = PRCF_DEFAULTCLASS;
2145 			else if (!strcmp($1, "red"))
2146 				$$ = PRCF_RED;
2147 			else if (!strcmp($1, "ecn"))
2148 				$$ = PRCF_RED|PRCF_ECN;
2149 			else if (!strcmp($1, "rio"))
2150 				$$ = PRCF_RIO;
2151 			else if (!strcmp($1, "codel"))
2152 				$$ = PRCF_CODEL;
2153 			else {
2154 				yyerror("unknown priq flag \"%s\"", $1);
2155 				free($1);
2156 				YYERROR;
2157 			}
2158 			free($1);
2159 		}
2160 		;
2161 
2162 hfsc_opts	:	{
2163 				bzero(&hfsc_opts,
2164 				    sizeof(struct node_hfsc_opts));
2165 			}
2166 		    hfscopts_list				{
2167 			$$ = hfsc_opts;
2168 		}
2169 		;
2170 
2171 hfscopts_list	: hfscopts_item
2172 		| hfscopts_list comma hfscopts_item
2173 		;
2174 
2175 hfscopts_item	: LINKSHARE bandwidth				{
2176 			if (hfsc_opts.linkshare.used) {
2177 				yyerror("linkshare already specified");
2178 				YYERROR;
2179 			}
2180 			hfsc_opts.linkshare.m2 = $2;
2181 			hfsc_opts.linkshare.used = 1;
2182 		}
2183 		| LINKSHARE '(' bandwidth comma NUMBER comma bandwidth ')'
2184 		    {
2185 			if ($5 < 0 || $5 > INT_MAX) {
2186 				yyerror("timing in curve out of range");
2187 				YYERROR;
2188 			}
2189 			if (hfsc_opts.linkshare.used) {
2190 				yyerror("linkshare already specified");
2191 				YYERROR;
2192 			}
2193 			hfsc_opts.linkshare.m1 = $3;
2194 			hfsc_opts.linkshare.d = $5;
2195 			hfsc_opts.linkshare.m2 = $7;
2196 			hfsc_opts.linkshare.used = 1;
2197 		}
2198 		| REALTIME bandwidth				{
2199 			if (hfsc_opts.realtime.used) {
2200 				yyerror("realtime already specified");
2201 				YYERROR;
2202 			}
2203 			hfsc_opts.realtime.m2 = $2;
2204 			hfsc_opts.realtime.used = 1;
2205 		}
2206 		| REALTIME '(' bandwidth comma NUMBER comma bandwidth ')'
2207 		    {
2208 			if ($5 < 0 || $5 > INT_MAX) {
2209 				yyerror("timing in curve out of range");
2210 				YYERROR;
2211 			}
2212 			if (hfsc_opts.realtime.used) {
2213 				yyerror("realtime already specified");
2214 				YYERROR;
2215 			}
2216 			hfsc_opts.realtime.m1 = $3;
2217 			hfsc_opts.realtime.d = $5;
2218 			hfsc_opts.realtime.m2 = $7;
2219 			hfsc_opts.realtime.used = 1;
2220 		}
2221 		| UPPERLIMIT bandwidth				{
2222 			if (hfsc_opts.upperlimit.used) {
2223 				yyerror("upperlimit already specified");
2224 				YYERROR;
2225 			}
2226 			hfsc_opts.upperlimit.m2 = $2;
2227 			hfsc_opts.upperlimit.used = 1;
2228 		}
2229 		| UPPERLIMIT '(' bandwidth comma NUMBER comma bandwidth ')'
2230 		    {
2231 			if ($5 < 0 || $5 > INT_MAX) {
2232 				yyerror("timing in curve out of range");
2233 				YYERROR;
2234 			}
2235 			if (hfsc_opts.upperlimit.used) {
2236 				yyerror("upperlimit already specified");
2237 				YYERROR;
2238 			}
2239 			hfsc_opts.upperlimit.m1 = $3;
2240 			hfsc_opts.upperlimit.d = $5;
2241 			hfsc_opts.upperlimit.m2 = $7;
2242 			hfsc_opts.upperlimit.used = 1;
2243 		}
2244 		| STRING	{
2245 			if (!strcmp($1, "default"))
2246 				hfsc_opts.flags |= HFCF_DEFAULTCLASS;
2247 			else if (!strcmp($1, "red"))
2248 				hfsc_opts.flags |= HFCF_RED;
2249 			else if (!strcmp($1, "ecn"))
2250 				hfsc_opts.flags |= HFCF_RED|HFCF_ECN;
2251 			else if (!strcmp($1, "rio"))
2252 				hfsc_opts.flags |= HFCF_RIO;
2253 			else if (!strcmp($1, "codel"))
2254 				hfsc_opts.flags |= HFCF_CODEL;
2255 			else {
2256 				yyerror("unknown hfsc flag \"%s\"", $1);
2257 				free($1);
2258 				YYERROR;
2259 			}
2260 			free($1);
2261 		}
2262 		;
2263 
2264 fairq_opts	:	{
2265 				bzero(&fairq_opts,
2266 				    sizeof(struct node_fairq_opts));
2267 			}
2268 		    fairqopts_list				{
2269 			$$ = fairq_opts;
2270 		}
2271 		;
2272 
2273 fairqopts_list	: fairqopts_item
2274 		| fairqopts_list comma fairqopts_item
2275 		;
2276 
2277 fairqopts_item	: LINKSHARE bandwidth				{
2278 			if (fairq_opts.linkshare.used) {
2279 				yyerror("linkshare already specified");
2280 				YYERROR;
2281 			}
2282 			fairq_opts.linkshare.m2 = $2;
2283 			fairq_opts.linkshare.used = 1;
2284 		}
2285 		| LINKSHARE '(' bandwidth number bandwidth ')'	{
2286 			if (fairq_opts.linkshare.used) {
2287 				yyerror("linkshare already specified");
2288 				YYERROR;
2289 			}
2290 			fairq_opts.linkshare.m1 = $3;
2291 			fairq_opts.linkshare.d = $4;
2292 			fairq_opts.linkshare.m2 = $5;
2293 			fairq_opts.linkshare.used = 1;
2294 		}
2295 		| HOGS bandwidth {
2296 			fairq_opts.hogs_bw = $2;
2297 		}
2298 		| BUCKETS number {
2299 			fairq_opts.nbuckets = $2;
2300 		}
2301 		| STRING	{
2302 			if (!strcmp($1, "default"))
2303 				fairq_opts.flags |= FARF_DEFAULTCLASS;
2304 			else if (!strcmp($1, "red"))
2305 				fairq_opts.flags |= FARF_RED;
2306 			else if (!strcmp($1, "ecn"))
2307 				fairq_opts.flags |= FARF_RED|FARF_ECN;
2308 			else if (!strcmp($1, "rio"))
2309 				fairq_opts.flags |= FARF_RIO;
2310 			else if (!strcmp($1, "codel"))
2311 				fairq_opts.flags |= FARF_CODEL;
2312 			else {
2313 				yyerror("unknown fairq flag \"%s\"", $1);
2314 				free($1);
2315 				YYERROR;
2316 			}
2317 			free($1);
2318 		}
2319 		;
2320 
2321 codel_opts	:	{
2322 				bzero(&codel_opts,
2323 				    sizeof(struct codel_opts));
2324 			}
2325 		    codelopts_list				{
2326 			$$ = codel_opts;
2327 		}
2328 		;
2329 
2330 codelopts_list	: codelopts_item
2331 		| codelopts_list comma codelopts_item
2332 		;
2333 
2334 codelopts_item	: INTERVAL number				{
2335 			if (codel_opts.interval) {
2336 				yyerror("interval already specified");
2337 				YYERROR;
2338 			}
2339 			codel_opts.interval = $2;
2340 		}
2341 		| TARGET number					{
2342 			if (codel_opts.target) {
2343 				yyerror("target already specified");
2344 				YYERROR;
2345 			}
2346 			codel_opts.target = $2;
2347 		}
2348 		| STRING					{
2349 			if (!strcmp($1, "ecn"))
2350 				codel_opts.ecn = 1;
2351 			else {
2352 				yyerror("unknown codel option \"%s\"", $1);
2353 				free($1);
2354 				YYERROR;
2355 			}
2356 			free($1);
2357 		}
2358 		;
2359 
2360 qassign		: /* empty */		{ $$ = NULL; }
2361 		| qassign_item		{ $$ = $1; }
2362 		| '{' optnl qassign_list '}'	{ $$ = $3; }
2363 		;
2364 
2365 qassign_list	: qassign_item optnl		{ $$ = $1; }
2366 		| qassign_list comma qassign_item optnl	{
2367 			$1->tail->next = $3;
2368 			$1->tail = $3;
2369 			$$ = $1;
2370 		}
2371 		;
2372 
2373 qassign_item	: STRING			{
2374 			$$ = calloc(1, sizeof(struct node_queue));
2375 			if ($$ == NULL)
2376 				err(1, "qassign_item: calloc");
2377 			if (strlcpy($$->queue, $1, sizeof($$->queue)) >=
2378 			    sizeof($$->queue)) {
2379 				yyerror("queue name '%s' too long (max "
2380 				    "%d chars)", $1, sizeof($$->queue)-1);
2381 				free($1);
2382 				free($$);
2383 				YYERROR;
2384 			}
2385 			free($1);
2386 			$$->next = NULL;
2387 			$$->tail = $$;
2388 		}
2389 		;
2390 
2391 statelim		: statelim_nm statelim_opts {
2392 			struct pfctl_statelim *stlim;
2393 			size_t len;
2394 
2395 			if (!ISSET($2->marker, STATELIM_M_ID)) {
2396 				yyerror("id not specified");
2397 				free($1);
2398 				YYERROR;
2399 			}
2400 			if (!ISSET($2->marker, STATELIM_M_LIMIT)) {
2401 				yyerror("limit not specified");
2402 				free($1);
2403 				YYERROR;
2404 			}
2405 
2406 			stlim = calloc(1, sizeof(*stlim));
2407 			if (stlim == NULL)
2408 				err(1, "state limiter: malloc");
2409 
2410 			len = strlcpy(stlim->ioc.name, $1,
2411 			    sizeof(stlim->ioc.name));
2412 			free($1);
2413 			if (len >= sizeof(stlim->ioc.name)) {
2414 				/* abort? */
2415 				YYERROR;
2416 			}
2417 
2418 			stlim->ioc.id = $2->id;
2419 			stlim->ioc.limit = $2->limit;
2420 			stlim->ioc.rate.limit = $2->rate.limit;
2421 			stlim->ioc.rate.seconds = $2->rate.seconds;
2422 
2423 			if (pfctl_add_statelim(pf, stlim) != 0) {
2424 				yyerror("state limiter %s id %u"
2425 				    " already exists",
2426 				    stlim->ioc.name, stlim->ioc.id);
2427 				free(stlim);
2428 				YYERROR;
2429 			}
2430 		}
2431 		;
2432 
2433 statelim_nm		: STATE LIMITER string {
2434 			size_t len = strlen($3);
2435 			if (len < 1) {
2436 				yyerror("state limiter name is too short");
2437 				free($3);
2438 				YYERROR;
2439 			}
2440 			if (len >= PF_STATELIM_NAME_LEN) {
2441 				yyerror("state limiter name is too long");
2442 				free($3);
2443 				YYERROR;
2444 			}
2445 			$$ = $3;
2446 		}
2447 		;
2448 
2449 statelim_id		: ID NUMBER {
2450 			if ($2 < PF_STATELIM_ID_MIN ||
2451 			    $2 > PF_STATELIM_ID_MAX) {
2452 				yyerror("state limiter id %lld: "
2453 				    "invalid identifier", $2);
2454 				YYERROR;
2455 			}
2456 
2457 			$$ = $2;
2458 		}
2459 		;
2460 
2461 statelim_opts		: /* empty */ {
2462 			yyerror("state limiter missing options");
2463 			YYERROR;
2464 		}
2465 		| {
2466 			memset(&statelim_opts, 0, sizeof(statelim_opts));
2467 		} statelim_opts_l {
2468 			$$ = &statelim_opts;
2469 		}
2470 		;
2471 
2472 statelim_opts_l		: statelim_opts_l statelim_opt
2473 		| statelim_opt
2474 		;
2475 
2476 statelim_opt		: statelim_id {
2477 			if (ISSET(statelim_opts.marker, STATELIM_M_ID)) {
2478 				yyerror("id cannot be respecified");
2479 				YYERROR;
2480 			}
2481 
2482 			statelim_opts.id = $1;
2483 
2484 			statelim_opts.marker |= STATELIM_M_ID;
2485 		}
2486 		| LIMIT NUMBER  {
2487 			if (ISSET(statelim_opts.marker, STATELIM_M_LIMIT)) {
2488 				yyerror("limit cannot be respecified");
2489 				YYERROR;
2490 			}
2491 
2492 			if ($2 < PF_STATELIM_LIMIT_MIN ||
2493 			    $2 > PF_STATELIM_LIMIT_MAX) {
2494 				yyerror("invalid state limiter limit");
2495 				YYERROR;
2496 			}
2497 
2498 			statelim_opts.limit = $2;
2499 
2500 			statelim_opts.marker |= STATELIM_M_LIMIT;
2501 		}
2502 		| RATE NUMBER '/' NUMBER {
2503 			if (ISSET(statelim_opts.marker, STATELIM_M_RATE)) {
2504 				yyerror("rate cannot be respecified");
2505 				YYERROR;
2506 			}
2507 			if ($2 < 1) {
2508 				yyerror("invalid rate limit %lld", $2);
2509 				YYERROR;
2510 			}
2511 			if ($4 < 1) {
2512 				yyerror("invalid rate seconds %lld", $4);
2513 				YYERROR;
2514 			}
2515 
2516 			statelim_opts.rate.limit = $2;
2517 			statelim_opts.rate.seconds = $4;
2518 
2519 			statelim_opts.marker |= STATELIM_M_RATE;
2520 		}
2521 		;
2522 
2523 statelim_filter_opt
2524 		: STATE LIMITER STRING limiter_opt_spec {
2525 			struct pfctl_statelim *stlim;
2526 
2527 			stlim = pfctl_get_statelim_nm(pf, $3);
2528 			free($3);
2529 			if (stlim == NULL) {
2530 				yyerror("state limiter not found");
2531 				YYERROR;
2532 			}
2533 
2534 			$$.id = stlim->ioc.id;
2535 			$$.limiter_action = $4;
2536 		}
2537 		| STATE LIMITER statelim_id limiter_opt_spec {
2538 			$$.id = $3;
2539 			$$.limiter_action = $4;
2540 		}
2541 		;
2542 
2543 sourcelim		: sourcelim_nm sourcelim_opts {
2544 			struct pfctl_sourcelim *srlim;
2545 			size_t len;
2546 
2547 			if (!ISSET($2->marker, SOURCELIM_M_ID)) {
2548 				yyerror("id not specified");
2549 				free($1);
2550 				YYERROR;
2551 			}
2552 			if (!ISSET($2->marker, SOURCELIM_M_ENTRIES)) {
2553 				yyerror("entries not specified");
2554 				free($1);
2555 				YYERROR;
2556 			}
2557 			if (!ISSET($2->marker, SOURCELIM_M_LIMIT)) {
2558 				yyerror("state limit not specified");
2559 				free($1);
2560 				YYERROR;
2561 			}
2562 
2563 			srlim = calloc(1, sizeof(*srlim));
2564 			if (srlim == NULL)
2565 				err(1, "source limiter: malloc");
2566 
2567 			len = strlcpy(srlim->ioc.name, $1,
2568 			    sizeof(srlim->ioc.name));
2569 			free($1);
2570 			if (len >= sizeof(srlim->ioc.name)) {
2571 				/* abort? */
2572 				YYERROR;
2573 			}
2574 
2575 			srlim->ioc.id = $2->id;
2576 			srlim->ioc.entries = $2->entries;
2577 			srlim->ioc.limit = $2->limit;
2578 			srlim->ioc.rate.limit = $2->rate.limit;
2579 			srlim->ioc.rate.seconds = $2->rate.seconds;
2580 
2581 			if (ISSET($2->marker, SOURCELIM_M_TABLE)) {
2582 				if (strlcpy(srlim->ioc.overload_tblname,
2583 				    $2->table.name,
2584 				    sizeof(srlim->ioc.overload_tblname)) >=
2585 				    sizeof(srlim->ioc.overload_tblname)) {
2586 					abort();
2587 				}
2588 				srlim->ioc.overload_hwm = $2->table.above;
2589 				srlim->ioc.overload_lwm = $2->table.below;
2590 			}
2591 
2592 			srlim->ioc.inet_prefix = $2->inet_mask;
2593 			srlim->ioc.inet6_prefix = $2->inet6_mask;
2594 
2595 			if (pfctl_add_sourcelim(pf, srlim) != 0) {
2596 				yyerror("source limiter %s id %u"
2597 				    " already exists",
2598 				    srlim->ioc.name, srlim->ioc.id);
2599 				free(srlim);
2600 				YYERROR;
2601 			}
2602 		}
2603 		;
2604 
2605 sourcelim_nm		: SOURCE LIMITER string {
2606 			size_t len = strlen($3);
2607 			if (len < 1) {
2608 				yyerror("source limiter name is too short");
2609 				free($3);
2610 				YYERROR;
2611 			}
2612 			if (len >= PF_SOURCELIM_NAME_LEN) {
2613 				yyerror("source limiter name is too long");
2614 				free($3);
2615 				YYERROR;
2616 			}
2617 			$$ = $3;
2618 		}
2619 		;
2620 
2621 sourcelim_id		: ID NUMBER {
2622 			if ($2 < PF_SOURCELIM_ID_MIN ||
2623 			    $2 > PF_SOURCELIM_ID_MAX) {
2624 				yyerror("source limiter id %lld: "
2625 				    "invalid identifier", $2);
2626 				YYERROR;
2627 			}
2628 
2629 			$$ = $2;
2630 		}
2631 		;
2632 
2633 sourcelim_opts		: /* empty */ {
2634 			yyerror("source limiter missing options");
2635 			YYERROR;
2636 		}
2637 		| {
2638 			memset(&sourcelim_opts, 0, sizeof(sourcelim_opts));
2639 			sourcelim_opts.inet_mask = 32;
2640 			sourcelim_opts.inet6_mask = 128;
2641 		} sourcelim_opts_l {
2642 			$$ = &sourcelim_opts;
2643 		}
2644 		;
2645 
2646 sourcelim_opts_l		: sourcelim_opts_l sourcelim_opt
2647 		| sourcelim_opt
2648 		;
2649 
2650 sourcelim_opt		: sourcelim_id {
2651 			if (ISSET(sourcelim_opts.marker, SOURCELIM_M_ID)) {
2652 				yyerror("entries cannot be respecified");
2653 				YYERROR;
2654 			}
2655 
2656 			sourcelim_opts.id = $1;
2657 
2658 			sourcelim_opts.marker |= SOURCELIM_M_ID;
2659 		}
2660 		| ENTRIES NUMBER {
2661 			if (ISSET(sourcelim_opts.marker, SOURCELIM_M_ENTRIES)) {
2662 				yyerror("entries cannot be respecified");
2663 				YYERROR;
2664 			}
2665 
2666 			sourcelim_opts.entries = $2;
2667 
2668 			sourcelim_opts.marker |= SOURCELIM_M_ENTRIES;
2669 		}
2670 		| LIMIT NUMBER {
2671 			if (ISSET(sourcelim_opts.marker, SOURCELIM_M_LIMIT)) {
2672 				yyerror("state limit cannot be respecified");
2673 				YYERROR;
2674 			}
2675 
2676 			sourcelim_opts.limit = $2;
2677 
2678 			sourcelim_opts.marker |= SOURCELIM_M_LIMIT;
2679 		}
2680 		| RATE NUMBER '/' NUMBER {
2681 			if (ISSET(sourcelim_opts.marker, SOURCELIM_M_RATE)) {
2682 				yyerror("rate cannot be respecified");
2683 				YYERROR;
2684 			}
2685 
2686 			sourcelim_opts.rate.limit = $2;
2687 			sourcelim_opts.rate.seconds = $4;
2688 
2689 			sourcelim_opts.marker |= SOURCELIM_M_RATE;
2690 		}
2691 		| TABLE '<' STRING '>' ABOVE NUMBER sourcelim_opt_below {
2692 			size_t stringlen;
2693 
2694 			if (ISSET(sourcelim_opts.marker, SOURCELIM_M_TABLE)) {
2695 				free($3);
2696 				yyerror("rate cannot be respecified");
2697 				YYERROR;
2698 			}
2699 
2700 			stringlen = strlcpy(sourcelim_opts.table.name,
2701 			    $3, sizeof(sourcelim_opts.table.name));
2702 			free($3);
2703 			if (stringlen == 0 ||
2704 			    stringlen >= PF_TABLE_NAME_SIZE) {
2705 				yyerror("invalid table name");
2706 				YYERROR;
2707 			}
2708 
2709 			if ($6 < 0) {
2710 				yyerror("above limit is invalid");
2711 				YYERROR;
2712 			}
2713 			if ($7 > $6) {
2714 				yyerror("below limit higher than above limit");
2715 				YYERROR;
2716 			}
2717 
2718 			sourcelim_opts.table.above = $6;
2719 			sourcelim_opts.table.below = $7;
2720 
2721 			sourcelim_opts.marker |= SOURCELIM_M_TABLE;
2722 		}
2723 		| INET MASK NUMBER {
2724 			if (ISSET(sourcelim_opts.marker,
2725 			    SOURCELIM_M_INET_MASK)) {
2726 				yyerror("inet mask cannot be respecified");
2727 				YYERROR;
2728 			}
2729 
2730 			if ($3 < 1 || $3 > 32) {
2731 				yyerror("inet mask length out of range");
2732 				YYERROR;
2733 			}
2734 
2735 			sourcelim_opts.inet_mask = $3;
2736 
2737 			sourcelim_opts.marker |= SOURCELIM_M_INET_MASK;
2738 		}
2739 		| INET6 MASK NUMBER {
2740 			if (ISSET(sourcelim_opts.marker,
2741 			    SOURCELIM_M_INET6_MASK)) {
2742 				yyerror("inet6 mask cannot be respecified");
2743 				YYERROR;
2744 			}
2745 
2746 			if ($3 < 1 || $3 > 128) {
2747 				yyerror("inet6 mask length out of range");
2748 				YYERROR;
2749 			}
2750 
2751 			sourcelim_opts.inet6_mask = $3;
2752 
2753 			sourcelim_opts.marker |= SOURCELIM_M_INET6_MASK;
2754 		}
2755 		;
2756 
2757 sourcelim_opt_below
2758 		: /* empty */ {
2759 			$$ = 0;
2760 		}
2761 		| BELOW NUMBER {
2762 			if ($2 < 1) {
2763 				yyerror("below limit is invalid");
2764 				YYERROR;
2765 			}
2766 			$$ = $2;
2767 		}
2768 		;
2769 
2770 sourcelim_filter_opt
2771 		: SOURCE LIMITER STRING limiter_opt_spec {
2772 			struct pfctl_sourcelim *srlim;
2773 
2774 			srlim = pfctl_get_sourcelim_nm(pf, $3);
2775 			free($3);
2776 			if (srlim == NULL) {
2777 				yyerror("source limiter not found");
2778 				YYERROR;
2779 			}
2780 
2781 			$$.id = srlim->ioc.id;
2782 			$$.limiter_action = $4;
2783 		}
2784 		| SOURCE LIMITER sourcelim_id limiter_opt_spec {
2785 			$$.id = $3;
2786 			$$.limiter_action = $4;
2787 		}
2788 		;
2789 
2790 limiter_opt_spec: /* empty */ { $$ = PF_LIMITER_DEFAULT; }
2791 		| '(' limiter_opt ')' { $$ = $2; }
2792 		;
2793 
2794 limiter_opt:   BLOCK {
2795 			$$ = PF_LIMITER_BLOCK;
2796 		}
2797 		| NOMATCH {
2798 			$$ = PF_LIMITER_NOMATCH;
2799 		}
2800 		;
2801 
2802 pfrule		: action dir logquick interface route af proto fromto
2803 		    filter_opts
2804 		{
2805 			struct pfctl_rule	 r;
2806 			struct node_state_opt	*o;
2807 			struct node_proto	*proto;
2808 			int			 srctrack = 0;
2809 			int			 statelock = 0;
2810 			int			 adaptive = 0;
2811 			int			 defaults = 0;
2812 
2813 			if (check_rulestate(PFCTL_STATE_FILTER))
2814 				YYERROR;
2815 
2816 			pfctl_init_rule(&r);
2817 
2818 			r.action = $1.b1;
2819 			switch ($1.b2) {
2820 			case PFRULE_RETURNRST:
2821 				r.rule_flag |= PFRULE_RETURNRST;
2822 				r.return_ttl = $1.w;
2823 				break;
2824 			case PFRULE_RETURNICMP:
2825 				r.rule_flag |= PFRULE_RETURNICMP;
2826 				r.return_icmp = $1.w;
2827 				r.return_icmp6 = $1.w2;
2828 				break;
2829 			case PFRULE_RETURN:
2830 				r.rule_flag |= PFRULE_RETURN;
2831 				r.return_icmp = $1.w;
2832 				r.return_icmp6 = $1.w2;
2833 				break;
2834 			}
2835 			r.direction = $2;
2836 			r.log = $3.log;
2837 			r.logif = $3.logif;
2838 			r.quick = $3.quick;
2839 			r.af = $6;
2840 
2841 			if (filteropts_to_rule(&r, &$9))
2842 				YYERROR;
2843 
2844 			if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
2845 				for (proto = $7; proto != NULL &&
2846 				    proto->proto != IPPROTO_TCP;
2847 				    proto = proto->next)
2848 					;	/* nothing */
2849 				if (proto == NULL && $7 != NULL) {
2850 					if ($9.flags.b1 || $9.flags.b2)
2851 						yyerror(
2852 						    "flags only apply to tcp");
2853 					if ($8.src_os)
2854 						yyerror(
2855 						    "OS fingerprinting only "
2856 						    "apply to tcp");
2857 					YYERROR;
2858 				}
2859 			}
2860 
2861 			o = $9.keep.options;
2862 
2863 			/* 'keep state' by default on pass rules. */
2864 			if (!r.keep_state && !r.action &&
2865 			    !($9.marker & FOM_KEEP)) {
2866 				r.keep_state = PF_STATE_NORMAL;
2867 				o = keep_state_defaults;
2868 				defaults = 1;
2869 			}
2870 
2871 			while (o) {
2872 				struct node_state_opt	*p = o;
2873 
2874 				switch (o->type) {
2875 				case PF_STATE_OPT_MAX:
2876 					if (r.max_states) {
2877 						yyerror("state option 'max' "
2878 						    "multiple definitions");
2879 						YYERROR;
2880 					}
2881 					r.max_states = o->data.max_states;
2882 					break;
2883 				case PF_STATE_OPT_NOSYNC:
2884 					if (r.rule_flag & PFRULE_NOSYNC) {
2885 						yyerror("state option 'sync' "
2886 						    "multiple definitions");
2887 						YYERROR;
2888 					}
2889 					r.rule_flag |= PFRULE_NOSYNC;
2890 					break;
2891 				case PF_STATE_OPT_SRCTRACK:
2892 					if (srctrack) {
2893 						yyerror("state option "
2894 						    "'source-track' "
2895 						    "multiple definitions");
2896 						YYERROR;
2897 					}
2898 					srctrack =  o->data.src_track;
2899 					r.rule_flag |= PFRULE_SRCTRACK;
2900 					break;
2901 				case PF_STATE_OPT_MAX_SRC_STATES:
2902 					if (r.max_src_states) {
2903 						yyerror("state option "
2904 						    "'max-src-states' "
2905 						    "multiple definitions");
2906 						YYERROR;
2907 					}
2908 					if (o->data.max_src_states == 0) {
2909 						yyerror("'max-src-states' must "
2910 						    "be > 0");
2911 						YYERROR;
2912 					}
2913 					r.max_src_states =
2914 					    o->data.max_src_states;
2915 					r.rule_flag |= PFRULE_SRCTRACK;
2916 					break;
2917 				case PF_STATE_OPT_OVERLOAD:
2918 					if (r.overload_tblname[0]) {
2919 						yyerror("multiple 'overload' "
2920 						    "table definitions");
2921 						YYERROR;
2922 					}
2923 					if (strlcpy(r.overload_tblname,
2924 					    o->data.overload.tblname,
2925 					    PF_TABLE_NAME_SIZE) >=
2926 					    PF_TABLE_NAME_SIZE) {
2927 						yyerror("state option: "
2928 						    "strlcpy");
2929 						YYERROR;
2930 					}
2931 					r.flush = o->data.overload.flush;
2932 					break;
2933 				case PF_STATE_OPT_MAX_SRC_CONN:
2934 					if (r.max_src_conn) {
2935 						yyerror("state option "
2936 						    "'max-src-conn' "
2937 						    "multiple definitions");
2938 						YYERROR;
2939 					}
2940 					if (o->data.max_src_conn == 0) {
2941 						yyerror("'max-src-conn' "
2942 						    "must be > 0");
2943 						YYERROR;
2944 					}
2945 					r.max_src_conn =
2946 					    o->data.max_src_conn;
2947 					r.rule_flag |= PFRULE_SRCTRACK |
2948 					    PFRULE_RULESRCTRACK;
2949 					break;
2950 				case PF_STATE_OPT_MAX_SRC_CONN_RATE:
2951 					if (r.max_src_conn_rate.limit) {
2952 						yyerror("state option "
2953 						    "'max-src-conn-rate' "
2954 						    "multiple definitions");
2955 						YYERROR;
2956 					}
2957 					if (!o->data.max_src_conn_rate.limit ||
2958 					    !o->data.max_src_conn_rate.seconds) {
2959 						yyerror("'max-src-conn-rate' "
2960 						    "values must be > 0");
2961 						YYERROR;
2962 					}
2963 					if (o->data.max_src_conn_rate.limit >
2964 					    PF_THRESHOLD_MAX) {
2965 						yyerror("'max-src-conn-rate' "
2966 						    "maximum rate must be < %u",
2967 						    PF_THRESHOLD_MAX);
2968 						YYERROR;
2969 					}
2970 					r.max_src_conn_rate.limit =
2971 					    o->data.max_src_conn_rate.limit;
2972 					r.max_src_conn_rate.seconds =
2973 					    o->data.max_src_conn_rate.seconds;
2974 					r.rule_flag |= PFRULE_SRCTRACK |
2975 					    PFRULE_RULESRCTRACK;
2976 					break;
2977 				case PF_STATE_OPT_MAX_SRC_NODES:
2978 					if (r.max_src_nodes) {
2979 						yyerror("state option "
2980 						    "'max-src-nodes' "
2981 						    "multiple definitions");
2982 						YYERROR;
2983 					}
2984 					if (o->data.max_src_nodes == 0) {
2985 						yyerror("'max-src-nodes' must "
2986 						    "be > 0");
2987 						YYERROR;
2988 					}
2989 					r.max_src_nodes =
2990 					    o->data.max_src_nodes;
2991 					r.rule_flag |= PFRULE_SRCTRACK |
2992 					    PFRULE_RULESRCTRACK;
2993 					break;
2994 				case PF_STATE_OPT_STATELOCK:
2995 					if (statelock) {
2996 						yyerror("state locking option: "
2997 						    "multiple definitions");
2998 						YYERROR;
2999 					}
3000 					statelock = 1;
3001 					r.rule_flag |= o->data.statelock;
3002 					break;
3003 				case PF_STATE_OPT_SLOPPY:
3004 					if (r.rule_flag & PFRULE_STATESLOPPY) {
3005 						yyerror("state sloppy option: "
3006 						    "multiple definitions");
3007 						YYERROR;
3008 					}
3009 					r.rule_flag |= PFRULE_STATESLOPPY;
3010 					break;
3011 				case PF_STATE_OPT_PFLOW:
3012 					if (r.rule_flag & PFRULE_PFLOW) {
3013 						yyerror("state pflow option: "
3014 						    "multiple definitions");
3015 						YYERROR;
3016 					}
3017 					r.rule_flag |= PFRULE_PFLOW;
3018 					break;
3019 				case PF_STATE_OPT_ALLOW_RELATED:
3020 					if (r.rule_flag & PFRULE_ALLOW_RELATED) {
3021 						yyerror("state allow-related option: "
3022 						    "multiple definitions");
3023 						YYERROR;
3024 					}
3025 					r.rule_flag |= PFRULE_ALLOW_RELATED;
3026 					break;
3027 				case PF_STATE_OPT_TIMEOUT:
3028 					if (o->data.timeout.number ==
3029 					    PFTM_ADAPTIVE_START ||
3030 					    o->data.timeout.number ==
3031 					    PFTM_ADAPTIVE_END)
3032 						adaptive = 1;
3033 					if (r.timeout[o->data.timeout.number]) {
3034 						yyerror("state timeout %s "
3035 						    "multiple definitions",
3036 						    pf_timeouts[o->data.
3037 						    timeout.number].name);
3038 						YYERROR;
3039 					}
3040 					r.timeout[o->data.timeout.number] =
3041 					    o->data.timeout.seconds;
3042 					break;
3043 				}
3044 				o = o->next;
3045 				if (!defaults)
3046 					free(p);
3047 			}
3048 
3049 			/* 'flags S/SA' by default on stateful rules */
3050 			if (!r.action && !r.flags && !r.flagset &&
3051 			    !$9.fragment && !($9.marker & FOM_FLAGS) &&
3052 			    r.keep_state) {
3053 				r.flags = parse_flags("S");
3054 				r.flagset =  parse_flags("SA");
3055 			}
3056 			if (!adaptive && r.max_states) {
3057 				r.timeout[PFTM_ADAPTIVE_START] =
3058 				    (r.max_states / 10) * 6;
3059 				r.timeout[PFTM_ADAPTIVE_END] =
3060 				    (r.max_states / 10) * 12;
3061 			}
3062 			if (r.rule_flag & PFRULE_SRCTRACK) {
3063 				if (srctrack == PF_SRCTRACK_GLOBAL &&
3064 				    r.max_src_nodes) {
3065 					yyerror("'max-src-nodes' is "
3066 					    "incompatible with "
3067 					    "'source-track global'");
3068 					YYERROR;
3069 				}
3070 				if (srctrack == PF_SRCTRACK_GLOBAL &&
3071 				    r.max_src_conn) {
3072 					yyerror("'max-src-conn' is "
3073 					    "incompatible with "
3074 					    "'source-track global'");
3075 					YYERROR;
3076 				}
3077 				if (srctrack == PF_SRCTRACK_GLOBAL &&
3078 				    r.max_src_conn_rate.seconds) {
3079 					yyerror("'max-src-conn-rate' is "
3080 					    "incompatible with "
3081 					    "'source-track global'");
3082 					YYERROR;
3083 				}
3084 				if (r.timeout[PFTM_SRC_NODE] <
3085 				    r.max_src_conn_rate.seconds)
3086 					r.timeout[PFTM_SRC_NODE] =
3087 					    r.max_src_conn_rate.seconds;
3088 				r.rule_flag |= PFRULE_SRCTRACK;
3089 				if (srctrack == PF_SRCTRACK_RULE)
3090 					r.rule_flag |= PFRULE_RULESRCTRACK;
3091 			}
3092 			if (r.keep_state && !statelock)
3093 				r.rule_flag |= default_statelock;
3094 
3095 			decide_address_family($8.src.host, &r.af);
3096 			decide_address_family($8.dst.host, &r.af);
3097 
3098 			if ($5.rt) {
3099 				if (!r.direction) {
3100 					yyerror("direction must be explicit "
3101 					    "with rules that specify routing");
3102 					YYERROR;
3103 				}
3104 				r.rt = $5.rt;
3105 
3106 				if (!($5.redirspec->pool_opts.opts & PF_POOL_IPV6NH)) {
3107 					decide_address_family($5.redirspec->host, &r.af);
3108 					if (!(r.rule_flag & PFRULE_AFTO))
3109 						remove_invalid_hosts(&($5.redirspec->host), &r.af);
3110 					if ($5.redirspec->host == NULL) {
3111 						yyerror("no routing address with "
3112 						    "matching address family found.");
3113 						YYERROR;
3114 					}
3115 				}
3116 			}
3117 #ifdef __FreeBSD__
3118 			r.divert.port = $9.divert.port;
3119 #else
3120 			if ((r.divert.port = $9.divert.port)) {
3121 				if (r.direction == PF_OUT) {
3122 					if ($9.divert.addr) {
3123 						yyerror("address specified "
3124 						    "for outgoing divert");
3125 						YYERROR;
3126 					}
3127 					bzero(&r.divert.addr,
3128 					    sizeof(r.divert.addr));
3129 				} else {
3130 					if (!$9.divert.addr) {
3131 						yyerror("no address specified "
3132 						    "for incoming divert");
3133 						YYERROR;
3134 					}
3135 					if ($9.divert.addr->af != r.af) {
3136 						yyerror("address family "
3137 						    "mismatch for divert");
3138 						YYERROR;
3139 					}
3140 					r.divert.addr =
3141 					    $9.divert.addr->addr.v.a.addr;
3142 				}
3143 			}
3144 #endif
3145 
3146 			if ($9.dnpipe || $9.dnrpipe) {
3147 				r.dnpipe = $9.dnpipe;
3148 				r.dnrpipe = $9.dnrpipe;
3149 				if ($9.free_flags & PFRULE_DN_IS_PIPE)
3150 					r.free_flags |= PFRULE_DN_IS_PIPE;
3151 				else
3152 					r.free_flags |= PFRULE_DN_IS_QUEUE;
3153 			}
3154 
3155 			if ($9.marker & FOM_AFTO) {
3156 				r.naf = $9.nat->af;
3157 			} else {
3158 				if ($9.nat) {
3159 					if (!r.af && ! $9.nat->host->ifindex)
3160 						r.af = $9.nat->host->af;
3161 					remove_invalid_hosts(&($9.nat->host), &r.af);
3162 					if (invalid_redirect($9.nat->host, r.af))
3163 						YYERROR;
3164 					if ($9.nat->host->addr.type == PF_ADDR_DYNIFTL) {
3165 						if (($9.nat->host = gen_dynnode($9.nat->host, r.af)) == NULL)
3166 							err(1, "calloc");
3167 					}
3168 					if (check_netmask($9.nat->host, r.af))
3169 						YYERROR;
3170 				}
3171 				if ($9.rdr) {
3172 					if (!r.af && ! $9.rdr->host->ifindex)
3173 						r.af = $9.rdr->host->af;
3174 					remove_invalid_hosts(&($9.rdr->host), &r.af);
3175 					if (invalid_redirect($9.rdr->host, r.af))
3176 						YYERROR;
3177 					if ($9.rdr->host->addr.type == PF_ADDR_DYNIFTL) {
3178 						if (($9.rdr->host = gen_dynnode($9.rdr->host, r.af)) == NULL)
3179 							err(1, "calloc");
3180 					}
3181 					if (check_netmask($9.rdr->host, r.af))
3182 						YYERROR;
3183 				}
3184 			}
3185 
3186 			expand_rule(&r, false, $4, $9.nat, $9.rdr, $5.redirspec,
3187 			    $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host,
3188 			    $8.dst.port, $9.uid, $9.gid, $9.rcv, $9.icmpspec);
3189 		}
3190 		;
3191 
3192 filter_opts	:	{
3193 				bzero(&filter_opts, sizeof filter_opts);
3194 				filter_opts.statelim.id = PF_STATELIM_ID_NONE;
3195 				filter_opts.statelim.limiter_action = PF_LIMITER_NOMATCH;
3196 				filter_opts.sourcelim.id = PF_SOURCELIM_ID_NONE;
3197 				filter_opts.sourcelim.limiter_action = PF_LIMITER_NOMATCH;
3198 				filter_opts.rtableid = -1;
3199 			}
3200 		    filter_opts_l
3201 			{ $$ = filter_opts; }
3202 		| /* empty */	{
3203 			bzero(&filter_opts, sizeof filter_opts);
3204 			filter_opts.statelim.id = PF_STATELIM_ID_NONE;
3205 			filter_opts.statelim.limiter_action = PF_LIMITER_NOMATCH;
3206 			filter_opts.sourcelim.id = PF_SOURCELIM_ID_NONE;
3207 			filter_opts.sourcelim.limiter_action = PF_LIMITER_NOMATCH;
3208 			filter_opts.rtableid = -1;
3209 			$$ = filter_opts;
3210 		}
3211 		;
3212 
3213 filter_opts_l	: filter_opts_l filter_opt
3214 		| filter_opt
3215 		;
3216 
3217 filter_opt	: USER uids {
3218 			if (filter_opts.uid)
3219 				$2->tail->next = filter_opts.uid;
3220 			filter_opts.uid = $2;
3221 		}
3222 		| GROUP gids {
3223 			if (filter_opts.gid)
3224 				$2->tail->next = filter_opts.gid;
3225 			filter_opts.gid = $2;
3226 		}
3227 		| flags {
3228 			if (filter_opts.marker & FOM_FLAGS) {
3229 				yyerror("flags cannot be redefined");
3230 				YYERROR;
3231 			}
3232 			filter_opts.marker |= FOM_FLAGS;
3233 			filter_opts.flags.b1 |= $1.b1;
3234 			filter_opts.flags.b2 |= $1.b2;
3235 			filter_opts.flags.w |= $1.w;
3236 			filter_opts.flags.w2 |= $1.w2;
3237 		}
3238 		| icmpspec {
3239 			if (filter_opts.marker & FOM_ICMP) {
3240 				yyerror("icmp-type cannot be redefined");
3241 				YYERROR;
3242 			}
3243 			filter_opts.marker |= FOM_ICMP;
3244 			filter_opts.icmpspec = $1;
3245 		}
3246 		| PRIO NUMBER {
3247 			if (filter_opts.marker & FOM_PRIO) {
3248 				yyerror("prio cannot be redefined");
3249 				YYERROR;
3250 			}
3251 			if ($2 < 0 || $2 > PF_PRIO_MAX) {
3252 				yyerror("prio must be 0 - %u", PF_PRIO_MAX);
3253 				YYERROR;
3254 			}
3255 			filter_opts.marker |= FOM_PRIO;
3256 			filter_opts.prio = $2;
3257 		}
3258 		| TOS tos {
3259 			if (filter_opts.marker & FOM_TOS) {
3260 				yyerror("tos cannot be redefined");
3261 				YYERROR;
3262 			}
3263 			filter_opts.marker |= FOM_TOS;
3264 			filter_opts.tos = $2;
3265 		}
3266 		| keep {
3267 			if (filter_opts.marker & FOM_KEEP) {
3268 				yyerror("modulate or keep cannot be redefined");
3269 				YYERROR;
3270 			}
3271 			filter_opts.marker |= FOM_KEEP;
3272 			filter_opts.keep.action = $1.action;
3273 			filter_opts.keep.options = $1.options;
3274 		}
3275 		| RIDENTIFIER number {
3276 			filter_opts.ridentifier = $2;
3277 		}
3278 		| FRAGMENT {
3279 			filter_opts.fragment = 1;
3280 		}
3281 		| ALLOWOPTS {
3282 			filter_opts.allowopts = 1;
3283 		}
3284 		| label	{
3285 			if (filter_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) {
3286 				yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT);
3287 				YYERROR;
3288 			}
3289 			filter_opts.label[filter_opts.labelcount++] = $1;
3290 		}
3291 		| qname	{
3292 			if (filter_opts.queues.qname) {
3293 				yyerror("queue cannot be redefined");
3294 				YYERROR;
3295 			}
3296 			filter_opts.queues = $1;
3297 		}
3298 		| DNPIPE number {
3299 			filter_opts.dnpipe = $2;
3300 			filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
3301 		}
3302 		| DNPIPE '(' number ')' {
3303 			filter_opts.dnpipe = $3;
3304 			filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
3305 		}
3306 		| DNPIPE '(' number comma number ')' {
3307 			filter_opts.dnrpipe = $5;
3308 			filter_opts.dnpipe = $3;
3309 			filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
3310 		}
3311 		| DNQUEUE number {
3312 			filter_opts.dnpipe = $2;
3313 			filter_opts.free_flags |= PFRULE_DN_IS_QUEUE;
3314 		}
3315 		| DNQUEUE '(' number comma number ')' {
3316 			filter_opts.dnrpipe = $5;
3317 			filter_opts.dnpipe = $3;
3318 			filter_opts.free_flags |= PFRULE_DN_IS_QUEUE;
3319 		}
3320 		| DNQUEUE '(' number ')' {
3321 			filter_opts.dnpipe = $3;
3322 			filter_opts.free_flags |= PFRULE_DN_IS_QUEUE;
3323 		}
3324 		| TAG string				{
3325 			filter_opts.tag = $2;
3326 		}
3327 		| not TAGGED string			{
3328 			filter_opts.match_tag = $3;
3329 			filter_opts.match_tag_not = $1;
3330 		}
3331 		| not RECEIVEDON if_item {
3332 			if (filter_opts.rcv) {
3333 				yyerror("cannot respecify received-on");
3334 				YYERROR;
3335 			}
3336 			filter_opts.rcv = $3;
3337 			filter_opts.rcv->not = $1;
3338 		}
3339 		| PROBABILITY probability		{
3340 			double	p;
3341 
3342 			p = floor($2 * UINT_MAX + 0.5);
3343 			if (p < 0.0 || p > UINT_MAX) {
3344 				yyerror("invalid probability: %lf", p);
3345 				YYERROR;
3346 			}
3347 			filter_opts.prob = (u_int32_t)p;
3348 			if (filter_opts.prob == 0)
3349 				filter_opts.prob = 1;
3350 		}
3351 		| statelim_filter_opt {
3352 			if (filter_opts.statelim.id != PF_STATELIM_ID_NONE) {
3353 				yyerror("state limiter already specified");
3354 				YYERROR;
3355 			}
3356 			filter_opts.statelim = $1;
3357 		}
3358 		| sourcelim_filter_opt {
3359 			if (filter_opts.sourcelim.id != PF_SOURCELIM_ID_NONE) {
3360 				yyerror("source limiter already specified");
3361 				YYERROR;
3362 			}
3363 			filter_opts.sourcelim = $1;
3364 		}
3365 		| RTABLE NUMBER				{
3366 			if ($2 < 0 || $2 > rt_tableid_max()) {
3367 				yyerror("invalid rtable id");
3368 				YYERROR;
3369 			}
3370 			filter_opts.rtableid = $2;
3371 		}
3372 		| DIVERTTO portplain {
3373 #ifdef __FreeBSD__
3374 			filter_opts.divert.port = $2.a;
3375 			if (!filter_opts.divert.port) {
3376 				yyerror("invalid divert port: %u", ntohs($2.a));
3377 				YYERROR;
3378 			}
3379 #endif
3380 		}
3381 		| DIVERTTO STRING PORT portplain {
3382 #ifndef __FreeBSD__
3383 			if ((filter_opts.divert.addr = host($2, pf->opts)) == NULL) {
3384 				yyerror("could not parse divert address: %s",
3385 				    $2);
3386 				free($2);
3387 				YYERROR;
3388 			}
3389 #else
3390 			if ($2)
3391 #endif
3392 			free($2);
3393 			filter_opts.divert.port = $4.a;
3394 			if (!filter_opts.divert.port) {
3395 				yyerror("invalid divert port: %u", ntohs($4.a));
3396 				YYERROR;
3397 			}
3398 		}
3399 		| DIVERTREPLY {
3400 #ifdef __FreeBSD__
3401 			yyerror("divert-reply has no meaning in FreeBSD pf(4)");
3402 			YYERROR;
3403 #else
3404 			filter_opts.divert.port = 1;	/* some random value */
3405 #endif
3406 		}
3407 		| SCRUB '(' scrub_opts ')' {
3408 			filter_opts.nodf = $3.nodf;
3409 			filter_opts.minttl = $3.minttl;
3410 			if ($3.marker & FOM_SETTOS) {
3411 				/* Old style rules are "scrub set-tos 0x42"
3412 				 * New style are "set tos 0x42 scrub (...)"
3413 				 * What is in "scrub(...)"" is unfortunately the
3414 				 * original scrub syntax so it would overwrite
3415 				 * "set tos" of a pass/match rule.
3416 				 */
3417 				filter_opts.settos = $3.settos;
3418 			}
3419 			filter_opts.randomid = $3.randomid;
3420 			filter_opts.max_mss = $3.maxmss;
3421 			if ($3.reassemble_tcp)
3422 				filter_opts.marker |= FOM_SCRUB_TCP;
3423 			filter_opts.marker |= $3.marker;
3424 		}
3425 		| NATTO port_redirspec {
3426 			if (filter_opts.nat) {
3427 				yyerror("cannot respecify nat-to/binat-to");
3428 				YYERROR;
3429 			}
3430 			filter_opts.nat = $2;
3431 		}
3432 		| RDRTO port_redirspec {
3433 			if (filter_opts.rdr) {
3434 				yyerror("cannot respecify rdr-to");
3435 				YYERROR;
3436 			}
3437 			filter_opts.rdr = $2;
3438 		}
3439 		| BINATTO port_redirspec {
3440 			if (filter_opts.nat) {
3441 				yyerror("cannot respecify nat-to/binat-to");
3442 				YYERROR;
3443 			}
3444 			filter_opts.nat = $2;
3445 			filter_opts.nat->binat = 1;
3446 			filter_opts.nat->pool_opts.staticport = 1;
3447 		}
3448 		| AFTO af FROM port_redirspec {
3449 			if (filter_opts.nat) {
3450 				yyerror("cannot respecify af-to");
3451 				YYERROR;
3452 			}
3453 			if ($2 == 0) {
3454 				yyerror("no address family specified");
3455 				YYERROR;
3456 			}
3457 
3458 			filter_opts.nat = $4;
3459 			filter_opts.nat->af = $2;
3460 			remove_invalid_hosts(&($4->host), &(filter_opts.nat->af));
3461 			if ($4->host == NULL) {
3462 				yyerror("af-to addresses must be in the "
3463 				   "target address family");
3464 				YYERROR;
3465 			}
3466 			filter_opts.marker |= FOM_AFTO;
3467 		}
3468 		| AFTO af FROM port_redirspec TO port_redirspec {
3469 			if (filter_opts.nat) {
3470 				yyerror("cannot respecify af-to");
3471 				YYERROR;
3472 			}
3473 			if ($2 == 0) {
3474 				yyerror("no address family specified");
3475 				YYERROR;
3476 			}
3477 			filter_opts.nat = $4;
3478 			filter_opts.nat->af = $2;
3479 			filter_opts.rdr = $6;
3480 			filter_opts.rdr->af = $2;
3481 			remove_invalid_hosts(&($4->host), &(filter_opts.nat->af));
3482 			remove_invalid_hosts(&($6->host), &(filter_opts.rdr->af));
3483 			if ($4->host == NULL || $6->host == NULL) {
3484 				yyerror("af-to addresses must be in the "
3485 				   "target address family");
3486 				YYERROR;
3487 			}
3488 			filter_opts.marker |= FOM_AFTO;
3489 		}
3490 		| MAXPKTRATE NUMBER '/' NUMBER {
3491 			if ($2 < 0 || $2 > UINT_MAX ||
3492 			    $4 < 0 || $4 > UINT_MAX) {
3493 				yyerror("only positive values permitted");
3494 				YYERROR;
3495 			}
3496 			if (filter_opts.pktrate.limit) {
3497 				yyerror("cannot respecify max-pkt-rate");
3498 				YYERROR;
3499 			}
3500 			filter_opts.pktrate.limit = $2;
3501 			filter_opts.pktrate.seconds = $4;
3502 		}
3503 		| MAXPKTSIZE NUMBER {
3504 			if ($2 < 0 || $2 > UINT16_MAX) {
3505 				yyerror("only positive values permitted");
3506 				YYERROR;
3507 			}
3508 			filter_opts.max_pkt_size = $2;
3509 		}
3510 		| ONCE {
3511 			filter_opts.marker |= FOM_ONCE;
3512 		}
3513 		| filter_sets
3514 		;
3515 
3516 filter_sets	: SET '(' filter_sets_l ')'	{ $$ = filter_opts; }
3517 		| SET filter_set		{ $$ = filter_opts; }
3518 		;
3519 
3520 filter_sets_l	: filter_sets_l comma filter_set
3521 		| filter_set
3522 		;
3523 
3524 filter_set	: prio {
3525 			if (filter_opts.marker & FOM_SETPRIO) {
3526 				yyerror("prio cannot be redefined");
3527 				YYERROR;
3528 			}
3529 			filter_opts.marker |= FOM_SETPRIO;
3530 			filter_opts.set_prio[0] = $1.b1;
3531 			filter_opts.set_prio[1] = $1.b2;
3532 		}
3533 		| TOS tos {
3534 			if (filter_opts.marker & FOM_SETTOS) {
3535 				yyerror("tos cannot be respecified");
3536 				YYERROR;
3537 			}
3538 			filter_opts.marker |= FOM_SETTOS;
3539 			filter_opts.settos = $2;
3540 		}
3541 prio		: PRIO NUMBER {
3542 			if ($2 < 0 || $2 > PF_PRIO_MAX) {
3543 				yyerror("prio must be 0 - %u", PF_PRIO_MAX);
3544 				YYERROR;
3545 			}
3546 			$$.b1 = $$.b2 = $2;
3547 		}
3548 		| PRIO '(' NUMBER comma NUMBER ')' {
3549 			if ($3 < 0 || $3 > PF_PRIO_MAX ||
3550 			    $5 < 0 || $5 > PF_PRIO_MAX) {
3551 				yyerror("prio must be 0 - %u", PF_PRIO_MAX);
3552 				YYERROR;
3553 			}
3554 			$$.b1 = $3;
3555 			$$.b2 = $5;
3556 		}
3557 		;
3558 
3559 probability	: STRING				{
3560 			char	*e;
3561 			double	 p = strtod($1, &e);
3562 
3563 			if (*e == '%') {
3564 				p *= 0.01;
3565 				e++;
3566 			}
3567 			if (*e) {
3568 				yyerror("invalid probability: %s", $1);
3569 				free($1);
3570 				YYERROR;
3571 			}
3572 			free($1);
3573 			$$ = p;
3574 		}
3575 		| NUMBER				{
3576 			$$ = (double)$1;
3577 		}
3578 		;
3579 
3580 
3581 action		: PASS 			{
3582 			$$.b1 = PF_PASS;
3583 			$$.b2 = failpolicy;
3584 			$$.w = returnicmpdefault;
3585 			$$.w2 = returnicmp6default;
3586 		}
3587 		| MATCH			{ $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; }
3588 		| BLOCK blockspec	{ $$ = $2; $$.b1 = PF_DROP; }
3589 		;
3590 
3591 blockspec	: /* empty */		{
3592 			$$.b2 = blockpolicy;
3593 			$$.w = returnicmpdefault;
3594 			$$.w2 = returnicmp6default;
3595 		}
3596 		| DROP			{
3597 			$$.b2 = PFRULE_DROP;
3598 			$$.w = 0;
3599 			$$.w2 = 0;
3600 		}
3601 		| RETURNRST		{
3602 			$$.b2 = PFRULE_RETURNRST;
3603 			$$.w = 0;
3604 			$$.w2 = 0;
3605 		}
3606 		| RETURNRST '(' TTL NUMBER ')'	{
3607 			if ($4 < 0 || $4 > 255) {
3608 				yyerror("illegal ttl value %d", $4);
3609 				YYERROR;
3610 			}
3611 			$$.b2 = PFRULE_RETURNRST;
3612 			$$.w = $4;
3613 			$$.w2 = 0;
3614 		}
3615 		| RETURNICMP		{
3616 			$$.b2 = PFRULE_RETURNICMP;
3617 			$$.w = returnicmpdefault;
3618 			$$.w2 = returnicmp6default;
3619 		}
3620 		| RETURNICMP6		{
3621 			$$.b2 = PFRULE_RETURNICMP;
3622 			$$.w = returnicmpdefault;
3623 			$$.w2 = returnicmp6default;
3624 		}
3625 		| RETURNICMP '(' reticmpspec ')'	{
3626 			$$.b2 = PFRULE_RETURNICMP;
3627 			$$.w = $3;
3628 			$$.w2 = returnicmpdefault;
3629 		}
3630 		| RETURNICMP6 '(' reticmp6spec ')'	{
3631 			$$.b2 = PFRULE_RETURNICMP;
3632 			$$.w = returnicmpdefault;
3633 			$$.w2 = $3;
3634 		}
3635 		| RETURNICMP '(' reticmpspec comma reticmp6spec ')' {
3636 			$$.b2 = PFRULE_RETURNICMP;
3637 			$$.w = $3;
3638 			$$.w2 = $5;
3639 		}
3640 		| RETURN {
3641 			$$.b2 = PFRULE_RETURN;
3642 			$$.w = returnicmpdefault;
3643 			$$.w2 = returnicmp6default;
3644 		}
3645 		;
3646 
3647 reticmpspec	: STRING			{
3648 			if (!($$ = parseicmpspec($1, AF_INET))) {
3649 				free($1);
3650 				YYERROR;
3651 			}
3652 			free($1);
3653 		}
3654 		| NUMBER			{
3655 			u_int8_t		icmptype;
3656 
3657 			if ($1 < 0 || $1 > 255) {
3658 				yyerror("invalid icmp code %lu", $1);
3659 				YYERROR;
3660 			}
3661 			icmptype = returnicmpdefault >> 8;
3662 			$$ = (icmptype << 8 | $1);
3663 		}
3664 		;
3665 
3666 reticmp6spec	: STRING			{
3667 			if (!($$ = parseicmpspec($1, AF_INET6))) {
3668 				free($1);
3669 				YYERROR;
3670 			}
3671 			free($1);
3672 		}
3673 		| NUMBER			{
3674 			u_int8_t		icmptype;
3675 
3676 			if ($1 < 0 || $1 > 255) {
3677 				yyerror("invalid icmp code %lu", $1);
3678 				YYERROR;
3679 			}
3680 			icmptype = returnicmp6default >> 8;
3681 			$$ = (icmptype << 8 | $1);
3682 		}
3683 		;
3684 
3685 dir		: /* empty */			{ $$ = PF_INOUT; }
3686 		| IN				{ $$ = PF_IN; }
3687 		| OUT				{ $$ = PF_OUT; }
3688 		;
3689 
3690 quick		: /* empty */			{ $$.quick = 0; }
3691 		| QUICK				{ $$.quick = 1; }
3692 		;
3693 
3694 logquick	: /* empty */	{ $$.log = 0; $$.quick = 0; $$.logif = 0; }
3695 		| log		{ $$ = $1; $$.quick = 0; }
3696 		| QUICK		{ $$.quick = 1; $$.log = 0; $$.logif = 0; }
3697 		| log QUICK	{ $$ = $1; $$.quick = 1; }
3698 		| QUICK log	{ $$ = $2; $$.quick = 1; }
3699 		;
3700 
3701 log		: LOG			{ $$.log = PF_LOG; $$.logif = 0; }
3702 		| LOG '(' logopts ')'	{
3703 			$$.log = PF_LOG | $3.log;
3704 			$$.logif = $3.logif;
3705 		}
3706 		;
3707 
3708 logopts		: logopt			{ $$ = $1; }
3709 		| logopts comma logopt		{
3710 			$$.log = $1.log | $3.log;
3711 			$$.logif = $3.logif;
3712 			if ($$.logif == 0)
3713 				$$.logif = $1.logif;
3714 		}
3715 		;
3716 
3717 logopt		: ALL		{ $$.log = PF_LOG_ALL; $$.logif = 0; }
3718 		| MATCHES		{ $$.log = PF_LOG_MATCHES; $$.logif = 0; }
3719 		| USER		{ $$.log = PF_LOG_USER; $$.logif = 0; }
3720 		| TO string	{
3721 			const char	*errstr;
3722 			u_int		 i;
3723 
3724 			$$.log = 0;
3725 			if (strncmp($2, "pflog", 5)) {
3726 				yyerror("%s: should be a pflog interface", $2);
3727 				free($2);
3728 				YYERROR;
3729 			}
3730 			i = strtonum($2 + 5, 0, 255, &errstr);
3731 			if (errstr) {
3732 				yyerror("%s: %s", $2, errstr);
3733 				free($2);
3734 				YYERROR;
3735 			}
3736 			free($2);
3737 			$$.logif = i;
3738 		}
3739 		;
3740 
3741 interface	: /* empty */			{ $$ = NULL; }
3742 		| ON if_item_not		{ $$ = $2; }
3743 		| ON '{' optnl if_list '}'	{ $$ = $4; }
3744 		;
3745 
3746 if_list		: if_item_not optnl		{ $$ = $1; }
3747 		| if_list comma if_item_not optnl	{
3748 			$1->tail->next = $3;
3749 			$1->tail = $3;
3750 			$$ = $1;
3751 		}
3752 		;
3753 
3754 if_item_not	: not if_item			{ $$ = $2; $$->not = $1; }
3755 		;
3756 
3757 if_item		: STRING			{
3758 			struct node_host	*n;
3759 
3760 			$$ = calloc(1, sizeof(struct node_if));
3761 			if ($$ == NULL)
3762 				err(1, "if_item: calloc");
3763 			if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >=
3764 			    sizeof($$->ifname)) {
3765 				free($1);
3766 				free($$);
3767 				yyerror("interface name too long");
3768 				YYERROR;
3769 			}
3770 
3771 			if ((n = ifa_exists($1)) != NULL)
3772 				$$->ifa_flags = n->ifa_flags;
3773 
3774 			free($1);
3775 			$$->not = 0;
3776 			$$->next = NULL;
3777 			$$->tail = $$;
3778 		}
3779 		| ANY				{
3780 			$$ = calloc(1, sizeof(struct node_if));
3781 			if ($$ == NULL)
3782 				err(1, "if_item: calloc");
3783 			strlcpy($$->ifname, "any", sizeof($$->ifname));
3784 			$$->not = 0;
3785 			$$->next = NULL;
3786 			$$->tail = $$;
3787 		}
3788 		;
3789 
3790 af		: /* empty */			{ $$ = 0; }
3791 		| INET				{ $$ = AF_INET; }
3792 		| INET6				{ $$ = AF_INET6; }
3793 		;
3794 
3795 etherproto	: /* empty */				{ $$ = NULL; }
3796 		| PROTO etherproto_item			{ $$ = $2; }
3797 		| PROTO '{' optnl etherproto_list '}'	{ $$ = $4; }
3798 		;
3799 
3800 etherproto_list	: etherproto_item optnl			{ $$ = $1; }
3801 		| etherproto_list comma etherproto_item optnl	{
3802 			$1->tail->next = $3;
3803 			$1->tail = $3;
3804 			$$ = $1;
3805 		}
3806 		;
3807 
3808 etherproto_item	: etherprotoval		{
3809 			u_int16_t	pr;
3810 
3811 			pr = (u_int16_t)$1;
3812 			if (pr == 0) {
3813 				yyerror("proto 0 cannot be used");
3814 				YYERROR;
3815 			}
3816 			$$ = calloc(1, sizeof(struct node_proto));
3817 			if ($$ == NULL)
3818 				err(1, "proto_item: calloc");
3819 			$$->proto = pr;
3820 			$$->next = NULL;
3821 			$$->tail = $$;
3822 		}
3823 		;
3824 
3825 etherprotoval	: NUMBER			{
3826 			if ($1 < 0 || $1 > 65565) {
3827 				yyerror("protocol outside range");
3828 				YYERROR;
3829 			}
3830 		}
3831 		| STRING
3832 		{
3833 			if (!strncmp($1, "0x", 2)) {
3834 				if (sscanf($1, "0x%4x", &$$) != 1) {
3835 					free($1);
3836 					yyerror("invalid EtherType hex");
3837 					YYERROR;
3838 				}
3839 			} else {
3840 				yyerror("Symbolic EtherType not yet supported");
3841 			}
3842 		}
3843 		;
3844 
3845 proto		: /* empty */				{ $$ = NULL; }
3846 		| PROTO proto_item			{ $$ = $2; }
3847 		| PROTO '{' optnl proto_list '}'	{ $$ = $4; }
3848 		;
3849 
3850 proto_list	: proto_item optnl		{ $$ = $1; }
3851 		| proto_list comma proto_item optnl	{
3852 			$1->tail->next = $3;
3853 			$1->tail = $3;
3854 			$$ = $1;
3855 		}
3856 		;
3857 
3858 proto_item	: protoval			{
3859 			u_int8_t	pr;
3860 
3861 			pr = (u_int8_t)$1;
3862 			if (pr == 0) {
3863 				yyerror("proto 0 cannot be used");
3864 				YYERROR;
3865 			}
3866 			$$ = calloc(1, sizeof(struct node_proto));
3867 			if ($$ == NULL)
3868 				err(1, "proto_item: calloc");
3869 			$$->proto = pr;
3870 			$$->next = NULL;
3871 			$$->tail = $$;
3872 		}
3873 		;
3874 
3875 protoval	: STRING			{
3876 			struct protoent	*p;
3877 
3878 			p = getprotobyname($1);
3879 			if (p == NULL) {
3880 				yyerror("unknown protocol %s", $1);
3881 				free($1);
3882 				YYERROR;
3883 			}
3884 			$$ = p->p_proto;
3885 			free($1);
3886 		}
3887 		| NUMBER			{
3888 			if ($1 < 0 || $1 > 255) {
3889 				yyerror("protocol outside range");
3890 				YYERROR;
3891 			}
3892 		}
3893 		;
3894 
3895 l3fromto	: /* empty */			{
3896 			bzero(&$$, sizeof($$));
3897 		}
3898 		| L3 fromto			{
3899 			if ($2.src.host != NULL &&
3900 			    $2.src.host->addr.type != PF_ADDR_ADDRMASK &&
3901 			    $2.src.host->addr.type != PF_ADDR_TABLE) {
3902 				yyerror("from must be an address or table");
3903 				YYERROR;
3904 			}
3905 			if ($2.dst.host != NULL &&
3906 			    $2.dst.host->addr.type != PF_ADDR_ADDRMASK &&
3907 			    $2.dst.host->addr.type != PF_ADDR_TABLE) {
3908 				yyerror("to must be an address or table");
3909 				YYERROR;
3910 			}
3911 			$$ = $2;
3912 		}
3913 		;
3914 etherfromto	: ALL				{
3915 			$$.src = NULL;
3916 			$$.dst = NULL;
3917 		}
3918 		| etherfrom etherto		{
3919 			$$.src = $1.mac;
3920 			$$.dst = $2.mac;
3921 		}
3922 		;
3923 
3924 etherfrom	: /* emtpy */			{
3925 			bzero(&$$, sizeof($$));
3926 		}
3927 		| FROM macspec			{
3928 			$$.mac = $2;
3929 		}
3930 		;
3931 
3932 etherto		: /* empty */			{
3933 			bzero(&$$, sizeof($$));
3934 		}
3935 		| TO macspec			{
3936 			$$.mac = $2;
3937 		}
3938 		;
3939 
3940 mac		: string '/' NUMBER		{
3941 			$$ = node_mac_from_string_masklen($1, $3);
3942 			free($1);
3943 			if ($$ == NULL)
3944 				YYERROR;
3945 		}
3946 		| string			{
3947 			if (strchr($1, '&')) {
3948 				/* mac&mask */
3949 				char *mac = strtok($1, "&");
3950 				char *mask = strtok(NULL, "&");
3951 				$$ = node_mac_from_string_mask(mac, mask);
3952 			} else {
3953 				$$ = node_mac_from_string($1);
3954 			}
3955 			free($1);
3956 			if ($$ == NULL)
3957 				YYERROR;
3958 
3959 		}
3960 xmac		: not mac {
3961 			struct node_mac	*n;
3962 
3963 			for (n = $2; n != NULL; n = n->next)
3964 				n->neg = $1;
3965 			$$ = $2;
3966 		}
3967 		;
3968 macspec		: xmac {
3969 			$$ = $1;
3970 		}
3971 		| '{' optnl mac_list '}'
3972 		{
3973 			$$ = $3;
3974 		}
3975 		;
3976 mac_list	: xmac optnl {
3977 			$$ = $1;
3978 		}
3979 		| mac_list comma xmac {
3980 			if ($3 == NULL)
3981 				$$ = $1;
3982 			else if ($1 == NULL)
3983 				$$ = $3;
3984 			else {
3985 				$1->tail->next = $3;
3986 				$1->tail = $3->tail;
3987 				$$ = $1;
3988 			}
3989 		}
3990 
3991 fromto		: ALL				{
3992 			$$.src.host = NULL;
3993 			$$.src.port = NULL;
3994 			$$.dst.host = NULL;
3995 			$$.dst.port = NULL;
3996 			$$.src_os = NULL;
3997 		}
3998 		| from os to			{
3999 			$$.src = $1;
4000 			$$.src_os = $2;
4001 			$$.dst = $3;
4002 		}
4003 		;
4004 
4005 os		: /* empty */			{ $$ = NULL; }
4006 		| OS xos			{ $$ = $2; }
4007 		| OS '{' optnl os_list '}'	{ $$ = $4; }
4008 		;
4009 
4010 xos		: STRING {
4011 			$$ = calloc(1, sizeof(struct node_os));
4012 			if ($$ == NULL)
4013 				err(1, "os: calloc");
4014 			$$->os = $1;
4015 			$$->tail = $$;
4016 		}
4017 		;
4018 
4019 os_list		: xos optnl 			{ $$ = $1; }
4020 		| os_list comma xos optnl	{
4021 			$1->tail->next = $3;
4022 			$1->tail = $3;
4023 			$$ = $1;
4024 		}
4025 		;
4026 
4027 from		: /* empty */			{
4028 			$$.host = NULL;
4029 			$$.port = NULL;
4030 		}
4031 		| FROM ipportspec		{
4032 			$$ = $2;
4033 		}
4034 		;
4035 
4036 to		: /* empty */			{
4037 			$$.host = NULL;
4038 			$$.port = NULL;
4039 		}
4040 		| TO ipportspec		{
4041 			if (disallow_urpf_failed($2.host, "\"urpf-failed\" is "
4042 			    "not permitted in a destination address"))
4043 				YYERROR;
4044 			$$ = $2;
4045 		}
4046 		;
4047 
4048 ipportspec	: ipspec			{
4049 			$$.host = $1;
4050 			$$.port = NULL;
4051 		}
4052 		| ipspec PORT portspec		{
4053 			$$.host = $1;
4054 			$$.port = $3;
4055 		}
4056 		| PORT portspec			{
4057 			$$.host = NULL;
4058 			$$.port = $2;
4059 		}
4060 		;
4061 
4062 optnl		: '\n' optnl
4063 		|
4064 		;
4065 
4066 ipspec		: ANY				{ $$ = NULL; }
4067 		| xhost				{ $$ = $1; }
4068 		| '{' optnl host_list '}'	{ $$ = $3; }
4069 		;
4070 
4071 toipspec	: TO ipspec			{ $$ = $2; }
4072 		| /* empty */			{ $$ = NULL; }
4073 		;
4074 
4075 host_list	: ipspec optnl			{ $$ = $1; }
4076 		| host_list comma ipspec optnl	{
4077 			if ($1 == NULL) {
4078 				freehostlist($3);
4079 				$$ = $1;
4080 			} else if ($3 == NULL) {
4081 				freehostlist($1);
4082 				$$ = $3;
4083 			} else {
4084 				$1->tail->next = $3;
4085 				$1->tail = $3->tail;
4086 				$$ = $1;
4087 			}
4088 		}
4089 		;
4090 
4091 xhost		: not host			{
4092 			struct node_host	*n;
4093 
4094 			for (n = $2; n != NULL; n = n->next)
4095 				n->not = $1;
4096 			$$ = $2;
4097 		}
4098 		| not NOROUTE			{
4099 			$$ = calloc(1, sizeof(struct node_host));
4100 			if ($$ == NULL)
4101 				err(1, "xhost: calloc");
4102 			$$->addr.type = PF_ADDR_NOROUTE;
4103 			$$->next = NULL;
4104 			$$->not = $1;
4105 			$$->tail = $$;
4106 		}
4107 		| not URPFFAILED		{
4108 			$$ = calloc(1, sizeof(struct node_host));
4109 			if ($$ == NULL)
4110 				err(1, "xhost: calloc");
4111 			$$->addr.type = PF_ADDR_URPFFAILED;
4112 			$$->next = NULL;
4113 			$$->not = $1;
4114 			$$->tail = $$;
4115 		}
4116 		;
4117 
4118 host		: STRING			{
4119 			if (($$ = host($1, pf->opts)) == NULL)	{
4120 				/* error. "any" is handled elsewhere */
4121 				free($1);
4122 				yyerror("could not parse host specification");
4123 				YYERROR;
4124 			}
4125 			free($1);
4126 
4127 		}
4128 		| STRING '-' STRING		{
4129 			struct node_host *b, *e;
4130 
4131 			if ((b = host($1, pf->opts)) == NULL ||
4132 			    (e = host($3, pf->opts)) == NULL) {
4133 				free($1);
4134 				free($3);
4135 				yyerror("could not parse host specification");
4136 				YYERROR;
4137 			}
4138 			if (b->af != e->af ||
4139 			    b->addr.type != PF_ADDR_ADDRMASK ||
4140 			    e->addr.type != PF_ADDR_ADDRMASK ||
4141 			    unmask(&b->addr.v.a.mask) !=
4142 			    (b->af == AF_INET ? 32 : 128) ||
4143 			    unmask(&e->addr.v.a.mask) !=
4144 			    (e->af == AF_INET ? 32 : 128) ||
4145 			    b->next != NULL || b->not ||
4146 			    e->next != NULL || e->not) {
4147 				free(b);
4148 				free(e);
4149 				free($1);
4150 				free($3);
4151 				yyerror("invalid address range");
4152 				YYERROR;
4153 			}
4154 			memcpy(&b->addr.v.a.mask, &e->addr.v.a.addr,
4155 			    sizeof(b->addr.v.a.mask));
4156 			b->addr.type = PF_ADDR_RANGE;
4157 			$$ = b;
4158 			free(e);
4159 			free($1);
4160 			free($3);
4161 		}
4162 		| STRING '/' NUMBER		{
4163 			char	*buf;
4164 
4165 			if (asprintf(&buf, "%s/%lld", $1, (long long)$3) == -1)
4166 				err(1, "host: asprintf");
4167 			free($1);
4168 			if (($$ = host(buf, pf->opts)) == NULL)	{
4169 				/* error. "any" is handled elsewhere */
4170 				free(buf);
4171 				yyerror("could not parse host specification");
4172 				YYERROR;
4173 			}
4174 			free(buf);
4175 		}
4176 		| NUMBER '/' NUMBER		{
4177 			char	*buf;
4178 
4179 			/* ie. for 10/8 parsing */
4180 #ifdef __FreeBSD__
4181 			if (asprintf(&buf, "%lld/%lld", (long long)$1, (long long)$3) == -1)
4182 #else
4183 			if (asprintf(&buf, "%lld/%lld", $1, $3) == -1)
4184 #endif
4185 				err(1, "host: asprintf");
4186 			if (($$ = host(buf, pf->opts)) == NULL)	{
4187 				/* error. "any" is handled elsewhere */
4188 				free(buf);
4189 				yyerror("could not parse host specification");
4190 				YYERROR;
4191 			}
4192 			free(buf);
4193 		}
4194 		| dynaddr
4195 		| dynaddr '/' NUMBER		{
4196 			struct node_host	*n;
4197 
4198 			if ($3 < 0 || $3 > 128) {
4199 				yyerror("bit number too big");
4200 				YYERROR;
4201 			}
4202 			$$ = $1;
4203 			for (n = $1; n != NULL; n = n->next)
4204 				set_ipmask(n, $3);
4205 		}
4206 		| '<' STRING '>'	{
4207 			if (strlen($2) >= PF_TABLE_NAME_SIZE) {
4208 				yyerror("table name '%s' too long", $2);
4209 				free($2);
4210 				YYERROR;
4211 			}
4212 			$$ = calloc(1, sizeof(struct node_host));
4213 			if ($$ == NULL)
4214 				err(1, "host: calloc");
4215 			$$->addr.type = PF_ADDR_TABLE;
4216 			if (strlcpy($$->addr.v.tblname, $2,
4217 			    sizeof($$->addr.v.tblname)) >=
4218 			    sizeof($$->addr.v.tblname))
4219 				errx(1, "host: strlcpy");
4220 			free($2);
4221 			$$->next = NULL;
4222 			$$->tail = $$;
4223 		}
4224 		;
4225 
4226 number		: NUMBER
4227 		| STRING		{
4228 			u_long	ulval;
4229 
4230 			if (atoul($1, &ulval) == -1) {
4231 				yyerror("%s is not a number", $1);
4232 				free($1);
4233 				YYERROR;
4234 			} else
4235 				$$ = ulval;
4236 			free($1);
4237 		}
4238 		;
4239 
4240 dynaddr		: '(' STRING ')'		{
4241 			int	 flags = 0;
4242 			char	*p, *op;
4243 
4244 			op = $2;
4245 			if (!isalpha(op[0])) {
4246 				yyerror("invalid interface name '%s'", op);
4247 				free(op);
4248 				YYERROR;
4249 			}
4250 			while ((p = strrchr($2, ':')) != NULL) {
4251 				if (!strcmp(p+1, "network"))
4252 					flags |= PFI_AFLAG_NETWORK;
4253 				else if (!strcmp(p+1, "broadcast"))
4254 					flags |= PFI_AFLAG_BROADCAST;
4255 				else if (!strcmp(p+1, "peer"))
4256 					flags |= PFI_AFLAG_PEER;
4257 				else if (!strcmp(p+1, "0"))
4258 					flags |= PFI_AFLAG_NOALIAS;
4259 				else {
4260 					yyerror("interface %s has bad modifier",
4261 					    $2);
4262 					free(op);
4263 					YYERROR;
4264 				}
4265 				*p = '\0';
4266 			}
4267 			if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) {
4268 				free(op);
4269 				yyerror("illegal combination of "
4270 				    "interface modifiers");
4271 				YYERROR;
4272 			}
4273 			$$ = calloc(1, sizeof(struct node_host));
4274 			if ($$ == NULL)
4275 				err(1, "address: calloc");
4276 			$$->af = 0;
4277 			set_ipmask($$, 128);
4278 			$$->addr.type = PF_ADDR_DYNIFTL;
4279 			$$->addr.iflags = flags;
4280 			if (strlcpy($$->addr.v.ifname, $2,
4281 			    sizeof($$->addr.v.ifname)) >=
4282 			    sizeof($$->addr.v.ifname)) {
4283 				free(op);
4284 				free($$);
4285 				yyerror("interface name too long");
4286 				YYERROR;
4287 			}
4288 			free(op);
4289 			$$->next = NULL;
4290 			$$->tail = $$;
4291 		}
4292 		;
4293 
4294 portspec	: port_item			{ $$ = $1; }
4295 		| '{' optnl port_list '}'	{ $$ = $3; }
4296 		;
4297 
4298 port_list	: port_item optnl		{ $$ = $1; }
4299 		| port_list comma port_item optnl	{
4300 			$1->tail->next = $3;
4301 			$1->tail = $3;
4302 			$$ = $1;
4303 		}
4304 		;
4305 
4306 port_item	: portrange			{
4307 			$$ = calloc(1, sizeof(struct node_port));
4308 			if ($$ == NULL)
4309 				err(1, "port_item: calloc");
4310 			$$->port[0] = $1.a;
4311 			$$->port[1] = $1.b;
4312 			if ($1.t) {
4313 				$$->op = PF_OP_RRG;
4314 				if (validate_range($$->op, $$->port[0],
4315 				    $$->port[1])) {
4316 					yyerror("invalid port range");
4317 					YYERROR;
4318 				}
4319 			} else
4320 				$$->op = PF_OP_EQ;
4321 			$$->next = NULL;
4322 			$$->tail = $$;
4323 		}
4324 		| unaryop portrange	{
4325 			if ($2.t) {
4326 				yyerror("':' cannot be used with an other "
4327 				    "port operator");
4328 				YYERROR;
4329 			}
4330 			$$ = calloc(1, sizeof(struct node_port));
4331 			if ($$ == NULL)
4332 				err(1, "port_item: calloc");
4333 			$$->port[0] = $2.a;
4334 			$$->port[1] = $2.b;
4335 			$$->op = $1;
4336 			if (validate_range($$->op, $$->port[0], $$->port[1])) {
4337 				yyerror("invalid port range");
4338 				YYERROR;
4339 			}
4340 			$$->next = NULL;
4341 			$$->tail = $$;
4342 		}
4343 		| portrange PORTBINARY portrange	{
4344 			if ($1.t || $3.t) {
4345 				yyerror("':' cannot be used with an other "
4346 				    "port operator");
4347 				YYERROR;
4348 			}
4349 			$$ = calloc(1, sizeof(struct node_port));
4350 			if ($$ == NULL)
4351 				err(1, "port_item: calloc");
4352 			$$->port[0] = $1.a;
4353 			$$->port[1] = $3.a;
4354 			$$->op = $2;
4355 			if (validate_range($$->op, $$->port[0], $$->port[1])) {
4356 				yyerror("invalid port range");
4357 				YYERROR;
4358 			}
4359 			$$->next = NULL;
4360 			$$->tail = $$;
4361 		}
4362 		;
4363 
4364 portplain	: numberstring			{
4365 			if (parseport($1, &$$, 0) == -1) {
4366 				free($1);
4367 				YYERROR;
4368 			}
4369 			free($1);
4370 		}
4371 		;
4372 
4373 portrange	: numberstring			{
4374 			if (parseport($1, &$$, PPORT_RANGE) == -1) {
4375 				free($1);
4376 				YYERROR;
4377 			}
4378 			free($1);
4379 		}
4380 		;
4381 
4382 uids		: uid_item			{ $$ = $1; }
4383 		| '{' optnl uid_list '}'	{ $$ = $3; }
4384 		;
4385 
4386 uid_list	: uid_item optnl		{ $$ = $1; }
4387 		| uid_list comma uid_item optnl	{
4388 			$1->tail->next = $3;
4389 			$1->tail = $3;
4390 			$$ = $1;
4391 		}
4392 		;
4393 
4394 uid_item	: uid				{
4395 			$$ = calloc(1, sizeof(struct node_uid));
4396 			if ($$ == NULL)
4397 				err(1, "uid_item: calloc");
4398 			$$->uid[0] = $1;
4399 			$$->uid[1] = $1;
4400 			$$->op = PF_OP_EQ;
4401 			$$->next = NULL;
4402 			$$->tail = $$;
4403 		}
4404 		| unaryop uid			{
4405 			if ($2 == -1 && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
4406 				yyerror("user unknown requires operator = or "
4407 				    "!=");
4408 				YYERROR;
4409 			}
4410 			$$ = calloc(1, sizeof(struct node_uid));
4411 			if ($$ == NULL)
4412 				err(1, "uid_item: calloc");
4413 			$$->uid[0] = $2;
4414 			$$->uid[1] = $2;
4415 			$$->op = $1;
4416 			$$->next = NULL;
4417 			$$->tail = $$;
4418 		}
4419 		| uid PORTBINARY uid		{
4420 			if ($1 == -1 || $3 == -1) {
4421 				yyerror("user unknown requires operator = or "
4422 				    "!=");
4423 				YYERROR;
4424 			}
4425 			$$ = calloc(1, sizeof(struct node_uid));
4426 			if ($$ == NULL)
4427 				err(1, "uid_item: calloc");
4428 			$$->uid[0] = $1;
4429 			$$->uid[1] = $3;
4430 			$$->op = $2;
4431 			$$->next = NULL;
4432 			$$->tail = $$;
4433 		}
4434 		;
4435 
4436 uid		: STRING			{
4437 			if (!strcmp($1, "unknown"))
4438 				$$ = -1;
4439 			else {
4440 				uid_t uid;
4441 
4442 				if (uid_from_user($1, &uid) == -1) {
4443 					yyerror("unknown user %s", $1);
4444 					free($1);
4445 					YYERROR;
4446 				}
4447 				$$ = uid;
4448 			}
4449 			free($1);
4450 		}
4451 		| NUMBER			{
4452 			if ($1 < 0 || $1 >= UID_MAX) {
4453 				yyerror("illegal uid value %lu", $1);
4454 				YYERROR;
4455 			}
4456 			$$ = $1;
4457 		}
4458 		;
4459 
4460 gids		: gid_item			{ $$ = $1; }
4461 		| '{' optnl gid_list '}'	{ $$ = $3; }
4462 		;
4463 
4464 gid_list	: gid_item optnl		{ $$ = $1; }
4465 		| gid_list comma gid_item optnl	{
4466 			$1->tail->next = $3;
4467 			$1->tail = $3;
4468 			$$ = $1;
4469 		}
4470 		;
4471 
4472 gid_item	: gid				{
4473 			$$ = calloc(1, sizeof(struct node_gid));
4474 			if ($$ == NULL)
4475 				err(1, "gid_item: calloc");
4476 			$$->gid[0] = $1;
4477 			$$->gid[1] = $1;
4478 			$$->op = PF_OP_EQ;
4479 			$$->next = NULL;
4480 			$$->tail = $$;
4481 		}
4482 		| unaryop gid			{
4483 			if ($2 == -1 && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
4484 				yyerror("group unknown requires operator = or "
4485 				    "!=");
4486 				YYERROR;
4487 			}
4488 			$$ = calloc(1, sizeof(struct node_gid));
4489 			if ($$ == NULL)
4490 				err(1, "gid_item: calloc");
4491 			$$->gid[0] = $2;
4492 			$$->gid[1] = $2;
4493 			$$->op = $1;
4494 			$$->next = NULL;
4495 			$$->tail = $$;
4496 		}
4497 		| gid PORTBINARY gid		{
4498 			if ($1 == -1 || $3 == -1) {
4499 				yyerror("group unknown requires operator = or "
4500 				    "!=");
4501 				YYERROR;
4502 			}
4503 			$$ = calloc(1, sizeof(struct node_gid));
4504 			if ($$ == NULL)
4505 				err(1, "gid_item: calloc");
4506 			$$->gid[0] = $1;
4507 			$$->gid[1] = $3;
4508 			$$->op = $2;
4509 			$$->next = NULL;
4510 			$$->tail = $$;
4511 		}
4512 		;
4513 
4514 gid		: STRING			{
4515 			if (!strcmp($1, "unknown"))
4516 				$$ = -1;
4517 			else {
4518 				gid_t gid;
4519 
4520 				if (gid_from_group($1, &gid) == -1) {
4521 					yyerror("unknown group %s", $1);
4522 					free($1);
4523 					YYERROR;
4524 				}
4525 				$$ = gid;
4526 			}
4527 			free($1);
4528 		}
4529 		| NUMBER			{
4530 			if ($1 < 0 || $1 >= GID_MAX) {
4531 				yyerror("illegal gid value %lu", $1);
4532 				YYERROR;
4533 			}
4534 			$$ = $1;
4535 		}
4536 		;
4537 
4538 flag		: STRING			{
4539 			int	f;
4540 
4541 			if ((f = parse_flags($1)) < 0) {
4542 				yyerror("bad flags %s", $1);
4543 				free($1);
4544 				YYERROR;
4545 			}
4546 			free($1);
4547 			$$.b1 = f;
4548 		}
4549 		;
4550 
4551 flags		: FLAGS flag '/' flag	{ $$.b1 = $2.b1; $$.b2 = $4.b1; }
4552 		| FLAGS '/' flag	{ $$.b1 = 0; $$.b2 = $3.b1; }
4553 		| FLAGS ANY		{ $$.b1 = 0; $$.b2 = 0; }
4554 		;
4555 
4556 icmpspec	: ICMPTYPE icmp_item			{ $$ = $2; }
4557 		| ICMPTYPE '{' optnl icmp_list '}'	{ $$ = $4; }
4558 		| ICMP6TYPE icmp6_item			{ $$ = $2; }
4559 		| ICMP6TYPE '{' optnl icmp6_list '}'	{ $$ = $4; }
4560 		;
4561 
4562 icmp_list	: icmp_item optnl		{ $$ = $1; }
4563 		| icmp_list comma icmp_item optnl {
4564 			$1->tail->next = $3;
4565 			$1->tail = $3;
4566 			$$ = $1;
4567 		}
4568 		;
4569 
4570 icmp6_list	: icmp6_item optnl		{ $$ = $1; }
4571 		| icmp6_list comma icmp6_item optnl {
4572 			$1->tail->next = $3;
4573 			$1->tail = $3;
4574 			$$ = $1;
4575 		}
4576 		;
4577 
4578 icmp_item	: icmptype		{
4579 			$$ = calloc(1, sizeof(struct node_icmp));
4580 			if ($$ == NULL)
4581 				err(1, "icmp_item: calloc");
4582 			$$->type = $1;
4583 			$$->code = 0;
4584 			$$->proto = IPPROTO_ICMP;
4585 			$$->next = NULL;
4586 			$$->tail = $$;
4587 		}
4588 		| icmptype CODE STRING	{
4589 			const struct icmpcodeent	*p;
4590 
4591 			if ((p = geticmpcodebyname($1-1, $3, AF_INET)) == NULL) {
4592 				yyerror("unknown icmp-code %s", $3);
4593 				free($3);
4594 				YYERROR;
4595 			}
4596 
4597 			free($3);
4598 			$$ = calloc(1, sizeof(struct node_icmp));
4599 			if ($$ == NULL)
4600 				err(1, "icmp_item: calloc");
4601 			$$->type = $1;
4602 			$$->code = p->code + 1;
4603 			$$->proto = IPPROTO_ICMP;
4604 			$$->next = NULL;
4605 			$$->tail = $$;
4606 		}
4607 		| icmptype CODE NUMBER	{
4608 			if ($3 < 0 || $3 > 255) {
4609 				yyerror("illegal icmp-code %lu", $3);
4610 				YYERROR;
4611 			}
4612 			$$ = calloc(1, sizeof(struct node_icmp));
4613 			if ($$ == NULL)
4614 				err(1, "icmp_item: calloc");
4615 			$$->type = $1;
4616 			$$->code = $3 + 1;
4617 			$$->proto = IPPROTO_ICMP;
4618 			$$->next = NULL;
4619 			$$->tail = $$;
4620 		}
4621 		;
4622 
4623 icmp6_item	: icmp6type		{
4624 			$$ = calloc(1, sizeof(struct node_icmp));
4625 			if ($$ == NULL)
4626 				err(1, "icmp_item: calloc");
4627 			$$->type = $1;
4628 			$$->code = 0;
4629 			$$->proto = IPPROTO_ICMPV6;
4630 			$$->next = NULL;
4631 			$$->tail = $$;
4632 		}
4633 		| icmp6type CODE STRING	{
4634 			const struct icmpcodeent	*p;
4635 
4636 			if ((p = geticmpcodebyname($1-1, $3, AF_INET6)) == NULL) {
4637 				yyerror("unknown icmp6-code %s", $3);
4638 				free($3);
4639 				YYERROR;
4640 			}
4641 			free($3);
4642 
4643 			$$ = calloc(1, sizeof(struct node_icmp));
4644 			if ($$ == NULL)
4645 				err(1, "icmp_item: calloc");
4646 			$$->type = $1;
4647 			$$->code = p->code + 1;
4648 			$$->proto = IPPROTO_ICMPV6;
4649 			$$->next = NULL;
4650 			$$->tail = $$;
4651 		}
4652 		| icmp6type CODE NUMBER	{
4653 			if ($3 < 0 || $3 > 255) {
4654 				yyerror("illegal icmp-code %lu", $3);
4655 				YYERROR;
4656 			}
4657 			$$ = calloc(1, sizeof(struct node_icmp));
4658 			if ($$ == NULL)
4659 				err(1, "icmp_item: calloc");
4660 			$$->type = $1;
4661 			$$->code = $3 + 1;
4662 			$$->proto = IPPROTO_ICMPV6;
4663 			$$->next = NULL;
4664 			$$->tail = $$;
4665 		}
4666 		;
4667 
4668 icmptype	: STRING			{
4669 			const struct icmptypeent	*p;
4670 
4671 			if ((p = geticmptypebyname($1, AF_INET)) == NULL) {
4672 				yyerror("unknown icmp-type %s", $1);
4673 				free($1);
4674 				YYERROR;
4675 			}
4676 			$$ = p->type + 1;
4677 			free($1);
4678 		}
4679 		| NUMBER			{
4680 			if ($1 < 0 || $1 > 255) {
4681 				yyerror("illegal icmp-type %lu", $1);
4682 				YYERROR;
4683 			}
4684 			$$ = $1 + 1;
4685 		}
4686 		;
4687 
4688 icmp6type	: STRING			{
4689 			const struct icmptypeent	*p;
4690 
4691 			if ((p = geticmptypebyname($1, AF_INET6)) ==
4692 			    NULL) {
4693 				yyerror("unknown icmp6-type %s", $1);
4694 				free($1);
4695 				YYERROR;
4696 			}
4697 			$$ = p->type + 1;
4698 			free($1);
4699 		}
4700 		| NUMBER			{
4701 			if ($1 < 0 || $1 > 255) {
4702 				yyerror("illegal icmp6-type %lu", $1);
4703 				YYERROR;
4704 			}
4705 			$$ = $1 + 1;
4706 		}
4707 		;
4708 
4709 tos	: STRING			{
4710 			int val;
4711 			char *end;
4712 
4713 			if (map_tos($1, &val))
4714 				$$ = val;
4715 			else if ($1[0] == '0' && $1[1] == 'x') {
4716 				errno = 0;
4717 				$$ = strtoul($1, &end, 16);
4718 				if (errno || *end != '\0')
4719 					$$ = 256;
4720 			} else
4721 				$$ = 256;		/* flag bad argument */
4722 			if ($$ < 0 || $$ > 255) {
4723 				yyerror("illegal tos value %s", $1);
4724 				free($1);
4725 				YYERROR;
4726 			}
4727 			free($1);
4728 		}
4729 		| NUMBER			{
4730 			$$ = $1;
4731 			if ($$ < 0 || $$ > 255) {
4732 				yyerror("illegal tos value %lu", $1);
4733 				YYERROR;
4734 			}
4735 		}
4736 		;
4737 
4738 sourcetrack	: SOURCETRACK		{ $$ = PF_SRCTRACK; }
4739 		| SOURCETRACK GLOBAL	{ $$ = PF_SRCTRACK_GLOBAL; }
4740 		| SOURCETRACK RULE	{ $$ = PF_SRCTRACK_RULE; }
4741 		;
4742 
4743 statelock	: IFBOUND {
4744 			$$ = PFRULE_IFBOUND;
4745 		}
4746 		| FLOATING {
4747 			$$ = 0;
4748 		}
4749 		;
4750 
4751 keep		: NO STATE			{
4752 			$$.action = 0;
4753 			$$.options = NULL;
4754 		}
4755 		| KEEP STATE state_opt_spec	{
4756 			$$.action = PF_STATE_NORMAL;
4757 			$$.options = $3;
4758 		}
4759 		| MODULATE STATE state_opt_spec {
4760 			$$.action = PF_STATE_MODULATE;
4761 			$$.options = $3;
4762 		}
4763 		| SYNPROXY STATE state_opt_spec {
4764 			$$.action = PF_STATE_SYNPROXY;
4765 			$$.options = $3;
4766 		}
4767 		;
4768 
4769 flush		: /* empty */			{ $$ = 0; }
4770 		| FLUSH				{ $$ = PF_FLUSH; }
4771 		| FLUSH GLOBAL			{
4772 			$$ = PF_FLUSH | PF_FLUSH_GLOBAL;
4773 		}
4774 		;
4775 
4776 state_opt_spec	: '(' state_opt_list ')'	{ $$ = $2; }
4777 		| /* empty */			{ $$ = NULL; }
4778 		;
4779 
4780 state_opt_list	: state_opt_item		{ $$ = $1; }
4781 		| state_opt_list comma state_opt_item {
4782 			$1->tail->next = $3;
4783 			$1->tail = $3;
4784 			$$ = $1;
4785 		}
4786 		;
4787 
4788 state_opt_item	: MAXIMUM NUMBER		{
4789 			if ($2 < 0 || $2 > UINT_MAX) {
4790 				yyerror("only positive values permitted");
4791 				YYERROR;
4792 			}
4793 			$$ = calloc(1, sizeof(struct node_state_opt));
4794 			if ($$ == NULL)
4795 				err(1, "state_opt_item: calloc");
4796 			$$->type = PF_STATE_OPT_MAX;
4797 			$$->data.max_states = $2;
4798 			$$->next = NULL;
4799 			$$->tail = $$;
4800 		}
4801 		| NOSYNC				{
4802 			$$ = calloc(1, sizeof(struct node_state_opt));
4803 			if ($$ == NULL)
4804 				err(1, "state_opt_item: calloc");
4805 			$$->type = PF_STATE_OPT_NOSYNC;
4806 			$$->next = NULL;
4807 			$$->tail = $$;
4808 		}
4809 		| MAXSRCSTATES NUMBER			{
4810 			if ($2 < 0 || $2 > UINT_MAX) {
4811 				yyerror("only positive values permitted");
4812 				YYERROR;
4813 			}
4814 			$$ = calloc(1, sizeof(struct node_state_opt));
4815 			if ($$ == NULL)
4816 				err(1, "state_opt_item: calloc");
4817 			$$->type = PF_STATE_OPT_MAX_SRC_STATES;
4818 			$$->data.max_src_states = $2;
4819 			$$->next = NULL;
4820 			$$->tail = $$;
4821 		}
4822 		| MAXSRCCONN NUMBER			{
4823 			if ($2 < 0 || $2 > UINT_MAX) {
4824 				yyerror("only positive values permitted");
4825 				YYERROR;
4826 			}
4827 			$$ = calloc(1, sizeof(struct node_state_opt));
4828 			if ($$ == NULL)
4829 				err(1, "state_opt_item: calloc");
4830 			$$->type = PF_STATE_OPT_MAX_SRC_CONN;
4831 			$$->data.max_src_conn = $2;
4832 			$$->next = NULL;
4833 			$$->tail = $$;
4834 		}
4835 		| MAXSRCCONNRATE NUMBER '/' NUMBER	{
4836 			if ($2 < 0 || $2 > UINT_MAX ||
4837 			    $4 < 0 || $4 > UINT_MAX) {
4838 				yyerror("only positive values permitted");
4839 				YYERROR;
4840 			}
4841 			$$ = calloc(1, sizeof(struct node_state_opt));
4842 			if ($$ == NULL)
4843 				err(1, "state_opt_item: calloc");
4844 			$$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE;
4845 			$$->data.max_src_conn_rate.limit = $2;
4846 			$$->data.max_src_conn_rate.seconds = $4;
4847 			$$->next = NULL;
4848 			$$->tail = $$;
4849 		}
4850 		| OVERLOAD '<' STRING '>' flush		{
4851 			if (strlen($3) >= PF_TABLE_NAME_SIZE) {
4852 				yyerror("table name '%s' too long", $3);
4853 				free($3);
4854 				YYERROR;
4855 			}
4856 			$$ = calloc(1, sizeof(struct node_state_opt));
4857 			if ($$ == NULL)
4858 				err(1, "state_opt_item: calloc");
4859 			if (strlcpy($$->data.overload.tblname, $3,
4860 			    PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE)
4861 				errx(1, "state_opt_item: strlcpy");
4862 			free($3);
4863 			$$->type = PF_STATE_OPT_OVERLOAD;
4864 			$$->data.overload.flush = $5;
4865 			$$->next = NULL;
4866 			$$->tail = $$;
4867 		}
4868 		| MAXSRCNODES NUMBER			{
4869 			if ($2 < 0 || $2 > UINT_MAX) {
4870 				yyerror("only positive values permitted");
4871 				YYERROR;
4872 			}
4873 			$$ = calloc(1, sizeof(struct node_state_opt));
4874 			if ($$ == NULL)
4875 				err(1, "state_opt_item: calloc");
4876 			$$->type = PF_STATE_OPT_MAX_SRC_NODES;
4877 			$$->data.max_src_nodes = $2;
4878 			$$->next = NULL;
4879 			$$->tail = $$;
4880 		}
4881 		| sourcetrack {
4882 			$$ = calloc(1, sizeof(struct node_state_opt));
4883 			if ($$ == NULL)
4884 				err(1, "state_opt_item: calloc");
4885 			$$->type = PF_STATE_OPT_SRCTRACK;
4886 			$$->data.src_track = $1;
4887 			$$->next = NULL;
4888 			$$->tail = $$;
4889 		}
4890 		| statelock {
4891 			$$ = calloc(1, sizeof(struct node_state_opt));
4892 			if ($$ == NULL)
4893 				err(1, "state_opt_item: calloc");
4894 			$$->type = PF_STATE_OPT_STATELOCK;
4895 			$$->data.statelock = $1;
4896 			$$->next = NULL;
4897 			$$->tail = $$;
4898 		}
4899 		| SLOPPY {
4900 			$$ = calloc(1, sizeof(struct node_state_opt));
4901 			if ($$ == NULL)
4902 				err(1, "state_opt_item: calloc");
4903 			$$->type = PF_STATE_OPT_SLOPPY;
4904 			$$->next = NULL;
4905 			$$->tail = $$;
4906 		}
4907 		| PFLOW {
4908 			$$ = calloc(1, sizeof(struct node_state_opt));
4909 			if ($$ == NULL)
4910 				err(1, "state_opt_item: calloc");
4911 			$$->type = PF_STATE_OPT_PFLOW;
4912 			$$->next = NULL;
4913 			$$->tail = $$;
4914 		}
4915 		| ALLOW_RELATED {
4916 			$$ = calloc(1, sizeof(struct node_state_opt));
4917 			if ($$ == NULL)
4918 				err(1, "state_opt_item: calloc");
4919 			$$->type = PF_STATE_OPT_ALLOW_RELATED;
4920 			$$->next = NULL;
4921 			$$->tail = $$;
4922 		}
4923 		| STRING NUMBER			{
4924 			int	i;
4925 
4926 			if ($2 < 0 || $2 > UINT_MAX) {
4927 				yyerror("only positive values permitted");
4928 				YYERROR;
4929 			}
4930 			for (i = 0; pf_timeouts[i].name &&
4931 			    strcmp(pf_timeouts[i].name, $1); ++i)
4932 				;	/* nothing */
4933 			if (!pf_timeouts[i].name) {
4934 				yyerror("illegal timeout name %s", $1);
4935 				free($1);
4936 				YYERROR;
4937 			}
4938 			if (strchr(pf_timeouts[i].name, '.') == NULL) {
4939 				yyerror("illegal state timeout %s", $1);
4940 				free($1);
4941 				YYERROR;
4942 			}
4943 			free($1);
4944 			$$ = calloc(1, sizeof(struct node_state_opt));
4945 			if ($$ == NULL)
4946 				err(1, "state_opt_item: calloc");
4947 			$$->type = PF_STATE_OPT_TIMEOUT;
4948 			$$->data.timeout.number = pf_timeouts[i].timeout;
4949 			$$->data.timeout.seconds = $2;
4950 			$$->next = NULL;
4951 			$$->tail = $$;
4952 		}
4953 		;
4954 
4955 label		: LABEL STRING			{
4956 			$$ = $2;
4957 		}
4958 		;
4959 
4960 etherqname	: QUEUE STRING				{
4961 			$$.qname = $2;
4962 		}
4963 		| QUEUE '(' STRING ')'			{
4964 			$$.qname = $3;
4965 		}
4966 		;
4967 
4968 qname		: QUEUE STRING				{
4969 			$$.qname = $2;
4970 			$$.pqname = NULL;
4971 		}
4972 		| QUEUE '(' STRING ')'			{
4973 			$$.qname = $3;
4974 			$$.pqname = NULL;
4975 		}
4976 		| QUEUE '(' STRING comma STRING ')'	{
4977 			$$.qname = $3;
4978 			$$.pqname = $5;
4979 		}
4980 		;
4981 
4982 no		: /* empty */			{ $$ = 0; }
4983 		| NO				{ $$ = 1; }
4984 		;
4985 
4986 portstar	: numberstring			{
4987 			if (parseport($1, &$$, PPORT_RANGE|PPORT_STAR) == -1) {
4988 				free($1);
4989 				YYERROR;
4990 			}
4991 			free($1);
4992 		}
4993 		;
4994 
4995 redir_host	: host				{ $$ = $1; }
4996 		| '{' optnl redir_host_list '}'	{ $$ = $3; }
4997 		;
4998 
4999 redir_host_list	: host optnl			{ $$ = $1; }
5000 		| redir_host_list comma host optnl {
5001 			$1->tail->next = $3;
5002 			$1->tail = $3->tail;
5003 			$$ = $1;
5004 		}
5005 		;
5006 
5007 /* Redirection without port */
5008 no_port_redirspec: redir_host pool_opts	{
5009 			$$ = calloc(1, sizeof(struct redirspec));
5010 			if ($$ == NULL)
5011 				err(1, "redirspec: calloc");
5012 			$$->host = $1;
5013 			$$->pool_opts = $2;
5014 			$$->rport.a = $$->rport.b = $$->rport.t = 0;
5015 		}
5016 		;
5017 
5018 /* Redirection with optional port */
5019 port_redirspec	: no_port_redirspec;
5020 		| redir_host PORT portstar pool_opts {
5021 			$$ = calloc(1, sizeof(struct redirspec));
5022 			if ($$ == NULL)
5023 				err(1, "redirspec: calloc");
5024 			$$->host = $1;
5025 			$$->rport = $3;
5026 			$$->pool_opts = $4;
5027 		}
5028 
5029 /* Redirection with an arrow and an optional port: FreeBSD NAT rules */
5030 nat_redirspec	: /* empty */		{ $$ = NULL; }
5031 		| ARROW port_redirspec {
5032 			$$ = $2;
5033 		}
5034 		;
5035 
5036 /* Redirection with interfaces and without ports: route-to rules */
5037 route_redirspec	: routespec pool_opts {
5038 			$$ = calloc(1, sizeof(struct redirspec));
5039 			if ($$ == NULL)
5040 				err(1, "redirspec: calloc");
5041 			$$->host = $1;
5042 			$$->pool_opts = $2;
5043 		}
5044 		;
5045 
5046 hashkey		: /* empty */
5047 		{
5048 			$$ = calloc(1, sizeof(struct pf_poolhashkey));
5049 			if ($$ == NULL)
5050 				err(1, "hashkey: calloc");
5051 			$$->key32[0] = arc4random();
5052 			$$->key32[1] = arc4random();
5053 			$$->key32[2] = arc4random();
5054 			$$->key32[3] = arc4random();
5055 		}
5056 		| string
5057 		{
5058 			if (!strncmp($1, "0x", 2)) {
5059 				if (strlen($1) != 34) {
5060 					free($1);
5061 					yyerror("hex key must be 128 bits "
5062 						"(32 hex digits) long");
5063 					YYERROR;
5064 				}
5065 				$$ = calloc(1, sizeof(struct pf_poolhashkey));
5066 				if ($$ == NULL)
5067 					err(1, "hashkey: calloc");
5068 
5069 				if (sscanf($1, "0x%8x%8x%8x%8x",
5070 				    &$$->key32[0], &$$->key32[1],
5071 				    &$$->key32[2], &$$->key32[3]) != 4) {
5072 					free($$);
5073 					free($1);
5074 					yyerror("invalid hex key");
5075 					YYERROR;
5076 				}
5077 			} else {
5078 				MD5_CTX	context;
5079 
5080 				$$ = calloc(1, sizeof(struct pf_poolhashkey));
5081 				if ($$ == NULL)
5082 					err(1, "hashkey: calloc");
5083 				MD5Init(&context);
5084 				MD5Update(&context, (unsigned char *)$1,
5085 				    strlen($1));
5086 				MD5Final((unsigned char *)$$, &context);
5087 				HTONL($$->key32[0]);
5088 				HTONL($$->key32[1]);
5089 				HTONL($$->key32[2]);
5090 				HTONL($$->key32[3]);
5091 			}
5092 			free($1);
5093 		}
5094 		;
5095 
5096 pool_opts	:	{ bzero(&pool_opts, sizeof pool_opts); }
5097 		    pool_opts_l
5098 			{ $$ = pool_opts; }
5099 		| /* empty */	{
5100 			bzero(&pool_opts, sizeof pool_opts);
5101 			$$ = pool_opts;
5102 		}
5103 		;
5104 
5105 pool_opts_l	: pool_opts_l pool_opt
5106 		| pool_opt
5107 		;
5108 
5109 pool_opt	: BITMASK	{
5110 			if (pool_opts.type) {
5111 				yyerror("pool type cannot be redefined");
5112 				YYERROR;
5113 			}
5114 			pool_opts.type =  PF_POOL_BITMASK;
5115 		}
5116 		| RANDOM	{
5117 			if (pool_opts.type) {
5118 				yyerror("pool type cannot be redefined");
5119 				YYERROR;
5120 			}
5121 			pool_opts.type = PF_POOL_RANDOM;
5122 		}
5123 		| SOURCEHASH hashkey {
5124 			if (pool_opts.type) {
5125 				yyerror("pool type cannot be redefined");
5126 				YYERROR;
5127 			}
5128 			pool_opts.type = PF_POOL_SRCHASH;
5129 			pool_opts.key = $2;
5130 		}
5131 		| ROUNDROBIN	{
5132 			if (pool_opts.type) {
5133 				yyerror("pool type cannot be redefined");
5134 				YYERROR;
5135 			}
5136 			pool_opts.type = PF_POOL_ROUNDROBIN;
5137 		}
5138 		| STATICPORT	{
5139 			if (pool_opts.staticport) {
5140 				yyerror("static-port cannot be redefined");
5141 				YYERROR;
5142 			}
5143 			pool_opts.staticport = 1;
5144 		}
5145 		| STICKYADDRESS	{
5146 			if (pool_opts.marker & POM_STICKYADDRESS) {
5147 				yyerror("sticky-address cannot be redefined");
5148 				YYERROR;
5149 			}
5150 			pool_opts.marker |= POM_STICKYADDRESS;
5151 			pool_opts.opts |= PF_POOL_STICKYADDR;
5152 		}
5153 		| ENDPI {
5154 			if (pool_opts.marker & POM_ENDPI) {
5155 				yyerror("endpoint-independent cannot be redefined");
5156 				YYERROR;
5157 			}
5158 			pool_opts.marker |= POM_ENDPI;
5159 			pool_opts.opts |= PF_POOL_ENDPI;
5160 		}
5161 		| IPV6NH {
5162 			if (pool_opts.marker & POM_IPV6NH) {
5163 				yyerror("prefer-ipv6-nexthop cannot be redefined");
5164 				YYERROR;
5165 			}
5166 			pool_opts.marker |= POM_IPV6NH;
5167 			pool_opts.opts |= PF_POOL_IPV6NH;
5168 		}
5169 		| MAPEPORTSET number '/' number '/' number {
5170 			if (pool_opts.mape.offset) {
5171 				yyerror("map-e-portset cannot be redefined");
5172 				YYERROR;
5173 			}
5174 			if (pool_opts.type) {
5175 				yyerror("map-e-portset cannot be used with "
5176 					"address pools");
5177 				YYERROR;
5178 			}
5179 			if ($2 <= 0 || $2 >= 16) {
5180 				yyerror("MAP-E PSID offset must be 1-15");
5181 				YYERROR;
5182 			}
5183 			if ($4 < 0 || $4 >= 16 || $2 + $4 > 16) {
5184 				yyerror("Invalid MAP-E PSID length");
5185 				YYERROR;
5186 			} else if ($4 == 0) {
5187 				yyerror("PSID Length = 0: this means"
5188 				    " you do not need MAP-E");
5189 				YYERROR;
5190 			}
5191 			if ($6 < 0 || $6 > 65535) {
5192 				yyerror("Invalid MAP-E PSID");
5193 				YYERROR;
5194 			}
5195 			pool_opts.mape.offset = $2;
5196 			pool_opts.mape.psidlen = $4;
5197 			pool_opts.mape.psid = $6;
5198 		}
5199 		;
5200 
5201 binat_redirspec	: /* empty */			{ $$ = NULL; }
5202 		| ARROW host			{
5203 			$$ = calloc(1, sizeof(struct redirspec));
5204 			if ($$ == NULL)
5205 				err(1, "redirspec: calloc");
5206 			$$->host = $2;
5207 			$$->rport.a = $$->rport.b = $$->rport.t = 0;
5208 		}
5209 		| ARROW host PORT portstar	{
5210 			$$ = calloc(1, sizeof(struct redirspec));
5211 			if ($$ == NULL)
5212 				err(1, "redirspec: calloc");
5213 			$$->host = $2;
5214 			$$->rport = $4;
5215 		}
5216 		;
5217 
5218 natpasslog	: /* empty */	{ $$.b1 = $$.b2 = 0; $$.w2 = 0; }
5219 		| PASS		{ $$.b1 = 1; $$.b2 = 0; $$.w2 = 0; }
5220 		| PASS log	{ $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; }
5221 		| log		{ $$.b1 = 0; $$.b2 = $1.log; $$.w2 = $1.logif; }
5222 		;
5223 
5224 nataction	: no NAT natpasslog {
5225 			if ($1 && $3.b1) {
5226 				yyerror("\"pass\" not valid with \"no\"");
5227 				YYERROR;
5228 			}
5229 			if ($1)
5230 				$$.b1 = PF_NONAT;
5231 			else
5232 				$$.b1 = PF_NAT;
5233 			$$.b2 = $3.b1;
5234 			$$.w = $3.b2;
5235 			$$.w2 = $3.w2;
5236 		}
5237 		| no RDR natpasslog {
5238 			if ($1 && $3.b1) {
5239 				yyerror("\"pass\" not valid with \"no\"");
5240 				YYERROR;
5241 			}
5242 			if ($1)
5243 				$$.b1 = PF_NORDR;
5244 			else
5245 				$$.b1 = PF_RDR;
5246 			$$.b2 = $3.b1;
5247 			$$.w = $3.b2;
5248 			$$.w2 = $3.w2;
5249 		}
5250 		;
5251 
5252 natrule		: nataction interface af proto fromto tag tagged rtable
5253 		    nat_redirspec
5254 		{
5255 			struct pfctl_rule	r;
5256 			struct node_state_opt	*o;
5257 
5258 			if (check_rulestate(PFCTL_STATE_NAT))
5259 				YYERROR;
5260 
5261 			pfctl_init_rule(&r);
5262 
5263 			r.action = $1.b1;
5264 			r.natpass = $1.b2;
5265 			r.log = $1.w;
5266 			r.logif = $1.w2;
5267 			r.af = $3;
5268 
5269 			if (!r.af) {
5270 				if ($5.src.host && $5.src.host->af &&
5271 				    !$5.src.host->ifindex)
5272 					r.af = $5.src.host->af;
5273 				else if ($5.dst.host && $5.dst.host->af &&
5274 				    !$5.dst.host->ifindex)
5275 					r.af = $5.dst.host->af;
5276 			}
5277 
5278 			if ($6 != NULL)
5279 				if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) >=
5280 				    PF_TAG_NAME_SIZE) {
5281 					yyerror("tag too long, max %u chars",
5282 					    PF_TAG_NAME_SIZE - 1);
5283 					YYERROR;
5284 				}
5285 
5286 			if ($7.name)
5287 				if (strlcpy(r.match_tagname, $7.name,
5288 				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
5289 					yyerror("tag too long, max %u chars",
5290 					    PF_TAG_NAME_SIZE - 1);
5291 					YYERROR;
5292 				}
5293 			r.match_tag_not = $7.neg;
5294 			r.rtableid = $8;
5295 
5296 			if (r.action == PF_NONAT || r.action == PF_NORDR) {
5297 				if ($9 != NULL) {
5298 					yyerror("translation rule with 'no' "
5299 					    "does not need '->'");
5300 					YYERROR;
5301 				}
5302 			} else {
5303 				if ($9 == NULL || $9->host == NULL) {
5304 					yyerror("translation rule requires '-> "
5305 					    "address'");
5306 					YYERROR;
5307 				}
5308 				if ($9->pool_opts.opts & PF_POOL_IPV6NH) {
5309 					yyerror("The prefer-ipv6-nexthop option "
5310 					    "can't be used for nat/rdr/binat pools"
5311 					);
5312 					YYERROR;
5313 				}
5314 				if (!r.af && ! $9->host->ifindex)
5315 					r.af = $9->host->af;
5316 
5317 				remove_invalid_hosts(&$9->host, &r.af);
5318 				if (invalid_redirect($9->host, r.af))
5319 					YYERROR;
5320 				if ($9->host->addr.type == PF_ADDR_DYNIFTL) {
5321 					if (($9->host = gen_dynnode($9->host, r.af)) == NULL)
5322 						err(1, "calloc");
5323 				}
5324 				if (check_netmask($9->host, r.af))
5325 					YYERROR;
5326 			}
5327 
5328 			o = keep_state_defaults;
5329 			while (o) {
5330 				switch (o->type) {
5331 				case PF_STATE_OPT_PFLOW:
5332 					if (r.rule_flag & PFRULE_PFLOW) {
5333 						yyerror("state pflow option: "
5334 						    "multiple definitions");
5335 						YYERROR;
5336 					}
5337 					r.rule_flag |= PFRULE_PFLOW;
5338 					break;
5339 				}
5340 				o = o->next;
5341 			}
5342 
5343 			expand_rule(&r, false, $2, NULL, $9, NULL, $4,
5344 			    $5.src_os, $5.src.host, $5.src.port, $5.dst.host,
5345 			    $5.dst.port, 0, 0, 0, 0);
5346 		}
5347 		;
5348 
5349 binatrule	: no BINAT natpasslog interface af proto FROM ipspec toipspec tag
5350 		    tagged rtable binat_redirspec
5351 		{
5352 			struct pfctl_rule	binat;
5353 			struct pfctl_pooladdr	*pa;
5354 
5355 			if (check_rulestate(PFCTL_STATE_NAT))
5356 				YYERROR;
5357 			if (disallow_urpf_failed($9, "\"urpf-failed\" is not "
5358 			    "permitted as a binat destination"))
5359 				YYERROR;
5360 
5361 			pfctl_init_rule(&binat);
5362 
5363 			if ($1 && $3.b1) {
5364 				yyerror("\"pass\" not valid with \"no\"");
5365 				YYERROR;
5366 			}
5367 			if ($1)
5368 				binat.action = PF_NOBINAT;
5369 			else
5370 				binat.action = PF_BINAT;
5371 			binat.natpass = $3.b1;
5372 			binat.log = $3.b2;
5373 			binat.logif = $3.w2;
5374 			binat.af = $5;
5375 			if (!binat.af && $8 != NULL && $8->af)
5376 				binat.af = $8->af;
5377 			if (!binat.af && $9 != NULL && $9->af)
5378 				binat.af = $9->af;
5379 
5380 			if (!binat.af && $13 != NULL && $13->host)
5381 				binat.af = $13->host->af;
5382 			if (!binat.af) {
5383 				yyerror("address family (inet/inet6) "
5384 				    "undefined");
5385 				YYERROR;
5386 			}
5387 
5388 			if ($4 != NULL) {
5389 				memcpy(binat.ifname, $4->ifname,
5390 				    sizeof(binat.ifname));
5391 				binat.ifnot = $4->not;
5392 				free($4);
5393 			}
5394 
5395 			if ($10 != NULL)
5396 				if (strlcpy(binat.tagname, $10,
5397 				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
5398 					yyerror("tag too long, max %u chars",
5399 					    PF_TAG_NAME_SIZE - 1);
5400 					YYERROR;
5401 				}
5402 			if ($11.name)
5403 				if (strlcpy(binat.match_tagname, $11.name,
5404 				    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
5405 					yyerror("tag too long, max %u chars",
5406 					    PF_TAG_NAME_SIZE - 1);
5407 					YYERROR;
5408 				}
5409 			binat.match_tag_not = $11.neg;
5410 			binat.rtableid = $12;
5411 
5412 			if ($6 != NULL) {
5413 				binat.proto = $6->proto;
5414 				free($6);
5415 			}
5416 
5417 			if ($8 != NULL && disallow_table($8, "invalid use of "
5418 			    "table <%s> as the source address of a binat rule"))
5419 				YYERROR;
5420 			if ($8 != NULL && disallow_alias($8, "invalid use of "
5421 			    "interface (%s) as the source address of a binat "
5422 			    "rule"))
5423 				YYERROR;
5424 			if ($13 != NULL && $13->host != NULL && disallow_table(
5425 			    $13->host, "invalid use of table <%s> as the "
5426 			    "redirect address of a binat rule"))
5427 				YYERROR;
5428 			if ($13 != NULL && $13->host != NULL && disallow_alias(
5429 			    $13->host, "invalid use of interface (%s) as the "
5430 			    "redirect address of a binat rule"))
5431 				YYERROR;
5432 
5433 			if ($8 != NULL) {
5434 				if ($8->next) {
5435 					yyerror("multiple binat ip addresses");
5436 					YYERROR;
5437 				}
5438 				if ($8->addr.type == PF_ADDR_DYNIFTL)
5439 					$8->af = binat.af;
5440 				if ($8->af != binat.af) {
5441 					yyerror("binat ip versions must match");
5442 					YYERROR;
5443 				}
5444 				if ($8->addr.type == PF_ADDR_DYNIFTL) {
5445 					if (($8 = gen_dynnode($8, binat.af)) == NULL)
5446 						err(1, "calloc");
5447 				}
5448 				if (check_netmask($8, binat.af))
5449 					YYERROR;
5450 				memcpy(&binat.src.addr, &$8->addr,
5451 				    sizeof(binat.src.addr));
5452 				free($8);
5453 			}
5454 			if ($9 != NULL) {
5455 				if ($9->next) {
5456 					yyerror("multiple binat ip addresses");
5457 					YYERROR;
5458 				}
5459 				if ($9->af != binat.af && $9->af) {
5460 					yyerror("binat ip versions must match");
5461 					YYERROR;
5462 				}
5463 				if ($9->addr.type == PF_ADDR_DYNIFTL) {
5464 					if (($9 = gen_dynnode($9, binat.af)) == NULL)
5465 						err(1, "calloc");
5466 				}
5467 				if (check_netmask($9, binat.af))
5468 					YYERROR;
5469 				memcpy(&binat.dst.addr, &$9->addr,
5470 				    sizeof(binat.dst.addr));
5471 				binat.dst.neg = $9->not;
5472 				free($9);
5473 			}
5474 
5475 			if (binat.action == PF_NOBINAT) {
5476 				if ($13 != NULL) {
5477 					yyerror("'no binat' rule does not need"
5478 					    " '->'");
5479 					YYERROR;
5480 				}
5481 			} else {
5482 				if ($13 == NULL || $13->host == NULL) {
5483 					yyerror("'binat' rule requires"
5484 					    " '-> address'");
5485 					YYERROR;
5486 				}
5487 
5488 				remove_invalid_hosts(&$13->host, &binat.af);
5489 				if (invalid_redirect($13->host, binat.af))
5490 					YYERROR;
5491 				if ($13->host->next != NULL) {
5492 					yyerror("binat rule must redirect to "
5493 					    "a single address");
5494 					YYERROR;
5495 				}
5496 				if ($13->host->addr.type == PF_ADDR_DYNIFTL) {
5497 					if (($13->host = gen_dynnode($13->host, binat.af)) == NULL)
5498 						err(1, "calloc");
5499 				}
5500 				if (check_netmask($13->host, binat.af))
5501 					YYERROR;
5502 
5503 				if (!PF_AZERO(&binat.src.addr.v.a.mask,
5504 				    binat.af) &&
5505 				    !PF_AEQ(&binat.src.addr.v.a.mask,
5506 				    &$13->host->addr.v.a.mask, binat.af)) {
5507 					yyerror("'binat' source mask and "
5508 					    "redirect mask must be the same");
5509 					YYERROR;
5510 				}
5511 
5512 				pa = calloc(1, sizeof(struct pfctl_pooladdr));
5513 				if (pa == NULL)
5514 					err(1, "binat: calloc");
5515 				pa->addr = $13->host->addr;
5516 				pa->ifname[0] = 0;
5517 				pa->af = $13->host->af;
5518 				TAILQ_INSERT_TAIL(&binat.rdr.list,
5519 				    pa, entries);
5520 
5521 				free($13);
5522 			}
5523 
5524 			pfctl_append_rule(pf, &binat);
5525 		}
5526 		;
5527 
5528 tag		: /* empty */		{ $$ = NULL; }
5529 		| TAG STRING		{ $$ = $2; }
5530 		;
5531 
5532 tagged		: /* empty */		{ $$.neg = 0; $$.name = NULL; }
5533 		| not TAGGED string	{ $$.neg = $1; $$.name = $3; }
5534 		;
5535 
5536 rtable		: /* empty */		{ $$ = -1; }
5537 		| RTABLE NUMBER		{
5538 			if ($2 < 0 || $2 > rt_tableid_max()) {
5539 				yyerror("invalid rtable id");
5540 				YYERROR;
5541 			}
5542 			$$ = $2;
5543 		}
5544 		;
5545 
5546 route_host	: STRING			{
5547 			$$ = calloc(1, sizeof(struct node_host));
5548 			if ($$ == NULL)
5549 				err(1, "route_host: calloc");
5550 			if (strlen($1) >= IFNAMSIZ) {
5551 				yyerror("interface name too long");
5552 				YYERROR;
5553 			}
5554 			$$->ifname = strdup($1);
5555 			set_ipmask($$, 128);
5556 			$$->next = NULL;
5557 			$$->tail = $$;
5558 		}
5559 		| '(' STRING host ')'		{
5560 			struct node_host *n;
5561 
5562 			$$ = $3;
5563 			for (n = $3; n != NULL; n = n->next) {
5564 				if (strlen($2) >= IFNAMSIZ) {
5565 					yyerror("interface name too long");
5566 					YYERROR;
5567 				}
5568 				n->ifname = strdup($2);
5569 			}
5570 		}
5571 		;
5572 
5573 route_host_list	: route_host optnl			{ $$ = $1; }
5574 		| route_host_list comma route_host optnl {
5575 			$1->tail->next = $3;
5576 			$1->tail = $3->tail;
5577 			$$ = $1;
5578 		}
5579 		;
5580 
5581 routespec	: route_host			{ $$ = $1; }
5582 		| '{' optnl route_host_list '}'	{ $$ = $3; }
5583 		;
5584 
5585 route		: /* empty */			{
5586 			$$.rt = PF_NOPFROUTE;
5587 		}
5588 		| FASTROUTE {
5589 			/* backwards-compat */
5590 			$$.rt = PF_NOPFROUTE;
5591 		}
5592 		| ROUTETO route_redirspec {
5593 			$$.rt = PF_ROUTETO;
5594 			$$.redirspec = $2;
5595 		}
5596 		| REPLYTO route_redirspec {
5597 			$$.rt = PF_REPLYTO;
5598 			$$.redirspec = $2;
5599 		}
5600 		| DUPTO route_redirspec {
5601 			$$.rt = PF_DUPTO;
5602 			$$.redirspec = $2;
5603 		}
5604 		;
5605 
5606 timeout_spec	: STRING NUMBER
5607 		{
5608 			if (check_rulestate(PFCTL_STATE_OPTION)) {
5609 				free($1);
5610 				YYERROR;
5611 			}
5612 			if ($2 < 0 || $2 > UINT_MAX) {
5613 				yyerror("only positive values permitted");
5614 				YYERROR;
5615 			}
5616 			if (pfctl_apply_timeout(pf, $1, $2, 0) != 0) {
5617 				yyerror("unknown timeout %s", $1);
5618 				free($1);
5619 				YYERROR;
5620 			}
5621 			free($1);
5622 		}
5623 		| INTERVAL NUMBER		{
5624 			if (check_rulestate(PFCTL_STATE_OPTION))
5625 				YYERROR;
5626 			if ($2 < 0 || $2 > UINT_MAX) {
5627 				yyerror("only positive values permitted");
5628 				YYERROR;
5629 			}
5630 			if (pfctl_apply_timeout(pf, "interval", $2, 0) != 0)
5631 				YYERROR;
5632 		}
5633 		;
5634 
5635 timeout_list	: timeout_list comma timeout_spec optnl
5636 		| timeout_spec optnl
5637 		;
5638 
5639 limit_spec	: STRING NUMBER
5640 		{
5641 			if (check_rulestate(PFCTL_STATE_OPTION)) {
5642 				free($1);
5643 				YYERROR;
5644 			}
5645 			if ($2 < 0 || $2 > UINT_MAX) {
5646 				yyerror("only positive values permitted");
5647 				YYERROR;
5648 			}
5649 			if (pfctl_apply_limit(pf, $1, $2) != 0) {
5650 				yyerror("unable to set limit %s %u", $1, $2);
5651 				free($1);
5652 				YYERROR;
5653 			}
5654 			free($1);
5655 		}
5656 		;
5657 
5658 limit_list	: limit_list comma limit_spec optnl
5659 		| limit_spec optnl
5660 		;
5661 
5662 comma		: ','
5663 		| /* empty */
5664 		;
5665 
5666 yesno		: NO			{ $$ = 0; }
5667 		| STRING		{
5668 			if (!strcmp($1, "yes"))
5669 				$$ = 1;
5670 			else {
5671 				yyerror("invalid value '%s', expected 'yes' "
5672 				    "or 'no'", $1);
5673 				free($1);
5674 				YYERROR;
5675 			}
5676 			free($1);
5677 		}
5678 		;
5679 
5680 unaryop		: '='		{ $$ = PF_OP_EQ; }
5681 		| NE			{ $$ = PF_OP_NE; }
5682 		| LE			{ $$ = PF_OP_LE; }
5683 		| '<'		{ $$ = PF_OP_LT; }
5684 		| GE		{ $$ = PF_OP_GE; }
5685 		| '>'		{ $$ = PF_OP_GT; }
5686 		;
5687 
5688 %%
5689 
5690 int
5691 yyerror(const char *fmt, ...)
5692 {
5693 	va_list		 ap;
5694 
5695 	file->errors++;
5696 	va_start(ap, fmt);
5697 	fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
5698 	vfprintf(stderr, fmt, ap);
5699 	fprintf(stderr, "\n");
5700 	va_end(ap);
5701 	return (0);
5702 }
5703 
5704 int
validate_range(uint8_t op,uint16_t p1,uint16_t p2)5705 validate_range(uint8_t op, uint16_t p1, uint16_t p2)
5706 {
5707 	uint16_t a = ntohs(p1);
5708 	uint16_t b = ntohs(p2);
5709 
5710 	if ((op == PF_OP_RRG && a > b) ||  /* 34:12,  i.e. none */
5711 	    (op == PF_OP_IRG && a >= b) || /* 34><12, i.e. none */
5712 	    (op == PF_OP_XRG && a > b))    /* 34<>22, i.e. all */
5713 		return 1;
5714 	return 0;
5715 }
5716 
5717 int
disallow_table(struct node_host * h,const char * fmt)5718 disallow_table(struct node_host *h, const char *fmt)
5719 {
5720 	for (; h != NULL; h = h->next)
5721 		if (h->addr.type == PF_ADDR_TABLE) {
5722 			yyerror(fmt, h->addr.v.tblname);
5723 			return (1);
5724 		}
5725 	return (0);
5726 }
5727 
5728 int
disallow_urpf_failed(struct node_host * h,const char * fmt)5729 disallow_urpf_failed(struct node_host *h, const char *fmt)
5730 {
5731 	for (; h != NULL; h = h->next)
5732 		if (h->addr.type == PF_ADDR_URPFFAILED) {
5733 			yyerror(fmt);
5734 			return (1);
5735 		}
5736 	return (0);
5737 }
5738 
5739 int
disallow_alias(struct node_host * h,const char * fmt)5740 disallow_alias(struct node_host *h, const char *fmt)
5741 {
5742 	for (; h != NULL; h = h->next)
5743 		if (DYNIF_MULTIADDR(h->addr)) {
5744 			yyerror(fmt, h->addr.v.tblname);
5745 			return (1);
5746 		}
5747 	return (0);
5748 }
5749 
5750 int
rule_consistent(struct pfctl_rule * r)5751 rule_consistent(struct pfctl_rule *r)
5752 {
5753 	int	problems = 0;
5754 
5755 	switch (r->action) {
5756 	case PF_PASS:
5757 	case PF_MATCH:
5758 	case PF_DROP:
5759 	case PF_SCRUB:
5760 	case PF_NOSCRUB:
5761 		problems = filter_consistent(r);
5762 		break;
5763 	case PF_NAT:
5764 	case PF_NONAT:
5765 		problems = nat_consistent(r);
5766 		break;
5767 	case PF_RDR:
5768 	case PF_NORDR:
5769 		problems = rdr_consistent(r);
5770 		break;
5771 	case PF_BINAT:
5772 	case PF_NOBINAT:
5773 	default:
5774 		break;
5775 	}
5776 	return (problems);
5777 }
5778 
5779 int
filter_consistent(struct pfctl_rule * r)5780 filter_consistent(struct pfctl_rule *r)
5781 {
5782 	int	problems = 0;
5783 
5784 	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
5785 	    r->proto != IPPROTO_SCTP &&
5786 	    (r->src.port_op || r->dst.port_op)) {
5787 		yyerror("port only applies to tcp/udp/sctp");
5788 		problems++;
5789 	}
5790 	if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
5791 	    (r->type || r->code)) {
5792 		yyerror("icmp-type/code only applies to icmp");
5793 		problems++;
5794 	}
5795 	if (!r->af && (r->type || r->code)) {
5796 		yyerror("must indicate address family with icmp-type/code");
5797 		problems++;
5798 	}
5799 	if (r->rule_flag & PFRULE_AFTO && r->af == r->naf) {
5800 		yyerror("must indicate different address family with af-to");
5801 		problems++;
5802 	}
5803 	if (r->overload_tblname[0] &&
5804 	    r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) {
5805 		yyerror("'overload' requires 'max-src-conn' "
5806 		    "or 'max-src-conn-rate'");
5807 		problems++;
5808 	}
5809 	if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
5810 	    (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
5811 		yyerror("proto %s doesn't match address family %s",
5812 		    r->proto == IPPROTO_ICMP ? "icmp" : "icmp6",
5813 		    r->af == AF_INET ? "inet" : "inet6");
5814 		problems++;
5815 	}
5816 	if (r->allow_opts && r->action != PF_PASS && r->action != PF_MATCH) {
5817 		yyerror("allow-opts can only be specified for pass or "
5818 		    "match rules");
5819 		problems++;
5820 	}
5821 	if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
5822 	    r->dst.port_op || r->flagset || r->type || r->code)) {
5823 		yyerror("fragments can be filtered only on IP header fields");
5824 		problems++;
5825 	}
5826 	if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) {
5827 		yyerror("return-rst can only be applied to TCP rules");
5828 		problems++;
5829 	}
5830 	if (r->max_src_nodes && !(r->rule_flag & PFRULE_RULESRCTRACK)) {
5831 		yyerror("max-src-nodes requires 'source-track rule'");
5832 		problems++;
5833 	}
5834 	if (r->action != PF_PASS && r->keep_state) {
5835 		yyerror("keep state is great, but only for pass rules");
5836 		problems++;
5837 	}
5838 	if (r->rule_flag & PFRULE_STATESLOPPY &&
5839 	    (r->keep_state == PF_STATE_MODULATE ||
5840 	    r->keep_state == PF_STATE_SYNPROXY)) {
5841 		yyerror("sloppy state matching cannot be used with "
5842 		    "synproxy state or modulate state");
5843 		problems++;
5844 	}
5845 	if ((r->keep_state == PF_STATE_SYNPROXY) && (r->direction != PF_IN))
5846 		fprintf(stderr, "%s:%d: warning: "
5847 		    "synproxy used for inbound rules only, "
5848 		    "ignored for outbound\n", file->name, yylval.lineno);
5849 	if (r->rule_flag & PFRULE_AFTO && r->rt) {
5850 		if (r->rt != PF_ROUTETO && r->rt != PF_REPLYTO) {
5851 			yyerror("dup-to "
5852 			   "must not be used on af-to rules");
5853 			problems++;
5854 		}
5855 	}
5856 	/* Basic rule sanity check. */
5857 	switch (r->action) {
5858 	case PF_MATCH:
5859 		if (r->divert.port) {
5860 			yyerror("divert is not supported on match rules");
5861 			problems++;
5862 		}
5863 		if (r->rt) {
5864 			yyerror("route-to, reply-to, dup-to and fastroute "
5865 			   "must not be used on match rules");
5866 			problems++;
5867 		}
5868 		if (r->rule_flag & PFRULE_AFTO) {
5869 			yyerror("af-to is not supported on match rules");
5870 			problems++;
5871 		}
5872 		break;
5873 	case PF_DROP:
5874 		if (r->rt) {
5875 			yyerror("route-to, reply-to and dup-to "
5876 			    "are not supported on block rules");
5877 			problems++;
5878 		}
5879 		break;
5880 	default:;
5881 	}
5882 	if (!TAILQ_EMPTY(&(r->nat.list)) || !TAILQ_EMPTY(&(r->rdr.list))) {
5883 		if (r->action != PF_MATCH && !r->keep_state) {
5884 			yyerror("nat-to and rdr-to require keep state");
5885 			problems++;
5886 		}
5887 		if (r->direction == PF_INOUT) {
5888 			yyerror("nat-to and rdr-to require a direction");
5889 			problems++;
5890 		}
5891 	}
5892 	if (r->route.opts & PF_POOL_STICKYADDR && !r->keep_state) {
5893 		yyerror("'sticky-address' requires 'keep state'");
5894 	}
5895 	return (-problems);
5896 }
5897 
5898 int
nat_consistent(struct pfctl_rule * r)5899 nat_consistent(struct pfctl_rule *r)
5900 {
5901 	return (0);	/* yeah! */
5902 }
5903 
5904 int
rdr_consistent(struct pfctl_rule * r)5905 rdr_consistent(struct pfctl_rule *r)
5906 {
5907 	int			 problems = 0;
5908 
5909 	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
5910 	    r->proto != IPPROTO_SCTP) {
5911 		if (r->src.port_op) {
5912 			yyerror("src port only applies to tcp/udp/sctp");
5913 			problems++;
5914 		}
5915 		if (r->dst.port_op) {
5916 			yyerror("dst port only applies to tcp/udp/sctp");
5917 			problems++;
5918 		}
5919 		if (r->rdr.proxy_port[0]) {
5920 			yyerror("rdr port only applies to tcp/udp/sctp");
5921 			problems++;
5922 		}
5923 	}
5924 	if (r->dst.port_op &&
5925 	    r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) {
5926 		yyerror("invalid port operator for rdr destination port");
5927 		problems++;
5928 	}
5929 	return (-problems);
5930 }
5931 
5932 int
process_tabledef(char * name,struct table_opts * opts,int popts)5933 process_tabledef(char *name, struct table_opts *opts, int popts)
5934 {
5935 	struct pfr_buffer	 ab;
5936 	struct node_tinit	*ti;
5937 	struct pfr_uktable	*ukt;
5938 	unsigned long		 maxcount;
5939 	size_t			 s = sizeof(maxcount);
5940 
5941 	bzero(&ab, sizeof(ab));
5942 	ab.pfrb_type = PFRB_ADDRS;
5943 	SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) {
5944 		if (ti->file)
5945 			if (pfr_buf_load(&ab, ti->file, 0, append_addr, popts)) {
5946 				if (errno)
5947 					yyerror("cannot load \"%s\": %s",
5948 					    ti->file, strerror(errno));
5949 				else
5950 					yyerror("file \"%s\" contains bad data",
5951 					    ti->file);
5952 				goto _error;
5953 			}
5954 		if (ti->host)
5955 			if (append_addr_host(&ab, ti->host, 0, 0)) {
5956 				yyerror("cannot create address buffer: %s",
5957 				    strerror(errno));
5958 				goto _error;
5959 			}
5960 	}
5961 	if (pf->opts & PF_OPT_VERBOSE)
5962 		print_tabledef(name, opts->flags, opts->init_addr,
5963 		    &opts->init_nodes);
5964 	if (!(pf->opts & PF_OPT_NOACTION) ||
5965 	    (pf->opts & PF_OPT_DUMMYACTION))
5966 		warn_duplicate_tables(name, pf->anchor->path);
5967 	else if (pf->opts & PF_OPT_VERBOSE)
5968 		fprintf(stderr, "%s:%d: skipping duplicate table checks"
5969 		    " for <%s>\n", file->name, yylval.lineno, name);
5970 	/*
5971 	 * postpone definition of non-root tables to moment
5972 	 * when path is fully resolved.
5973 	 */
5974 	if (pf->asd > 0) {
5975 		ukt = calloc(1, sizeof(struct pfr_uktable));
5976 		if (ukt == NULL) {
5977 			DBGPRINT(
5978 			    "%s:%d: not enough memory for <%s>\n", file->name,
5979 			    yylval.lineno, name);
5980 			goto _error;
5981 		}
5982 	} else
5983 		ukt = NULL;
5984 	if (!(pf->opts & PF_OPT_NOACTION) &&
5985 	    pfctl_define_table(name, opts->flags, opts->init_addr,
5986 	    pf->anchor->path, &ab, pf->anchor->ruleset.tticket, ukt)) {
5987 
5988 		if (sysctlbyname("net.pf.request_maxcount", &maxcount, &s,
5989 		    NULL, 0) == -1)
5990 			maxcount = 65535;
5991 
5992 		if (ab.pfrb_size > maxcount)
5993 			yyerror("cannot define table %s: too many elements.\n"
5994 			    "Consider increasing net.pf.request_maxcount.",
5995 			    name);
5996 		else
5997 			yyerror("cannot define table %s: %s", name,
5998 			    pf_strerror(errno));
5999 
6000 		goto _error;
6001 	}
6002 
6003 	if (ukt != NULL) {
6004 		ukt->pfrukt_init_addr = opts->init_addr;
6005 		if (RB_INSERT(pfr_ktablehead, &pfr_ktables,
6006 		    &ukt->pfrukt_kt) != NULL) {
6007 			/*
6008 			 * I think this should not happen, because
6009 			 * pfctl_define_table() above  does the same check
6010 			 * effectively.
6011 			 */
6012 			DBGPRINT(
6013 			    "%s:%d table %s already exists in %s\n",
6014 			    file->name, yylval.lineno,
6015 			    ukt->pfrukt_name, pf->anchor->path);
6016 			free(ukt);
6017 			goto _error;
6018 		}
6019 		DBGPRINT("%s %s@%s inserted to tree\n",
6020 		    __func__, ukt->pfrukt_name, pf->anchor->path);
6021 	} else
6022 		DBGPRINT("%s ukt is null\n", __func__);
6023 
6024 	pf->tdirty = 1;
6025 	pfr_buf_clear(&ab);
6026 	return (0);
6027 _error:
6028 	pfr_buf_clear(&ab);
6029 	return (-1);
6030 }
6031 
6032 struct keywords {
6033 	const char	*k_name;
6034 	int		 k_val;
6035 };
6036 
6037 /* macro gore, but you should've seen the prior indentation nightmare... */
6038 
6039 #define FREE_LIST(T,r) \
6040 	do { \
6041 		T *p, *node = r; \
6042 		while (node != NULL) { \
6043 			p = node; \
6044 			node = node->next; \
6045 			free(p); \
6046 		} \
6047 	} while (0)
6048 
6049 #define LOOP_THROUGH(T,n,r,C) \
6050 	do { \
6051 		T *n; \
6052 		if (r == NULL) { \
6053 			r = calloc(1, sizeof(T)); \
6054 			if (r == NULL) \
6055 				err(1, "LOOP: calloc"); \
6056 			r->next = NULL; \
6057 		} \
6058 		n = r; \
6059 		while (n != NULL) { \
6060 			do { \
6061 				C; \
6062 			} while (0); \
6063 			n = n->next; \
6064 		} \
6065 	} while (0)
6066 
6067 void
expand_label_str(char * label,size_t len,const char * srch,const char * repl)6068 expand_label_str(char *label, size_t len, const char *srch, const char *repl)
6069 {
6070 	char *tmp;
6071 	char *p, *q;
6072 
6073 	if ((tmp = calloc(1, len)) == NULL)
6074 		err(1, "%s: calloc", __func__);
6075 	p = q = label;
6076 	while ((q = strstr(p, srch)) != NULL) {
6077 		*q = '\0';
6078 		if ((strlcat(tmp, p, len) >= len) ||
6079 		    (strlcat(tmp, repl, len) >= len))
6080 			errx(1, "%s: label too long", __func__);
6081 		q += strlen(srch);
6082 		p = q;
6083 	}
6084 	if (strlcat(tmp, p, len) >= len)
6085 		errx(1, "%s: label too long", __func__);
6086 	strlcpy(label, tmp, len);	/* always fits */
6087 	free(tmp);
6088 }
6089 
6090 void
expand_label_if(const char * name,char * label,size_t len,const char * ifname)6091 expand_label_if(const char *name, char *label, size_t len, const char *ifname)
6092 {
6093 	if (strstr(label, name) != NULL) {
6094 		if (!*ifname)
6095 			expand_label_str(label, len, name, "any");
6096 		else
6097 			expand_label_str(label, len, name, ifname);
6098 	}
6099 }
6100 
6101 void
expand_label_addr(const char * name,char * label,size_t len,sa_family_t af,struct pf_rule_addr * addr)6102 expand_label_addr(const char *name, char *label, size_t len, sa_family_t af,
6103     struct pf_rule_addr *addr)
6104 {
6105 	char tmp[64], tmp_not[66];
6106 
6107 	if (strstr(label, name) != NULL) {
6108 		switch (addr->addr.type) {
6109 		case PF_ADDR_DYNIFTL:
6110 			snprintf(tmp, sizeof(tmp), "(%s)", addr->addr.v.ifname);
6111 			break;
6112 		case PF_ADDR_TABLE:
6113 			snprintf(tmp, sizeof(tmp), "<%s>", addr->addr.v.tblname);
6114 			break;
6115 		case PF_ADDR_NOROUTE:
6116 			snprintf(tmp, sizeof(tmp), "no-route");
6117 			break;
6118 		case PF_ADDR_URPFFAILED:
6119 			snprintf(tmp, sizeof(tmp), "urpf-failed");
6120 			break;
6121 		case PF_ADDR_ADDRMASK:
6122 			if (!af || (PF_AZERO(&addr->addr.v.a.addr, af) &&
6123 			    PF_AZERO(&addr->addr.v.a.mask, af)))
6124 				snprintf(tmp, sizeof(tmp), "any");
6125 			else {
6126 				char	a[48];
6127 				int	bits;
6128 
6129 				if (inet_ntop(af, &addr->addr.v.a.addr, a,
6130 				    sizeof(a)) == NULL)
6131 					snprintf(tmp, sizeof(tmp), "?");
6132 				else {
6133 					bits = unmask(&addr->addr.v.a.mask);
6134 					if ((af == AF_INET && bits < 32) ||
6135 					    (af == AF_INET6 && bits < 128))
6136 						snprintf(tmp, sizeof(tmp),
6137 						    "%s/%d", a, bits);
6138 					else
6139 						snprintf(tmp, sizeof(tmp),
6140 						    "%s", a);
6141 				}
6142 			}
6143 			break;
6144 		default:
6145 			snprintf(tmp, sizeof(tmp), "?");
6146 			break;
6147 		}
6148 
6149 		if (addr->neg) {
6150 			snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp);
6151 			expand_label_str(label, len, name, tmp_not);
6152 		} else
6153 			expand_label_str(label, len, name, tmp);
6154 	}
6155 }
6156 
6157 void
expand_label_port(const char * name,char * label,size_t len,struct pf_rule_addr * addr)6158 expand_label_port(const char *name, char *label, size_t len,
6159     struct pf_rule_addr *addr)
6160 {
6161 	char	 a1[6], a2[6], op[13] = "";
6162 
6163 	if (strstr(label, name) != NULL) {
6164 		snprintf(a1, sizeof(a1), "%u", ntohs(addr->port[0]));
6165 		snprintf(a2, sizeof(a2), "%u", ntohs(addr->port[1]));
6166 		if (!addr->port_op)
6167 			;
6168 		else if (addr->port_op == PF_OP_IRG)
6169 			snprintf(op, sizeof(op), "%s><%s", a1, a2);
6170 		else if (addr->port_op == PF_OP_XRG)
6171 			snprintf(op, sizeof(op), "%s<>%s", a1, a2);
6172 		else if (addr->port_op == PF_OP_EQ)
6173 			snprintf(op, sizeof(op), "%s", a1);
6174 		else if (addr->port_op == PF_OP_NE)
6175 			snprintf(op, sizeof(op), "!=%s", a1);
6176 		else if (addr->port_op == PF_OP_LT)
6177 			snprintf(op, sizeof(op), "<%s", a1);
6178 		else if (addr->port_op == PF_OP_LE)
6179 			snprintf(op, sizeof(op), "<=%s", a1);
6180 		else if (addr->port_op == PF_OP_GT)
6181 			snprintf(op, sizeof(op), ">%s", a1);
6182 		else if (addr->port_op == PF_OP_GE)
6183 			snprintf(op, sizeof(op), ">=%s", a1);
6184 		expand_label_str(label, len, name, op);
6185 	}
6186 }
6187 
6188 void
expand_label_proto(const char * name,char * label,size_t len,u_int8_t proto)6189 expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto)
6190 {
6191 	const char *protoname;
6192 	char n[4];
6193 
6194 	if (strstr(label, name) != NULL) {
6195 		protoname = pfctl_proto2name(proto);
6196 		if (protoname != NULL)
6197 			expand_label_str(label, len, name, protoname);
6198 		else {
6199 			snprintf(n, sizeof(n), "%u", proto);
6200 			expand_label_str(label, len, name, n);
6201 		}
6202 	}
6203 }
6204 
6205 void
expand_label_nr(const char * name,char * label,size_t len,struct pfctl_rule * r)6206 expand_label_nr(const char *name, char *label, size_t len,
6207     struct pfctl_rule *r)
6208 {
6209 	char n[11];
6210 
6211 	if (strstr(label, name) != NULL) {
6212 		snprintf(n, sizeof(n), "%u", r->nr);
6213 		expand_label_str(label, len, name, n);
6214 	}
6215 }
6216 
6217 void
expand_label(char * label,size_t len,struct pfctl_rule * r)6218 expand_label(char *label, size_t len, struct pfctl_rule *r)
6219 {
6220 	expand_label_if("$if", label, len, r->ifname);
6221 	expand_label_addr("$srcaddr", label, len, r->af, &r->src);
6222 	expand_label_addr("$dstaddr", label, len, r->af, &r->dst);
6223 	expand_label_port("$srcport", label, len, &r->src);
6224 	expand_label_port("$dstport", label, len, &r->dst);
6225 	expand_label_proto("$proto", label, len, r->proto);
6226 	expand_label_nr("$nr", label, len, r);
6227 }
6228 
6229 int
expand_altq(struct pf_altq * a,struct node_if * interfaces,struct node_queue * nqueues,struct node_queue_bw bwspec,struct node_queue_opt * opts)6230 expand_altq(struct pf_altq *a, struct node_if *interfaces,
6231     struct node_queue *nqueues, struct node_queue_bw bwspec,
6232     struct node_queue_opt *opts)
6233 {
6234 	struct pf_altq		 pa, pb;
6235 	char			 qname[PF_QNAME_SIZE];
6236 	struct node_queue	*n;
6237 	struct node_queue_bw	 bw;
6238 	int			 errs = 0;
6239 
6240 	if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
6241 		FREE_LIST(struct node_if, interfaces);
6242 		if (nqueues)
6243 			FREE_LIST(struct node_queue, nqueues);
6244 		return (0);
6245 	}
6246 
6247 	LOOP_THROUGH(struct node_if, interface, interfaces,
6248 		memcpy(&pa, a, sizeof(struct pf_altq));
6249 		if (strlcpy(pa.ifname, interface->ifname,
6250 		    sizeof(pa.ifname)) >= sizeof(pa.ifname))
6251 			errx(1, "%s: strlcpy", __func__);
6252 
6253 		if (interface->not) {
6254 			yyerror("altq on ! <interface> is not supported");
6255 			errs++;
6256 		} else {
6257 			if (eval_pfaltq(pf, &pa, &bwspec, opts))
6258 				errs++;
6259 			else
6260 				if (pfctl_add_altq(pf, &pa))
6261 					errs++;
6262 
6263 			if (pf->opts & PF_OPT_VERBOSE) {
6264 				print_altq(&pf->paltq->altq, 0,
6265 				    &bwspec, opts);
6266 				if (nqueues && nqueues->tail) {
6267 					printf("queue { ");
6268 					LOOP_THROUGH(struct node_queue, queue,
6269 					    nqueues,
6270 						printf("%s ",
6271 						    queue->queue);
6272 					);
6273 					printf("}");
6274 				}
6275 				printf("\n");
6276 			}
6277 
6278 			if (pa.scheduler == ALTQT_CBQ ||
6279 			    pa.scheduler == ALTQT_HFSC ||
6280 			    pa.scheduler == ALTQT_FAIRQ) {
6281 				/* now create a root queue */
6282 				memset(&pb, 0, sizeof(struct pf_altq));
6283 				if (strlcpy(qname, "root_", sizeof(qname)) >=
6284 				    sizeof(qname))
6285 					errx(1, "%s: strlcpy", __func__);
6286 				if (strlcat(qname, interface->ifname,
6287 				    sizeof(qname)) >= sizeof(qname))
6288 					errx(1, "%s: strlcat", __func__);
6289 				if (strlcpy(pb.qname, qname,
6290 				    sizeof(pb.qname)) >= sizeof(pb.qname))
6291 					errx(1, "%s: strlcpy", __func__);
6292 				if (strlcpy(pb.ifname, interface->ifname,
6293 				    sizeof(pb.ifname)) >= sizeof(pb.ifname))
6294 					errx(1, "%s: strlcpy", __func__);
6295 				pb.qlimit = pa.qlimit;
6296 				pb.scheduler = pa.scheduler;
6297 				bw.bw_absolute = pa.ifbandwidth;
6298 				bw.bw_percent = 0;
6299 				if (eval_pfqueue(pf, &pb, &bw, opts))
6300 					errs++;
6301 				else
6302 					if (pfctl_add_altq(pf, &pb))
6303 						errs++;
6304 			}
6305 
6306 			LOOP_THROUGH(struct node_queue, queue, nqueues,
6307 				n = calloc(1, sizeof(struct node_queue));
6308 				if (n == NULL)
6309 					err(1, "%s: calloc", __func__);
6310 				if (pa.scheduler == ALTQT_CBQ ||
6311 				    pa.scheduler == ALTQT_HFSC ||
6312 				    pa.scheduler == ALTQT_FAIRQ)
6313 					if (strlcpy(n->parent, qname,
6314 					    sizeof(n->parent)) >=
6315 					    sizeof(n->parent))
6316 						errx(1, "%s: strlcpy", __func__);
6317 				if (strlcpy(n->queue, queue->queue,
6318 				    sizeof(n->queue)) >= sizeof(n->queue))
6319 					errx(1, "%s: strlcpy", __func__);
6320 				if (strlcpy(n->ifname, interface->ifname,
6321 				    sizeof(n->ifname)) >= sizeof(n->ifname))
6322 					errx(1, "%s: strlcpy", __func__);
6323 				n->scheduler = pa.scheduler;
6324 				n->next = NULL;
6325 				n->tail = n;
6326 				if (queues == NULL)
6327 					queues = n;
6328 				else {
6329 					queues->tail->next = n;
6330 					queues->tail = n;
6331 				}
6332 			);
6333 		}
6334 	);
6335 	FREE_LIST(struct node_if, interfaces);
6336 	if (nqueues)
6337 		FREE_LIST(struct node_queue, nqueues);
6338 
6339 	return (errs);
6340 }
6341 
6342 int
expand_queue(struct pf_altq * a,struct node_if * interfaces,struct node_queue * nqueues,struct node_queue_bw bwspec,struct node_queue_opt * opts)6343 expand_queue(struct pf_altq *a, struct node_if *interfaces,
6344     struct node_queue *nqueues, struct node_queue_bw bwspec,
6345     struct node_queue_opt *opts)
6346 {
6347 	struct node_queue	*n, *nq;
6348 	struct pf_altq		 pa;
6349 	u_int8_t		 found = 0;
6350 	u_int8_t		 errs = 0;
6351 
6352 	if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
6353 		FREE_LIST(struct node_queue, nqueues);
6354 		return (0);
6355 	}
6356 
6357 	if (queues == NULL) {
6358 		yyerror("queue %s has no parent", a->qname);
6359 		FREE_LIST(struct node_queue, nqueues);
6360 		return (1);
6361 	}
6362 
6363 	LOOP_THROUGH(struct node_if, interface, interfaces,
6364 		LOOP_THROUGH(struct node_queue, tqueue, queues,
6365 			if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE) &&
6366 			    (interface->ifname[0] == 0 ||
6367 			    (!interface->not && !strncmp(interface->ifname,
6368 			    tqueue->ifname, IFNAMSIZ)) ||
6369 			    (interface->not && strncmp(interface->ifname,
6370 			    tqueue->ifname, IFNAMSIZ)))) {
6371 				/* found ourself in queues */
6372 				found++;
6373 
6374 				memcpy(&pa, a, sizeof(struct pf_altq));
6375 
6376 				if (pa.scheduler != ALTQT_NONE &&
6377 				    pa.scheduler != tqueue->scheduler) {
6378 					yyerror("exactly one scheduler type "
6379 					    "per interface allowed");
6380 					return (1);
6381 				}
6382 				pa.scheduler = tqueue->scheduler;
6383 
6384 				/* scheduler dependent error checking */
6385 				switch (pa.scheduler) {
6386 				case ALTQT_PRIQ:
6387 					if (nqueues != NULL) {
6388 						yyerror("priq queues cannot "
6389 						    "have child queues");
6390 						return (1);
6391 					}
6392 					if (bwspec.bw_absolute > 0 ||
6393 					    bwspec.bw_percent < 100) {
6394 						yyerror("priq doesn't take "
6395 						    "bandwidth");
6396 						return (1);
6397 					}
6398 					break;
6399 				default:
6400 					break;
6401 				}
6402 
6403 				if (strlcpy(pa.ifname, tqueue->ifname,
6404 				    sizeof(pa.ifname)) >= sizeof(pa.ifname))
6405 					errx(1, "%s: strlcpy", __func__);
6406 				if (strlcpy(pa.parent, tqueue->parent,
6407 				    sizeof(pa.parent)) >= sizeof(pa.parent))
6408 					errx(1, "%s: strlcpy", __func__);
6409 
6410 				if (eval_pfqueue(pf, &pa, &bwspec, opts))
6411 					errs++;
6412 				else
6413 					if (pfctl_add_altq(pf, &pa))
6414 						errs++;
6415 
6416 				for (nq = nqueues; nq != NULL; nq = nq->next) {
6417 					if (!strcmp(a->qname, nq->queue)) {
6418 						yyerror("queue cannot have "
6419 						    "itself as child");
6420 						errs++;
6421 						continue;
6422 					}
6423 					n = calloc(1,
6424 					    sizeof(struct node_queue));
6425 					if (n == NULL)
6426 						err(1, "%s: calloc", __func__);
6427 					if (strlcpy(n->parent, a->qname,
6428 					    sizeof(n->parent)) >=
6429 					    sizeof(n->parent))
6430 						errx(1, "%s strlcpy", __func__);
6431 					if (strlcpy(n->queue, nq->queue,
6432 					    sizeof(n->queue)) >=
6433 					    sizeof(n->queue))
6434 						errx(1, "%s strlcpy", __func__);
6435 					if (strlcpy(n->ifname, tqueue->ifname,
6436 					    sizeof(n->ifname)) >=
6437 					    sizeof(n->ifname))
6438 						errx(1, "%s strlcpy", __func__);
6439 					n->scheduler = tqueue->scheduler;
6440 					n->next = NULL;
6441 					n->tail = n;
6442 					if (queues == NULL)
6443 						queues = n;
6444 					else {
6445 						queues->tail->next = n;
6446 						queues->tail = n;
6447 					}
6448 				}
6449 				if ((pf->opts & PF_OPT_VERBOSE) && (
6450 				    (found == 1 && interface->ifname[0] == 0) ||
6451 				    (found > 0 && interface->ifname[0] != 0))) {
6452 					print_queue(&pf->paltq->altq, 0,
6453 					    &bwspec, interface->ifname[0] != 0,
6454 					    opts);
6455 					if (nqueues && nqueues->tail) {
6456 						printf("{ ");
6457 						LOOP_THROUGH(struct node_queue,
6458 						    queue, nqueues,
6459 							printf("%s ",
6460 							    queue->queue);
6461 						);
6462 						printf("}");
6463 					}
6464 					printf("\n");
6465 				}
6466 			}
6467 		);
6468 	);
6469 
6470 	FREE_LIST(struct node_queue, nqueues);
6471 	FREE_LIST(struct node_if, interfaces);
6472 
6473 	if (!found) {
6474 		yyerror("queue %s has no parent", a->qname);
6475 		errs++;
6476 	}
6477 
6478 	if (errs)
6479 		return (1);
6480 	else
6481 		return (0);
6482 }
6483 
6484 static int
pf_af_to_proto(sa_family_t af)6485 pf_af_to_proto(sa_family_t af)
6486 {
6487 	if (af == AF_INET)
6488 		return (ETHERTYPE_IP);
6489 	if (af == AF_INET6)
6490 		return (ETHERTYPE_IPV6);
6491 
6492 	return (0);
6493 }
6494 
6495 void
expand_eth_rule(struct pfctl_eth_rule * r,struct node_if * interfaces,struct node_etherproto * protos,struct node_mac * srcs,struct node_mac * dsts,struct node_host * ipsrcs,struct node_host * ipdsts,const char * bridge_to,const char * anchor_call)6496 expand_eth_rule(struct pfctl_eth_rule *r,
6497     struct node_if *interfaces, struct node_etherproto *protos,
6498     struct node_mac *srcs, struct node_mac *dsts,
6499     struct node_host *ipsrcs, struct node_host *ipdsts,
6500     const char *bridge_to, const char *anchor_call)
6501 {
6502 	char tagname[PF_TAG_NAME_SIZE];
6503 	char match_tagname[PF_TAG_NAME_SIZE];
6504 	char qname[PF_QNAME_SIZE];
6505 
6506 	if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
6507 		errx(1, "%s: tagname", __func__);
6508 	if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
6509 	    sizeof(match_tagname))
6510 		errx(1, "%s: match_tagname", __func__);
6511 	if (strlcpy(qname, r->qname, sizeof(qname)) >= sizeof(qname))
6512 		errx(1, "%s: qname", __func__);
6513 
6514 	LOOP_THROUGH(struct node_if, interface, interfaces,
6515 	LOOP_THROUGH(struct node_etherproto, proto, protos,
6516 	LOOP_THROUGH(struct node_mac, src, srcs,
6517 	LOOP_THROUGH(struct node_mac, dst, dsts,
6518 	LOOP_THROUGH(struct node_host, ipsrc, ipsrcs,
6519 	LOOP_THROUGH(struct node_host, ipdst, ipdsts,
6520 		strlcpy(r->ifname, interface->ifname,
6521 		    sizeof(r->ifname));
6522 		r->ifnot = interface->not;
6523 		r->proto = proto->proto;
6524 		if (!r->proto && ipsrc->af)
6525 			r->proto = pf_af_to_proto(ipsrc->af);
6526 		else if (!r->proto && ipdst->af)
6527 			r->proto = pf_af_to_proto(ipdst->af);
6528 		bcopy(src->mac, r->src.addr, ETHER_ADDR_LEN);
6529 		bcopy(src->mask, r->src.mask, ETHER_ADDR_LEN);
6530 		r->src.neg = src->neg;
6531 		r->src.isset = src->isset;
6532 		r->ipsrc.addr = ipsrc->addr;
6533 		r->ipsrc.neg = ipsrc->not;
6534 		r->ipdst.addr = ipdst->addr;
6535 		r->ipdst.neg = ipdst->not;
6536 		bcopy(dst->mac, r->dst.addr, ETHER_ADDR_LEN);
6537 		bcopy(dst->mask, r->dst.mask, ETHER_ADDR_LEN);
6538 		r->dst.neg = dst->neg;
6539 		r->dst.isset = dst->isset;
6540 		r->nr = pf->eastack[pf->asd]->match++;
6541 
6542 		if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
6543 		    sizeof(r->tagname))
6544 			errx(1, "%s: r->tagname", __func__);
6545 		if (strlcpy(r->match_tagname, match_tagname,
6546 		    sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
6547 			errx(1, "%s: r->match_tagname", __func__);
6548 		if (strlcpy(r->qname, qname, sizeof(r->qname)) >= sizeof(r->qname))
6549 			errx(1, "%s: r->qname", __func__);
6550 
6551 		if (bridge_to)
6552 			strlcpy(r->bridge_to, bridge_to, sizeof(r->bridge_to));
6553 
6554 		pfctl_append_eth_rule(pf, r, anchor_call);
6555 	))))));
6556 
6557 	FREE_LIST(struct node_if, interfaces);
6558 	FREE_LIST(struct node_etherproto, protos);
6559 	FREE_LIST(struct node_mac, srcs);
6560 	FREE_LIST(struct node_mac, dsts);
6561 	FREE_LIST(struct node_host, ipsrcs);
6562 	FREE_LIST(struct node_host, ipdsts);
6563 }
6564 
6565 int
apply_rdr_ports(struct pfctl_rule * r,struct pfctl_pool * rpool,struct redirspec * rs)6566 apply_rdr_ports(struct pfctl_rule *r, struct pfctl_pool *rpool, struct redirspec *rs)
6567 {
6568 	if (rs == NULL)
6569 		return 0;
6570 
6571 	rpool->proxy_port[0] = ntohs(rs->rport.a);
6572 
6573 	if (!rs->rport.b && rs->rport.t) {
6574 		rpool->proxy_port[1] = ntohs(rs->rport.a) +
6575 		    (ntohs(r->dst.port[1]) - ntohs(r->dst.port[0]));
6576 	} else {
6577 		if (validate_range(rs->rport.t, rs->rport.a,
6578 		    rs->rport.b)) {
6579 			yyerror("invalid rdr-to port range");
6580 			return (1);
6581 		}
6582 		r->rdr.proxy_port[1] = ntohs(rs->rport.b);
6583 	}
6584 
6585 	if (rs->pool_opts.staticport) {
6586 		yyerror("the 'static-port' option is only valid with nat rules");
6587 		return 1;
6588 	}
6589 
6590 	if (rs->pool_opts.mape.offset) {
6591 		yyerror("the 'map-e-portset' option is only valid with nat rules");
6592 		return 1;
6593 	}
6594 
6595 	return 0;
6596 }
6597 
6598 int
apply_nat_ports(struct pfctl_pool * rpool,struct redirspec * rs)6599 apply_nat_ports(struct pfctl_pool *rpool, struct redirspec *rs)
6600 {
6601 	if (rs == NULL)
6602 		return 0;
6603 
6604 	rpool->proxy_port[0] = ntohs(rs->rport.a);
6605 	rpool->proxy_port[1] = ntohs(rs->rport.b);
6606 	if (!rpool->proxy_port[0] && !rpool->proxy_port[1]) {
6607 		rpool->proxy_port[0] =  PF_NAT_PROXY_PORT_LOW;
6608 		rpool->proxy_port[1] =  PF_NAT_PROXY_PORT_HIGH;
6609 	} else if (!rpool->proxy_port[1])
6610 		rpool->proxy_port[1] = rpool->proxy_port[0];
6611 
6612 	if (rs->pool_opts.staticport) {
6613 		if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW &&
6614 		    rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) {
6615 			yyerror("the 'static-port' option can't"
6616 			    " be used when specifying a port"
6617 			    " range");
6618 			return 1;
6619 		}
6620 		rpool->proxy_port[0] = 0;
6621 		rpool->proxy_port[1] = 0;
6622 	}
6623 
6624 	if (rs->pool_opts.mape.offset) {
6625 		if (rs->pool_opts.staticport) {
6626 			yyerror("the 'map-e-portset' option"
6627 			    " can't be used 'static-port'");
6628 			return 1;
6629 		}
6630 		if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW &&
6631 		    rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) {
6632 			yyerror("the 'map-e-portset' option"
6633 			    " can't be used when specifying"
6634 			    " a port range");
6635 			return 1;
6636 		}
6637 		rpool->mape = rs->pool_opts.mape;
6638 	}
6639 
6640 	return 0;
6641 }
6642 
6643 int
apply_redirspec(struct pfctl_pool * rpool,struct redirspec * rs)6644 apply_redirspec(struct pfctl_pool *rpool, struct redirspec *rs)
6645 {
6646 	struct node_host	*h;
6647 	struct pfctl_pooladdr	*pa;
6648 
6649 	if (rs == NULL)
6650 		return 0;
6651 
6652 	rpool->opts = rs->pool_opts.type;
6653 
6654 	if ((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_NONE &&
6655 	    (rs->host->next != NULL ||
6656 	    rs->host->addr.type == PF_ADDR_TABLE ||
6657 	    DYNIF_MULTIADDR(rs->host->addr)))
6658 		rpool->opts = PF_POOL_ROUNDROBIN;
6659 
6660 	if (!PF_POOL_DYNTYPE(rpool->opts) &&
6661 	    (disallow_table(rs->host, "tables are not supported by pool type") ||
6662 	    disallow_alias(rs->host, "interface (%s) is not supported by pool type")))
6663 		return 1;
6664 
6665 	if (rs->host->next != NULL &&
6666 	    ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)) {
6667 		yyerror("r.route.opts must be PF_POOL_ROUNDROBIN");
6668 		return 1;
6669 	}
6670 
6671 	if (rs->host->next != NULL) {
6672 		if ((rpool->opts & PF_POOL_TYPEMASK) !=
6673 		    PF_POOL_ROUNDROBIN) {
6674 			yyerror("only round-robin valid for multiple "
6675 			    "redirection addresses");
6676 			return 1;
6677 		}
6678 	}
6679 
6680 	rpool->opts |= rs->pool_opts.opts;
6681 
6682 	if (rs->pool_opts.key != NULL)
6683 		memcpy(&(rpool->key), rs->pool_opts.key,
6684 		    sizeof(struct pf_poolhashkey));
6685 
6686 	for (h = rs->host; h != NULL; h = h->next) {
6687 		pa = calloc(1, sizeof(struct pfctl_pooladdr));
6688 		if (pa == NULL)
6689 			err(1, "%s: calloc", __func__);
6690 		pa->addr = h->addr;
6691 		pa->af = h->af;
6692 		if (h->ifname != NULL) {
6693 			if (strlcpy(pa->ifname, h->ifname,
6694 			    sizeof(pa->ifname)) >= sizeof(pa->ifname))
6695 				errx(1, "%s: strlcpy", __func__);
6696 		} else
6697 			pa->ifname[0] = 0;
6698 		TAILQ_INSERT_TAIL(&(rpool->list), pa, entries);
6699 	}
6700 
6701 	return 0;
6702 }
6703 
6704 int
check_binat_redirspec(struct node_host * src_host,struct pfctl_rule * r,sa_family_t af)6705 check_binat_redirspec(struct node_host *src_host, struct pfctl_rule *r,
6706     sa_family_t af)
6707 {
6708 	struct pfctl_pooladdr	*nat_pool = TAILQ_FIRST(&(r->nat.list));
6709 	int			error = 0;
6710 
6711 	/* XXX: FreeBSD allows syntax like "{ host1 host2 }" for redirection
6712 	 * pools but does not covert them to tables automatically, because
6713 	 * syntax "{ (iface1 host1), (iface2 iface2) }" is allowed for route-to
6714 	 * redirection. Add a FreeBSD-specific guard against using multiple
6715 	 * hosts for source and redirection.
6716 	 */
6717 	if (src_host->next) {
6718 		yyerror("invalid use of table as the source address "
6719 		    "of a binat-to rule");
6720 		error++;
6721 	}
6722 	if (TAILQ_NEXT(nat_pool, entries)) {
6723 		yyerror ("tables cannot be used as the redirect "
6724 		    "address of a binat-to rule");
6725 		error++;
6726 	}
6727 
6728 	if (disallow_table(src_host, "invalid use of table "
6729 	    "<%s> as the source address of a binat-to rule") ||
6730 	    disallow_alias(src_host, "invalid use of interface "
6731 	    "(%s) as the source address of a binat-to rule")) {
6732 		error++;
6733 	} else if ((r->src.addr.type != PF_ADDR_ADDRMASK &&
6734 	    r->src.addr.type != PF_ADDR_DYNIFTL) ||
6735 	    (nat_pool->addr.type != PF_ADDR_ADDRMASK &&
6736 	    nat_pool->addr.type != PF_ADDR_DYNIFTL)) {
6737 		yyerror("binat-to requires a specified "
6738 		    "source and redirect address");
6739 		error++;
6740 	}
6741 	if (DYNIF_MULTIADDR(r->src.addr) ||
6742 	    DYNIF_MULTIADDR(nat_pool->addr)) {
6743 		yyerror ("dynamic interfaces must be "
6744 		    "used with:0 in a binat-to rule");
6745 		error++;
6746 	}
6747 	if (PF_AZERO(&r->src.addr.v.a.mask, af) ||
6748 	    PF_AZERO(&(nat_pool->addr.v.a.mask), af)) {
6749 		yyerror ("source and redir addresses must have "
6750 		    "a matching network mask in binat-rule");
6751 		error++;
6752 	}
6753 	if (nat_pool->addr.type == PF_ADDR_TABLE) {
6754 		yyerror ("tables cannot be used as the redirect "
6755 		    "address of a binat-to rule");
6756 		error++;
6757 	}
6758 	if (r->direction != PF_INOUT) {
6759 		yyerror("binat-to cannot be specified "
6760 		    "with a direction");
6761 		error++;
6762 	}
6763 
6764 	/* first specify outbound NAT rule */
6765 	r->direction = PF_OUT;
6766 
6767 	return (error);
6768 }
6769 
6770 void
add_binat_rdr_rule(struct pfctl_rule * binat_rule,struct redirspec * binat_nat_redirspec,struct node_host * binat_src_host,struct pfctl_rule * rdr_rule,struct redirspec ** rdr_redirspec,struct node_host ** rdr_dst_host)6771 add_binat_rdr_rule(
6772     struct pfctl_rule *binat_rule,
6773     struct redirspec *binat_nat_redirspec, struct node_host *binat_src_host,
6774     struct pfctl_rule *rdr_rule, struct redirspec **rdr_redirspec,
6775     struct node_host **rdr_dst_host)
6776 {
6777 	struct node_host	*rdr_src_host;
6778 
6779 	/*
6780 	 * We're copying the whole rule, but we must re-init redir pools.
6781 	 * FreeBSD uses lists of pfctl_pooladdr, we can't just overwrite them.
6782 	 */
6783 	bcopy(binat_rule, rdr_rule, sizeof(struct pfctl_rule));
6784 	TAILQ_INIT(&(rdr_rule->rdr.list));
6785 	TAILQ_INIT(&(rdr_rule->nat.list));
6786 
6787 	/* now specify inbound rdr rule */
6788 	rdr_rule->direction = PF_IN;
6789 
6790 	if ((rdr_src_host = calloc(1, sizeof(*rdr_src_host))) == NULL)
6791 		err(1, "%s", __func__);
6792 	bcopy(binat_src_host, rdr_src_host, sizeof(*rdr_src_host));
6793 	rdr_src_host->ifname = NULL;
6794 	rdr_src_host->next = NULL;
6795 	rdr_src_host->tail = NULL;
6796 
6797 	if (((*rdr_dst_host) = calloc(1, sizeof(**rdr_dst_host))) == NULL)
6798 		err(1, "%s", __func__);
6799 	bcopy(&(binat_nat_redirspec->host->addr), &((*rdr_dst_host)->addr),
6800 	    sizeof((*rdr_dst_host)->addr));
6801 	(*rdr_dst_host)->ifname = NULL;
6802 	(*rdr_dst_host)->next = NULL;
6803 	(*rdr_dst_host)->tail = NULL;
6804 
6805 	if (((*rdr_redirspec) = calloc(1, sizeof(**rdr_redirspec))) == NULL)
6806 		err(1, "%s", __func__);
6807 	bcopy(binat_nat_redirspec, (*rdr_redirspec), sizeof(**rdr_redirspec));
6808 	(*rdr_redirspec)->pool_opts.staticport = 0;
6809 	(*rdr_redirspec)->host = rdr_src_host;
6810 }
6811 
6812 void
expand_rule(struct pfctl_rule * r,bool keeprule,struct node_if * interfaces,struct redirspec * nat,struct redirspec * rdr,struct redirspec * route,struct node_proto * protos,struct node_os * src_oses,struct node_host * src_hosts,struct node_port * src_ports,struct node_host * dst_hosts,struct node_port * dst_ports,struct node_uid * uids,struct node_gid * gids,struct node_if * rcv,struct node_icmp * icmp_types)6813 expand_rule(struct pfctl_rule *r, bool keeprule,
6814     struct node_if *interfaces, struct redirspec *nat,
6815     struct redirspec *rdr, struct redirspec *route,
6816     struct node_proto *protos,
6817     struct node_os *src_oses, struct node_host *src_hosts,
6818     struct node_port *src_ports, struct node_host *dst_hosts,
6819     struct node_port *dst_ports, struct node_uid *uids, struct node_gid *gids,
6820     struct node_if *rcv, struct node_icmp *icmp_types)
6821 {
6822 	sa_family_t		 af = r->af;
6823 	int			 added = 0, error = 0;
6824 	char			 ifname[IF_NAMESIZE];
6825 	char			 label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE];
6826 	char			 tagname[PF_TAG_NAME_SIZE];
6827 	char			 match_tagname[PF_TAG_NAME_SIZE];
6828 	struct node_host	*osrch, *odsth;
6829 	u_int8_t		 flags, flagset, keep_state;
6830 
6831 	memcpy(label, r->label, sizeof(r->label));
6832 	assert(sizeof(r->label) == sizeof(label));
6833 	if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
6834 		errx(1, "%s: strlcpy", __func__);
6835 	if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
6836 	    sizeof(match_tagname))
6837 		errx(1, "%s: strlcpy", __func__);
6838 	flags = r->flags;
6839 	flagset = r->flagset;
6840 	keep_state = r->keep_state;
6841 
6842 	LOOP_THROUGH(struct node_if, interface, interfaces,
6843 	LOOP_THROUGH(struct node_proto, proto, protos,
6844 	LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
6845 	LOOP_THROUGH(struct node_host, src_host, src_hosts,
6846 	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
6847 	LOOP_THROUGH(struct node_port, src_port, src_ports,
6848 	LOOP_THROUGH(struct node_port, dst_port, dst_ports,
6849 	LOOP_THROUGH(struct node_os, src_os, src_oses,
6850 	LOOP_THROUGH(struct node_uid, uid, uids,
6851 	LOOP_THROUGH(struct node_gid, gid, gids,
6852 
6853 		r->af = af;
6854 
6855 		if (r->rule_flag & PFRULE_AFTO) {
6856 			assert(nat != NULL);
6857 			r->naf = nat->af;
6858 		}
6859 
6860 		/* for link-local IPv6 address, interface must match up */
6861 		if ((r->af && src_host->af && r->af != src_host->af) ||
6862 		    (r->af && dst_host->af && r->af != dst_host->af) ||
6863 		    (src_host->af && dst_host->af &&
6864 		    src_host->af != dst_host->af) ||
6865 		    (src_host->ifindex && dst_host->ifindex &&
6866 		    src_host->ifindex != dst_host->ifindex) ||
6867 		    (src_host->ifindex && *interface->ifname &&
6868 		    src_host->ifindex != ifa_nametoindex(interface->ifname)) ||
6869 		    (dst_host->ifindex && *interface->ifname &&
6870 		    dst_host->ifindex != ifa_nametoindex(interface->ifname)))
6871 			continue;
6872 		if (!r->af && src_host->af)
6873 			r->af = src_host->af;
6874 		else if (!r->af && dst_host->af)
6875 			r->af = dst_host->af;
6876 
6877 		if (*interface->ifname)
6878 			strlcpy(r->ifname, interface->ifname,
6879 			    sizeof(r->ifname));
6880 		else if (ifa_indextoname(src_host->ifindex, ifname))
6881 			strlcpy(r->ifname, ifname, sizeof(r->ifname));
6882 		else if (ifa_indextoname(dst_host->ifindex, ifname))
6883 			strlcpy(r->ifname, ifname, sizeof(r->ifname));
6884 		else
6885 			memset(r->ifname, '\0', sizeof(r->ifname));
6886 
6887 		memcpy(r->label, label, sizeof(r->label));
6888 		if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
6889 		    sizeof(r->tagname))
6890 			errx(1, "%s: strlcpy", __func__);
6891 		if (strlcpy(r->match_tagname, match_tagname,
6892 		    sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
6893 			errx(1, "%s: strlcpy", __func__);
6894 
6895 		osrch = odsth = NULL;
6896 		if (src_host->addr.type == PF_ADDR_DYNIFTL) {
6897 			osrch = src_host;
6898 			if ((src_host = gen_dynnode(src_host, r->af)) == NULL)
6899 				err(1, "%s: calloc", __func__);
6900 		}
6901 		if (dst_host->addr.type == PF_ADDR_DYNIFTL) {
6902 			odsth = dst_host;
6903 			if ((dst_host = gen_dynnode(dst_host, r->af)) == NULL)
6904 				err(1, "%s: calloc", __func__);
6905 		}
6906 
6907 		error += check_netmask(src_host, r->af);
6908 		error += check_netmask(dst_host, r->af);
6909 
6910 		r->ifnot = interface->not;
6911 		r->proto = proto->proto;
6912 		r->src.addr = src_host->addr;
6913 		r->src.neg = src_host->not;
6914 		r->src.port[0] = src_port->port[0];
6915 		r->src.port[1] = src_port->port[1];
6916 		r->src.port_op = src_port->op;
6917 		r->dst.addr = dst_host->addr;
6918 		r->dst.neg = dst_host->not;
6919 		r->dst.port[0] = dst_port->port[0];
6920 		r->dst.port[1] = dst_port->port[1];
6921 		r->dst.port_op = dst_port->op;
6922 		r->uid.op = uid->op;
6923 		r->uid.uid[0] = uid->uid[0];
6924 		r->uid.uid[1] = uid->uid[1];
6925 		r->gid.op = gid->op;
6926 		r->gid.gid[0] = gid->gid[0];
6927 		r->gid.gid[1] = gid->gid[1];
6928 		if (rcv) {
6929 			strlcpy(r->rcv_ifname, rcv->ifname,
6930 			    sizeof(r->rcv_ifname));
6931 			r->rcvifnot = rcv->not;
6932 		}
6933 		r->type = icmp_type->type;
6934 		r->code = icmp_type->code;
6935 
6936 		if ((keep_state == PF_STATE_MODULATE ||
6937 		    keep_state == PF_STATE_SYNPROXY) &&
6938 		    r->proto && r->proto != IPPROTO_TCP)
6939 			r->keep_state = PF_STATE_NORMAL;
6940 		else
6941 			r->keep_state = keep_state;
6942 
6943 		if (r->proto && r->proto != IPPROTO_TCP) {
6944 			r->flags = 0;
6945 			r->flagset = 0;
6946 		} else {
6947 			r->flags = flags;
6948 			r->flagset = flagset;
6949 		}
6950 		if (icmp_type->proto && r->proto != icmp_type->proto) {
6951 			yyerror("icmp-type mismatch");
6952 			error++;
6953 		}
6954 
6955 		if (src_os && src_os->os) {
6956 			r->os_fingerprint = pfctl_get_fingerprint(src_os->os);
6957 			if ((pf->opts & PF_OPT_VERBOSE2) &&
6958 			    r->os_fingerprint == PF_OSFP_NOMATCH)
6959 				fprintf(stderr,
6960 				    "warning: unknown '%s' OS fingerprint\n",
6961 				    src_os->os);
6962 		} else {
6963 			r->os_fingerprint = PF_OSFP_ANY;
6964 		}
6965 
6966 		if (r->action == PF_RDR) {
6967 			/* Pre-FreeBSD 15 "rdr" rule */
6968 			error += apply_rdr_ports(r, &(r->rdr), rdr);
6969 			error += apply_redirspec(&(r->rdr), rdr);
6970 		} else if (r->action == PF_NAT) {
6971 			/* Pre-FreeBSD 15 "nat" rule */
6972 			error += apply_nat_ports(&(r->rdr), rdr);
6973 			error += apply_redirspec(&(r->rdr), rdr);
6974 		} else {
6975 			/* Modern rule with optional NAT, BINAT, RDR or ROUTE*/
6976 			error += apply_redirspec(&(r->route), route);
6977 
6978 			error += apply_nat_ports(&(r->nat), nat);
6979 			error += apply_redirspec(&(r->nat), nat);
6980 			error += apply_rdr_ports(r, &(r->rdr), rdr);
6981 			error += apply_redirspec(&(r->rdr), rdr);
6982 
6983 			if (nat && nat->binat)
6984 				error += check_binat_redirspec(src_host, r, af);
6985 		}
6986 
6987 		if (rule_consistent(r) < 0 || error)
6988 			yyerror("skipping rule due to errors");
6989 		else {
6990 			r->nr = pf->astack[pf->asd]->match++;
6991 			pfctl_append_rule(pf, r);
6992 			added++;
6993 		}
6994 
6995 		/* Generate binat's matching inbound rule */
6996 		if (!error && nat && nat->binat) {
6997 			struct pfctl_rule	rdr_rule;
6998 			struct redirspec	*rdr_redirspec;
6999 			struct node_host	*rdr_dst_host;
7000 
7001 			add_binat_rdr_rule(
7002 			    r, nat, src_hosts,
7003 			    &rdr_rule, &rdr_redirspec, &rdr_dst_host);
7004 
7005 			expand_rule(&rdr_rule, true, interface, NULL, rdr_redirspec,
7006 			    NULL, proto, src_os, dst_host, dst_port,
7007 			    rdr_dst_host, src_port, uid, gid, rcv, icmp_type);
7008 		}
7009 
7010 		if (osrch && src_host->addr.type == PF_ADDR_DYNIFTL) {
7011 			free(src_host);
7012 			src_host = osrch;
7013 		}
7014 		if (odsth && dst_host->addr.type == PF_ADDR_DYNIFTL) {
7015 			free(dst_host);
7016 			dst_host = odsth;
7017 		}
7018 
7019 	))))))))));
7020 
7021 	if (!keeprule) {
7022 		FREE_LIST(struct node_if, interfaces);
7023 		FREE_LIST(struct node_proto, protos);
7024 		FREE_LIST(struct node_host, src_hosts);
7025 		FREE_LIST(struct node_port, src_ports);
7026 		FREE_LIST(struct node_os, src_oses);
7027 		FREE_LIST(struct node_host, dst_hosts);
7028 		FREE_LIST(struct node_port, dst_ports);
7029 		FREE_LIST(struct node_uid, uids);
7030 		FREE_LIST(struct node_gid, gids);
7031 		FREE_LIST(struct node_icmp, icmp_types);
7032 		if (nat) {
7033 			FREE_LIST(struct node_host, nat->host);
7034 			free(nat);
7035 		}
7036 		if (rdr) {
7037 			FREE_LIST(struct node_host, rdr->host);
7038 			free(rdr);
7039 		}
7040 		if (route) {
7041 			FREE_LIST(struct node_host, route->host);
7042 			free(route);
7043 		}
7044 	}
7045 
7046 	if (!added)
7047 		yyerror("rule expands to no valid combination");
7048 }
7049 
7050 int
expand_skip_interface(struct node_if * interfaces)7051 expand_skip_interface(struct node_if *interfaces)
7052 {
7053 	int	errs = 0;
7054 
7055 	if (!interfaces || (!interfaces->next && !interfaces->not &&
7056 	    !strcmp(interfaces->ifname, "none"))) {
7057 		if (pf->opts & PF_OPT_VERBOSE)
7058 			printf("set skip on none\n");
7059 		errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0);
7060 		return (errs);
7061 	}
7062 
7063 	if (pf->opts & PF_OPT_VERBOSE)
7064 		printf("set skip on {");
7065 	LOOP_THROUGH(struct node_if, interface, interfaces,
7066 		if (pf->opts & PF_OPT_VERBOSE)
7067 			printf(" %s", interface->ifname);
7068 		if (interface->not) {
7069 			yyerror("skip on ! <interface> is not supported");
7070 			errs++;
7071 		} else
7072 			errs += pfctl_set_interface_flags(pf,
7073 			    interface->ifname, PFI_IFLAG_SKIP, 1);
7074 	);
7075 	if (pf->opts & PF_OPT_VERBOSE)
7076 		printf(" }\n");
7077 
7078 	FREE_LIST(struct node_if, interfaces);
7079 
7080 	if (errs)
7081 		return (1);
7082 	else
7083 		return (0);
7084 }
7085 
7086 void
freehostlist(struct node_host * h)7087 freehostlist(struct node_host *h)
7088 {
7089 	FREE_LIST(struct node_host, h);
7090 }
7091 
7092 #undef FREE_LIST
7093 #undef LOOP_THROUGH
7094 
7095 int
check_rulestate(int desired_state)7096 check_rulestate(int desired_state)
7097 {
7098 	if (require_order && (rulestate > desired_state)) {
7099 		yyerror("Rules must be in order: options, ethernet, "
7100 		    "normalization, queueing, translation, filtering");
7101 		return (1);
7102 	}
7103 	rulestate = desired_state;
7104 	return (0);
7105 }
7106 
7107 int
kw_cmp(const void * k,const void * e)7108 kw_cmp(const void *k, const void *e)
7109 {
7110 	return (strcmp(k, ((const struct keywords *)e)->k_name));
7111 }
7112 
7113 int
lookup(char * s)7114 lookup(char *s)
7115 {
7116 	/* this has to be sorted always */
7117 	static const struct keywords keywords[] = {
7118 		{ "above",		ABOVE},
7119 		{ "af-to",		AFTO},
7120 		{ "all",		ALL},
7121 		{ "allow-opts",		ALLOWOPTS},
7122 		{ "allow-related",	ALLOW_RELATED},
7123 		{ "altq",		ALTQ},
7124 		{ "anchor",		ANCHOR},
7125 		{ "antispoof",		ANTISPOOF},
7126 		{ "any",		ANY},
7127 		{ "bandwidth",		BANDWIDTH},
7128 		{ "below",		BELOW},
7129 		{ "binat",		BINAT},
7130 		{ "binat-anchor",	BINATANCHOR},
7131 		{ "binat-to",		BINATTO},
7132 		{ "bitmask",		BITMASK},
7133 		{ "block",		BLOCK},
7134 		{ "block-policy",	BLOCKPOLICY},
7135 		{ "bridge-to",		BRIDGE_TO},
7136 		{ "buckets",		BUCKETS},
7137 		{ "cbq",		CBQ},
7138 		{ "code",		CODE},
7139 		{ "codelq",		CODEL},
7140 		{ "debug",		DEBUG},
7141 		{ "divert-reply",	DIVERTREPLY},
7142 		{ "divert-to",		DIVERTTO},
7143 		{ "dnpipe",		DNPIPE},
7144 		{ "dnqueue",		DNQUEUE},
7145 		{ "drop",		DROP},
7146 		{ "dup-to",		DUPTO},
7147 		{ "endpoint-independent", ENDPI},
7148 		{ "entries",	ENTRIES},
7149 		{ "ether",		ETHER},
7150 		{ "fail-policy",	FAILPOLICY},
7151 		{ "fairq",		FAIRQ},
7152 		{ "fastroute",		FASTROUTE},
7153 		{ "file",		FILENAME},
7154 		{ "fingerprints",	FINGERPRINTS},
7155 		{ "flags",		FLAGS},
7156 		{ "floating",		FLOATING},
7157 		{ "flush",		FLUSH},
7158 		{ "for",		FOR},
7159 		{ "fragment",		FRAGMENT},
7160 		{ "from",		FROM},
7161 		{ "global",		GLOBAL},
7162 		{ "group",		GROUP},
7163 		{ "hfsc",		HFSC},
7164 		{ "hogs",		HOGS},
7165 		{ "hostid",		HOSTID},
7166 		{ "icmp-type",		ICMPTYPE},
7167 		{ "icmp6-type",		ICMP6TYPE},
7168 		{ "id",			ID},
7169 		{ "if-bound",		IFBOUND},
7170 		{ "in",			IN},
7171 		{ "include",		INCLUDE},
7172 		{ "inet",		INET},
7173 		{ "inet6",		INET6},
7174 		{ "interval",		INTERVAL},
7175 		{ "keep",		KEEP},
7176 		{ "keepcounters",	KEEPCOUNTERS},
7177 		{ "l3",			L3},
7178 		{ "label",		LABEL},
7179 		{ "limit",		LIMIT},
7180 		{ "limiter",	LIMITER},
7181 		{ "linkshare",		LINKSHARE},
7182 		{ "load",		LOAD},
7183 		{ "log",		LOG},
7184 		{ "loginterface",	LOGINTERFACE},
7185 		{ "map-e-portset",	MAPEPORTSET},
7186 		{ "mask",		MASK},
7187 		{ "match",		MATCH},
7188 		{ "matches",	MATCHES},
7189 		{ "max",		MAXIMUM},
7190 		{ "max-mss",		MAXMSS},
7191 		{ "max-pkt-rate",       MAXPKTRATE},
7192 		{ "max-pkt-size",	MAXPKTSIZE},
7193 		{ "max-src-conn",	MAXSRCCONN},
7194 		{ "max-src-conn-rate",	MAXSRCCONNRATE},
7195 		{ "max-src-nodes",	MAXSRCNODES},
7196 		{ "max-src-states",	MAXSRCSTATES},
7197 		{ "min-ttl",		MINTTL},
7198 		{ "modulate",		MODULATE},
7199 		{ "nat",		NAT},
7200 		{ "nat-anchor",		NATANCHOR},
7201 		{ "nat-to",		NATTO},
7202 		{ "no",			NO},
7203 		{ "no-df",		NODF},
7204 		{ "no-match",	NOMATCH},
7205 		{ "no-route",		NOROUTE},
7206 		{ "no-sync",		NOSYNC},
7207 		{ "on",			ON},
7208 		{ "once",		ONCE},
7209 		{ "optimization",	OPTIMIZATION},
7210 		{ "os",			OS},
7211 		{ "out",		OUT},
7212 		{ "overload",		OVERLOAD},
7213 		{ "pass",		PASS},
7214 		{ "pflow",		PFLOW},
7215 		{ "port",		PORT},
7216 		{ "prefer-ipv6-nexthop", IPV6NH},
7217 		{ "prio",		PRIO},
7218 		{ "priority",		PRIORITY},
7219 		{ "priq",		PRIQ},
7220 		{ "probability",	PROBABILITY},
7221 		{ "proto",		PROTO},
7222 		{ "qlimit",		QLIMIT},
7223 		{ "queue",		QUEUE},
7224 		{ "quick",		QUICK},
7225 		{ "random",		RANDOM},
7226 		{ "random-id",		RANDOMID},
7227 		{ "rate",		RATE},
7228 		{ "rdr",		RDR},
7229 		{ "rdr-anchor",		RDRANCHOR},
7230 		{ "rdr-to",		RDRTO},
7231 		{ "realtime",		REALTIME},
7232 		{ "reassemble",		REASSEMBLE},
7233 		{ "received-on",	RECEIVEDON},
7234 		{ "reply-to",		REPLYTO},
7235 		{ "require-order",	REQUIREORDER},
7236 		{ "return",		RETURN},
7237 		{ "return-icmp",	RETURNICMP},
7238 		{ "return-icmp6",	RETURNICMP6},
7239 		{ "return-rst",		RETURNRST},
7240 		{ "ridentifier",	RIDENTIFIER},
7241 		{ "round-robin",	ROUNDROBIN},
7242 		{ "route",		ROUTE},
7243 		{ "route-to",		ROUTETO},
7244 		{ "rtable",		RTABLE},
7245 		{ "rule",		RULE},
7246 		{ "ruleset-optimization",	RULESET_OPTIMIZATION},
7247 		{ "scrub",		SCRUB},
7248 		{ "set",		SET},
7249 		{ "set-tos",		SETTOS},
7250 		{ "skip",		SKIP},
7251 		{ "sloppy",		SLOPPY},
7252 		{ "source",		SOURCE},
7253 		{ "source-hash",	SOURCEHASH},
7254 		{ "source-track",	SOURCETRACK},
7255 		{ "state",		STATE},
7256 		{ "state-defaults",	STATEDEFAULTS},
7257 		{ "state-policy",	STATEPOLICY},
7258 		{ "static-port",	STATICPORT},
7259 		{ "sticky-address",	STICKYADDRESS},
7260 		{ "syncookies",         SYNCOOKIES},
7261 		{ "synproxy",		SYNPROXY},
7262 		{ "table",		TABLE},
7263 		{ "tag",		TAG},
7264 		{ "tagged",		TAGGED},
7265 		{ "target",		TARGET},
7266 		{ "tbrsize",		TBRSIZE},
7267 		{ "timeout",		TIMEOUT},
7268 		{ "to",			TO},
7269 		{ "tos",		TOS},
7270 		{ "ttl",		TTL},
7271 		{ "upperlimit",		UPPERLIMIT},
7272 		{ "urpf-failed",	URPFFAILED},
7273 		{ "user",		USER},
7274 	};
7275 	const struct keywords	*p;
7276 
7277 	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
7278 	    sizeof(keywords[0]), kw_cmp);
7279 
7280 	if (p) {
7281 		if (debug > 1)
7282 			fprintf(stderr, "%s: %d\n", s, p->k_val);
7283 		return (p->k_val);
7284 	} else {
7285 		if (debug > 1)
7286 			fprintf(stderr, "string: %s\n", s);
7287 		return (STRING);
7288 	}
7289 }
7290 
7291 #define	START_EXPAND	1
7292 #define	DONE_EXPAND		2
7293 
7294 static int expanding;
7295 
7296 int
igetc(void)7297 igetc(void)
7298 {
7299 	int c;
7300 	while (1) {
7301 		if (file->ungetpos > 0)
7302 			c = file->ungetbuf[--file->ungetpos];
7303 		else
7304 			c = getc(file->stream);
7305 		if (c == START_EXPAND)
7306 			expanding = 1;
7307 		else if (c == DONE_EXPAND)
7308 			expanding = 0;
7309 		else
7310 			break;
7311 	}
7312 	return (c);
7313 }
7314 
7315 int
lgetc(int quotec)7316 lgetc(int quotec)
7317 {
7318 	int	c, next;
7319 
7320 	if (quotec) {
7321 		if ((c = igetc()) == EOF) {
7322 			yyerror("reached end of file while parsing quoted string");
7323 			if (file == topfile || popfile() == EOF)
7324 				return (EOF);
7325 			return (quotec);
7326 		}
7327 		return (c);
7328 	}
7329 
7330 	while ((c = igetc()) == '\\') {
7331 		next = igetc();
7332 		if (next != '\n') {
7333 			c = next;
7334 			break;
7335 		}
7336 		yylval.lineno = file->lineno;
7337 		file->lineno++;
7338 	}
7339 
7340 	if (c == EOF) {
7341 		/*
7342 		 * Fake EOL when hit EOF for the first time. This gets line
7343 		 * count right if last line in included file is syntactically
7344 		 * invalid and has no newline.
7345 		 */
7346 		if (file->eof_reached == 0) {
7347 			file->eof_reached = 1;
7348 			return ('\n');
7349 		}
7350 		while (c == EOF) {
7351 			if (file == topfile || popfile() == EOF)
7352 				return (EOF);
7353 			c = igetc();
7354 		}
7355 	}
7356 	return (c);
7357 }
7358 
7359 void
lungetc(int c)7360 lungetc(int c)
7361 {
7362 	if (c == EOF)
7363 		return;
7364 	if (file->ungetpos >= file->ungetsize) {
7365 		void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
7366 		if (p == NULL)
7367 			err(1, "%s", __func__);
7368 		file->ungetbuf = p;
7369 		file->ungetsize *= 2;
7370 	}
7371 	file->ungetbuf[file->ungetpos++] = c;
7372 }
7373 
7374 int
findeol(void)7375 findeol(void)
7376 {
7377 	int	c;
7378 
7379 	/* skip to either EOF or the first real EOL */
7380 	while (1) {
7381 		c = lgetc(0);
7382 		if (c == '\n') {
7383 			file->lineno++;
7384 			break;
7385 		}
7386 		if (c == EOF)
7387 			break;
7388 	}
7389 	return (ERROR);
7390 }
7391 
7392 int
yylex(void)7393 yylex(void)
7394 {
7395 	char	 buf[8096];
7396 	char	*p, *val;
7397 	int	 quotec, next, c;
7398 	int	 token;
7399 
7400 top:
7401 	p = buf;
7402 	while ((c = lgetc(0)) == ' ' || c == '\t' || c == '\014')
7403 		; /* nothing */
7404 
7405 	yylval.lineno = file->lineno;
7406 	if (c == '#')
7407 		while ((c = lgetc(0)) != '\n' && c != EOF)
7408 			; /* nothing */
7409 	if (c == '$' && !expanding) {
7410 		while (1) {
7411 			if ((c = lgetc(0)) == EOF)
7412 				return (0);
7413 
7414 			if (p + 1 >= buf + sizeof(buf) - 1) {
7415 				yyerror("string too long");
7416 				return (findeol());
7417 			}
7418 			if (isalnum(c) || c == '_') {
7419 				*p++ = (char)c;
7420 				continue;
7421 			}
7422 			*p = '\0';
7423 			lungetc(c);
7424 			break;
7425 		}
7426 		val = symget(buf);
7427 		if (val == NULL) {
7428 			yyerror("macro '%s' not defined", buf);
7429 			return (findeol());
7430 		}
7431 		p = val + strlen(val) - 1;
7432 		lungetc(DONE_EXPAND);
7433 		while (p >= val) {
7434 			lungetc(*p);
7435 			p--;
7436 		}
7437 		lungetc(START_EXPAND);
7438 		goto top;
7439 	}
7440 
7441 	switch (c) {
7442 	case '\'':
7443 	case '"':
7444 		quotec = c;
7445 		while (1) {
7446 			if ((c = lgetc(quotec)) == EOF)
7447 				return (0);
7448 			if (c == '\n') {
7449 				file->lineno++;
7450 				continue;
7451 			} else if (c == '\\') {
7452 				if ((next = lgetc(quotec)) == EOF)
7453 					return (0);
7454 				if (next == quotec || next == ' ' ||
7455 				    next == '\t')
7456 					c = next;
7457 				else if (next == '\n') {
7458 					file->lineno++;
7459 					continue;
7460 				}
7461 				else
7462 					lungetc(next);
7463 			} else if (c == quotec) {
7464 				*p = '\0';
7465 				break;
7466 			} else if (c == '\0') {
7467 				yyerror("syntax error");
7468 				return (findeol());
7469 			}
7470 			if (p + 1 >= buf + sizeof(buf) - 1) {
7471 				yyerror("string too long");
7472 				return (findeol());
7473 			}
7474 			*p++ = (char)c;
7475 		}
7476 		yylval.v.string = strdup(buf);
7477 		if (yylval.v.string == NULL)
7478 			err(1, "%s: strdup", __func__);
7479 		return (STRING);
7480 		case '!':
7481 			next = lgetc(0);
7482 			if (next == '=')
7483 				return (NE);
7484 			lungetc(next);
7485 		break;
7486 	case '<':
7487 		next = lgetc(0);
7488 		if (next == '>') {
7489 			yylval.v.i = PF_OP_XRG;
7490 			return (PORTBINARY);
7491 		} else if (next == '=')
7492 			return (LE);
7493 		lungetc(next);
7494 		break;
7495 	case '>':
7496 		next = lgetc(0);
7497 		if (next == '<') {
7498 			yylval.v.i = PF_OP_IRG;
7499 			return (PORTBINARY);
7500 		} else if (next == '=')
7501 			return (GE);
7502 		lungetc(next);
7503 		break;
7504 	case '-':
7505 		next = lgetc(0);
7506 		if (next == '>')
7507 			return (ARROW);
7508 		lungetc(next);
7509 		break;
7510 	}
7511 
7512 #define allowed_to_end_number(x) \
7513 	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
7514 
7515 	if (c == '-' || isdigit(c)) {
7516 		do {
7517 			*p++ = c;
7518 			if ((size_t)(p-buf) >= sizeof(buf)) {
7519 				yyerror("string too long");
7520 				return (findeol());
7521 			}
7522 		} while ((c = lgetc(0)) != EOF && isdigit(c));
7523 		lungetc(c);
7524 		if (p == buf + 1 && buf[0] == '-')
7525 			goto nodigits;
7526 		if (c == EOF || allowed_to_end_number(c)) {
7527 			const char *errstr = NULL;
7528 
7529 			*p = '\0';
7530 			yylval.v.number = strtonum(buf, LLONG_MIN,
7531 			    LLONG_MAX, &errstr);
7532 			if (errstr) {
7533 				yyerror("\"%s\" invalid number: %s",
7534 				    buf, errstr);
7535 				return (findeol());
7536 			}
7537 			return (NUMBER);
7538 		} else {
7539 nodigits:
7540 			while (p > buf + 1)
7541 				lungetc(*--p);
7542 			c = *--p;
7543 			if (c == '-')
7544 				return (c);
7545 		}
7546 	}
7547 
7548 #define allowed_in_string(x) \
7549 	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
7550 	x != '{' && x != '}' && x != '<' && x != '>' && \
7551 	x != '!' && x != '=' && x != '/' && x != '#' && \
7552 	x != ','))
7553 
7554 	if (isalnum(c) || c == ':' || c == '_') {
7555 		do {
7556 			*p++ = c;
7557 			if ((size_t)(p-buf) >= sizeof(buf)) {
7558 				yyerror("string too long");
7559 				return (findeol());
7560 			}
7561 		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
7562 		lungetc(c);
7563 		*p = '\0';
7564 		if ((token = lookup(buf)) == STRING)
7565 			if ((yylval.v.string = strdup(buf)) == NULL)
7566 				err(1, "%s: strdup", __func__);
7567 		return (token);
7568 	}
7569 	if (c == '\n') {
7570 		yylval.lineno = file->lineno;
7571 		file->lineno++;
7572 	}
7573 	if (c == EOF)
7574 		return (0);
7575 	return (c);
7576 }
7577 
7578 int
check_file_secrecy(int fd,const char * fname)7579 check_file_secrecy(int fd, const char *fname)
7580 {
7581 	struct stat	st;
7582 
7583 	if (fstat(fd, &st)) {
7584 		warn("cannot stat %s", fname);
7585 		return (-1);
7586 	}
7587 	if (st.st_uid != 0 && st.st_uid != getuid()) {
7588 		warnx("%s: owner not root or current user", fname);
7589 		return (-1);
7590 	}
7591 	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
7592 		warnx("%s: group writable or world read/writable", fname);
7593 		return (-1);
7594 	}
7595 	return (0);
7596 }
7597 
7598 struct file *
pushfile(const char * name,int secret)7599 pushfile(const char *name, int secret)
7600 {
7601 	struct file	*nfile;
7602 
7603 	if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
7604 	    (nfile->name = strdup(name)) == NULL) {
7605 		warn("%s", __func__);
7606 		if (nfile)
7607 			free(nfile);
7608 		return (NULL);
7609 	}
7610 	if (TAILQ_FIRST(&files) == NULL && strcmp(nfile->name, "-") == 0) {
7611 		nfile->stream = stdin;
7612 		free(nfile->name);
7613 		if ((nfile->name = strdup("stdin")) == NULL) {
7614 			warn("%s", __func__);
7615 			free(nfile);
7616 			return (NULL);
7617 		}
7618 	} else if ((nfile->stream = pfctl_fopen(nfile->name, "r")) == NULL) {
7619 		warn("%s: %s", __func__, nfile->name);
7620 		free(nfile->name);
7621 		free(nfile);
7622 		return (NULL);
7623 	} else if (secret &&
7624 	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
7625 		fclose(nfile->stream);
7626 		free(nfile->name);
7627 		free(nfile);
7628 		return (NULL);
7629 	}
7630 	nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
7631 	nfile->ungetsize = 16;
7632 	nfile->ungetbuf = malloc(nfile->ungetsize);
7633 	if (nfile->ungetbuf == NULL) {
7634 		warn("%s", __func__);
7635 		fclose(nfile->stream);
7636 		free(nfile->name);
7637 		free(nfile);
7638 		return (NULL);
7639 	}
7640 	TAILQ_INSERT_TAIL(&files, nfile, entry);
7641 	return (nfile);
7642 }
7643 
7644 int
popfile(void)7645 popfile(void)
7646 {
7647 	struct file	*prev;
7648 
7649 	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
7650 		prev->errors += file->errors;
7651 
7652 	TAILQ_REMOVE(&files, file, entry);
7653 	fclose(file->stream);
7654 	free(file->name);
7655 	free(file->ungetbuf);
7656 	free(file);
7657 	file = prev;
7658 
7659 	return (file ? 0 : EOF);
7660 }
7661 
7662 int
parse_config(char * filename,struct pfctl * xpf)7663 parse_config(char *filename, struct pfctl *xpf)
7664 {
7665 	int		 errors = 0;
7666 	struct sym	*sym;
7667 
7668 	pf = xpf;
7669 	errors = 0;
7670 	rulestate = PFCTL_STATE_NONE;
7671 	returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
7672 	returnicmp6default =
7673 	    (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
7674 	blockpolicy = PFRULE_DROP;
7675 	failpolicy = PFRULE_DROP;
7676 	require_order = 1;
7677 
7678 	if ((file = pushfile(filename, 0)) == NULL) {
7679 		warn("cannot open the main config file!");
7680 		return (-1);
7681 	}
7682 	topfile = file;
7683 
7684 	yyparse();
7685 	errors = file->errors;
7686 	popfile();
7687 
7688 	/* Free macros and check which have not been used. */
7689 	while ((sym = TAILQ_FIRST(&symhead))) {
7690 		if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used)
7691 			fprintf(stderr, "warning: macro '%s' not "
7692 			    "used\n", sym->nam);
7693 		free(sym->nam);
7694 		free(sym->val);
7695 		TAILQ_REMOVE(&symhead, sym, entry);
7696 		free(sym);
7697 	}
7698 
7699 	return (errors ? -1 : 0);
7700 }
7701 
7702 int
symset(const char * nam,const char * val,int persist)7703 symset(const char *nam, const char *val, int persist)
7704 {
7705 	struct sym	*sym;
7706 
7707 	TAILQ_FOREACH(sym, &symhead, entry) {
7708 		if (strcmp(nam, sym->nam) == 0)
7709 			break;
7710 	}
7711 
7712 	if (sym != NULL) {
7713 		if (sym->persist == 1)
7714 			return (0);
7715 		else {
7716 			free(sym->nam);
7717 			free(sym->val);
7718 			TAILQ_REMOVE(&symhead, sym, entry);
7719 			free(sym);
7720 		}
7721 	}
7722 	if ((sym = calloc(1, sizeof(*sym))) == NULL)
7723 		return (-1);
7724 
7725 	sym->nam = strdup(nam);
7726 	if (sym->nam == NULL) {
7727 		free(sym);
7728 		return (-1);
7729 	}
7730 	sym->val = strdup(val);
7731 	if (sym->val == NULL) {
7732 		free(sym->nam);
7733 		free(sym);
7734 		return (-1);
7735 	}
7736 	sym->used = 0;
7737 	sym->persist = persist;
7738 	TAILQ_INSERT_TAIL(&symhead, sym, entry);
7739 	return (0);
7740 }
7741 
7742 int
pfctl_cmdline_symset(char * s)7743 pfctl_cmdline_symset(char *s)
7744 {
7745 	char	*sym, *val;
7746 	int	 ret;
7747 
7748 	if ((val = strrchr(s, '=')) == NULL)
7749 		return (-1);
7750 
7751 	sym = strndup(s, val - s);
7752 	if (sym == NULL)
7753 		err(1, "%s: malloc", __func__);
7754 
7755 	ret = symset(sym, val + 1, 1);
7756 	free(sym);
7757 
7758 	return (ret);
7759 }
7760 
7761 char *
symget(const char * nam)7762 symget(const char *nam)
7763 {
7764 	struct sym	*sym;
7765 
7766 	TAILQ_FOREACH(sym, &symhead, entry) {
7767 		if (strcmp(nam, sym->nam) == 0) {
7768 			sym->used = 1;
7769 			return (sym->val);
7770 		}
7771 	}
7772 	return (NULL);
7773 }
7774 
7775 void
mv_rules(struct pfctl_ruleset * src,struct pfctl_ruleset * dst)7776 mv_rules(struct pfctl_ruleset *src, struct pfctl_ruleset *dst)
7777 {
7778 	int i;
7779 	struct pfctl_rule *r;
7780 
7781 	for (i = 0; i < PF_RULESET_MAX; ++i) {
7782 		TAILQ_FOREACH(r, src->rules[i].active.ptr, entries)
7783 			dst->anchor->match++;
7784 		TAILQ_CONCAT(dst->rules[i].active.ptr, src->rules[i].active.ptr, entries);
7785 		src->anchor->match = 0;
7786 		TAILQ_CONCAT(dst->rules[i].inactive.ptr, src->rules[i].inactive.ptr, entries);
7787 	}
7788 }
7789 
7790 void
mv_eth_rules(struct pfctl_eth_ruleset * src,struct pfctl_eth_ruleset * dst)7791 mv_eth_rules(struct pfctl_eth_ruleset *src, struct pfctl_eth_ruleset *dst)
7792 {
7793 	struct pfctl_eth_rule *r;
7794 
7795 	while ((r = TAILQ_FIRST(&src->rules)) != NULL) {
7796 		TAILQ_REMOVE(&src->rules, r, entries);
7797 		TAILQ_INSERT_TAIL(&dst->rules, r, entries);
7798 		dst->anchor->match++;
7799 	}
7800 	src->anchor->match = 0;
7801 }
7802 
7803 void
mv_tables(struct pfctl * pf,struct pfr_ktablehead * ktables,struct pfctl_anchor * a,struct pfctl_anchor * alast)7804 mv_tables(struct pfctl *pf, struct pfr_ktablehead *ktables,
7805     struct pfctl_anchor *a, struct pfctl_anchor *alast)
7806 {
7807 	struct pfr_ktable *kt, *kt_safe;
7808 	char new_path[PF_ANCHOR_MAXPATH];
7809 	char *path_cut;
7810 	int sz;
7811 	struct pfr_uktable *ukt;
7812 	SLIST_HEAD(, pfr_uktable) ukt_list;
7813 
7814 	/*
7815 	 * Here we need to rename anchor path from temporal names such as
7816 	 * _1/_2/foo to _1/bar/foo etc.
7817 	 *
7818 	 * This also means we need to remove and insert table to ktables
7819 	 * tree as anchor path is being updated.
7820 	 */
7821 	SLIST_INIT(&ukt_list);
7822 	DBGPRINT("%s [ %s ] (%s)\n", __func__, a->path, alast->path);
7823 	RB_FOREACH_SAFE(kt, pfr_ktablehead, ktables, kt_safe) {
7824 		path_cut = strstr(kt->pfrkt_anchor, alast->path);
7825 		if (path_cut != NULL) {
7826 			path_cut += strlen(alast->path);
7827 			if (*path_cut)
7828 				sz = snprintf(new_path, sizeof (new_path),
7829 				    "%s%s", a->path, path_cut);
7830 			else
7831 				sz = snprintf(new_path, sizeof (new_path),
7832 				    "%s", a->path);
7833 			if (sz >= sizeof (new_path))
7834 				errx(1, "new path is too long for %s@%s\n",
7835 				    kt->pfrkt_name, kt->pfrkt_anchor);
7836 
7837 			DBGPRINT("%s %s@%s -> %s@%s\n", __func__,
7838 			    kt->pfrkt_name, kt->pfrkt_anchor,
7839 			    kt->pfrkt_name, new_path);
7840 			    RB_REMOVE(pfr_ktablehead, ktables, kt);
7841 			strlcpy(kt->pfrkt_anchor, new_path,
7842 			    sizeof(kt->pfrkt_anchor));
7843 			SLIST_INSERT_HEAD(&ukt_list, (struct pfr_uktable *)kt,
7844 			    pfrukt_entry);
7845 		}
7846 	}
7847 
7848 	while ((ukt = SLIST_FIRST(&ukt_list)) != NULL) {
7849 		SLIST_REMOVE_HEAD(&ukt_list, pfrukt_entry);
7850 		if (RB_INSERT(pfr_ktablehead, ktables,
7851 		    (struct pfr_ktable *)ukt) != NULL)
7852 			errx(1, "%s@%s exists already\n",
7853 			    ukt->pfrukt_name,
7854 			    ukt->pfrukt_anchor);
7855 	}
7856 }
7857 
7858 void
decide_address_family(struct node_host * n,sa_family_t * af)7859 decide_address_family(struct node_host *n, sa_family_t *af)
7860 {
7861 	if (*af != 0 || n == NULL)
7862 		return;
7863 	*af = n->af;
7864 	while ((n = n->next) != NULL) {
7865 		if (n->af != *af) {
7866 			*af = 0;
7867 			return;
7868 		}
7869 	}
7870 }
7871 
7872 void
remove_invalid_hosts(struct node_host ** nh,sa_family_t * af)7873 remove_invalid_hosts(struct node_host **nh, sa_family_t *af)
7874 {
7875 	struct node_host	*n = *nh, *prev = NULL;
7876 
7877 	while (n != NULL) {
7878 		if (*af && n->af && n->af != *af) {
7879 			/* unlink and free n */
7880 			struct node_host *next = n->next;
7881 
7882 			/* adjust tail pointer */
7883 			if (n == (*nh)->tail)
7884 				(*nh)->tail = prev;
7885 			/* adjust previous node's next pointer */
7886 			if (prev == NULL)
7887 				*nh = next;
7888 			else
7889 				prev->next = next;
7890 			/* free node */
7891 			if (n->ifname != NULL)
7892 				free(n->ifname);
7893 			free(n);
7894 			n = next;
7895 		} else {
7896 			if (n->af && !*af)
7897 				*af = n->af;
7898 			prev = n;
7899 			n = n->next;
7900 		}
7901 	}
7902 }
7903 
7904 int
invalid_redirect(struct node_host * nh,sa_family_t af)7905 invalid_redirect(struct node_host *nh, sa_family_t af)
7906 {
7907 	if (!af) {
7908 		struct node_host *n;
7909 
7910 		/* tables and dyniftl are ok without an address family */
7911 		for (n = nh; n != NULL; n = n->next) {
7912 			if (n->addr.type != PF_ADDR_TABLE &&
7913 			    n->addr.type != PF_ADDR_DYNIFTL) {
7914 				yyerror("address family not given and "
7915 				    "translation address expands to multiple "
7916 				    "address families");
7917 				return (1);
7918 			}
7919 		}
7920 	}
7921 	if (nh == NULL) {
7922 		yyerror("no translation address with matching address family "
7923 		    "found.");
7924 		return (1);
7925 	}
7926 	return (0);
7927 }
7928 
7929 int
atoul(char * s,u_long * ulvalp)7930 atoul(char *s, u_long *ulvalp)
7931 {
7932 	u_long	 ulval;
7933 	char	*ep;
7934 
7935 	errno = 0;
7936 	ulval = strtoul(s, &ep, 0);
7937 	if (s[0] == '\0' || *ep != '\0')
7938 		return (-1);
7939 	if (errno == ERANGE && ulval == ULONG_MAX)
7940 		return (-1);
7941 	*ulvalp = ulval;
7942 	return (0);
7943 }
7944 
7945 int
getservice(char * n)7946 getservice(char *n)
7947 {
7948 	struct servent	*s;
7949 	u_long		 ulval;
7950 
7951 	if (atoul(n, &ulval) == 0) {
7952 		if (ulval > 65535) {
7953 			yyerror("illegal port value %lu", ulval);
7954 			return (-1);
7955 		}
7956 		return (htons(ulval));
7957 	} else {
7958 		s = getservbyname(n, "tcp");
7959 		if (s == NULL)
7960 			s = getservbyname(n, "udp");
7961 		if (s == NULL)
7962 			s = getservbyname(n, "sctp");
7963 		if (s == NULL) {
7964 			yyerror("unknown port %s", n);
7965 			return (-1);
7966 		}
7967 		return (s->s_port);
7968 	}
7969 }
7970 
7971 int
rule_label(struct pfctl_rule * r,char * s[PF_RULE_MAX_LABEL_COUNT])7972 rule_label(struct pfctl_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT])
7973 {
7974 	for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
7975 		if (s[i] == NULL)
7976 			return (0);
7977 
7978 		if (strlcpy(r->label[i], s[i], sizeof(r->label[0])) >=
7979 		    sizeof(r->label[0])) {
7980 			yyerror("rule label too long (max %d chars)",
7981 			    sizeof(r->label[0])-1);
7982 			return (-1);
7983 		}
7984 	}
7985 	return (0);
7986 }
7987 
7988 int
eth_rule_label(struct pfctl_eth_rule * r,char * s[PF_RULE_MAX_LABEL_COUNT])7989 eth_rule_label(struct pfctl_eth_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT])
7990 {
7991 	for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
7992 		if (s[i] == NULL)
7993 			return (0);
7994 
7995 		if (strlcpy(r->label[i], s[i], sizeof(r->label[0])) >=
7996 		    sizeof(r->label[0])) {
7997 			yyerror("rule label too long (max %d chars)",
7998 			    sizeof(r->label[0])-1);
7999 			return (-1);
8000 		}
8001 	}
8002 	return (0);
8003 }
8004 
8005 u_int16_t
parseicmpspec(char * w,sa_family_t af)8006 parseicmpspec(char *w, sa_family_t af)
8007 {
8008 	const struct icmpcodeent	*p;
8009 	u_long				 ulval;
8010 	u_int8_t			 icmptype;
8011 
8012 	if (af == AF_INET)
8013 		icmptype = returnicmpdefault >> 8;
8014 	else
8015 		icmptype = returnicmp6default >> 8;
8016 
8017 	if (atoul(w, &ulval) == -1) {
8018 		if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
8019 			yyerror("unknown icmp code %s", w);
8020 			return (0);
8021 		}
8022 		ulval = p->code;
8023 	}
8024 	if (ulval > 255) {
8025 		yyerror("invalid icmp code %lu", ulval);
8026 		return (0);
8027 	}
8028 	return (icmptype << 8 | ulval);
8029 }
8030 
8031 int
parseport(char * port,struct range * r,int extensions)8032 parseport(char *port, struct range *r, int extensions)
8033 {
8034 	char	*p = strchr(port, ':');
8035 
8036 	if (p == NULL) {
8037 		if ((r->a = getservice(port)) == -1)
8038 			return (-1);
8039 		r->b = 0;
8040 		r->t = PF_OP_NONE;
8041 		return (0);
8042 	}
8043 	if ((extensions & PPORT_STAR) && !strcmp(p+1, "*")) {
8044 		*p = 0;
8045 		if ((r->a = getservice(port)) == -1)
8046 			return (-1);
8047 		r->b = 0;
8048 		r->t = PF_OP_IRG;
8049 		return (0);
8050 	}
8051 	if ((extensions & PPORT_RANGE)) {
8052 		*p++ = 0;
8053 		if ((r->a = getservice(port)) == -1 ||
8054 		    (r->b = getservice(p)) == -1)
8055 			return (-1);
8056 		if (r->a == r->b) {
8057 			r->b = 0;
8058 			r->t = PF_OP_NONE;
8059 		} else
8060 			r->t = PF_OP_RRG;
8061 		return (0);
8062 	}
8063 	return (-1);
8064 }
8065 
8066 int
pfctl_load_anchors(int dev,struct pfctl * pf)8067 pfctl_load_anchors(int dev, struct pfctl *pf)
8068 {
8069 	struct loadanchors	*la;
8070 
8071 	TAILQ_FOREACH(la, &loadanchorshead, entries) {
8072 		if (pf->opts & PF_OPT_VERBOSE)
8073 			fprintf(stderr, "\nLoading anchor %s from %s\n",
8074 			    la->anchorname, la->filename);
8075 		if (pfctl_rules(dev, la->filename, pf->opts, pf->optimize,
8076 		    la->anchorname, pf->trans) == -1)
8077 			return (-1);
8078 	}
8079 
8080 	return (0);
8081 }
8082 
8083 int
kw_casecmp(const void * k,const void * e)8084 kw_casecmp(const void *k, const void *e)
8085 {
8086 	return (strcasecmp(k, ((const struct keywords *)e)->k_name));
8087 }
8088 
8089 int
map_tos(char * s,int * val)8090 map_tos(char *s, int *val)
8091 {
8092 	/* DiffServ Codepoints and other TOS mappings */
8093 	const struct keywords	 toswords[] = {
8094 		{ "af11",		IPTOS_DSCP_AF11 },
8095 		{ "af12",		IPTOS_DSCP_AF12 },
8096 		{ "af13",		IPTOS_DSCP_AF13 },
8097 		{ "af21",		IPTOS_DSCP_AF21 },
8098 		{ "af22",		IPTOS_DSCP_AF22 },
8099 		{ "af23",		IPTOS_DSCP_AF23 },
8100 		{ "af31",		IPTOS_DSCP_AF31 },
8101 		{ "af32",		IPTOS_DSCP_AF32 },
8102 		{ "af33",		IPTOS_DSCP_AF33 },
8103 		{ "af41",		IPTOS_DSCP_AF41 },
8104 		{ "af42",		IPTOS_DSCP_AF42 },
8105 		{ "af43",		IPTOS_DSCP_AF43 },
8106 		{ "critical",		IPTOS_PREC_CRITIC_ECP },
8107 		{ "cs0",		IPTOS_DSCP_CS0 },
8108 		{ "cs1",		IPTOS_DSCP_CS1 },
8109 		{ "cs2",		IPTOS_DSCP_CS2 },
8110 		{ "cs3",		IPTOS_DSCP_CS3 },
8111 		{ "cs4",		IPTOS_DSCP_CS4 },
8112 		{ "cs5",		IPTOS_DSCP_CS5 },
8113 		{ "cs6",		IPTOS_DSCP_CS6 },
8114 		{ "cs7",		IPTOS_DSCP_CS7 },
8115 		{ "ef",			IPTOS_DSCP_EF },
8116 		{ "inetcontrol",	IPTOS_PREC_INTERNETCONTROL },
8117 		{ "lowdelay",		IPTOS_LOWDELAY },
8118 		{ "netcontrol",		IPTOS_PREC_NETCONTROL },
8119 		{ "reliability",	IPTOS_RELIABILITY },
8120 		{ "throughput",		IPTOS_THROUGHPUT },
8121 		{ "va",			IPTOS_DSCP_VA }
8122 	};
8123 	const struct keywords	*p;
8124 
8125 	p = bsearch(s, toswords, sizeof(toswords)/sizeof(toswords[0]),
8126 	    sizeof(toswords[0]), kw_casecmp);
8127 
8128 	if (p) {
8129 		*val = p->k_val;
8130 		return (1);
8131 	}
8132 	return (0);
8133 }
8134 
8135 int
rt_tableid_max(void)8136 rt_tableid_max(void)
8137 {
8138 #ifdef __FreeBSD__
8139 	int fibs;
8140 	size_t l = sizeof(fibs);
8141 
8142         if (sysctlbyname("net.fibs", &fibs, &l, NULL, 0) == -1)
8143 		fibs = 16;	/* XXX RT_MAXFIBS, at least limit it some. */
8144 	/*
8145 	 * As the OpenBSD code only compares > and not >= we need to adjust
8146 	 * here given we only accept values of 0..n and want to avoid #ifdefs
8147 	 * in the grammar.
8148 	 */
8149 	return (fibs - 1);
8150 #else
8151 	return (RT_TABLEID_MAX);
8152 #endif
8153 }
8154 
8155 struct node_mac*
node_mac_from_string(const char * str)8156 node_mac_from_string(const char *str)
8157 {
8158 	struct node_mac *m;
8159 
8160 	m = calloc(1, sizeof(struct node_mac));
8161 	if (m == NULL)
8162 		err(1, "%s: calloc", __func__);
8163 
8164 	if (sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
8165 	    &m->mac[0], &m->mac[1], &m->mac[2], &m->mac[3], &m->mac[4],
8166 	    &m->mac[5]) != 6) {
8167 		free(m);
8168 		yyerror("invalid MAC address");
8169 		return (NULL);
8170 	}
8171 
8172 	memset(m->mask, 0xff, ETHER_ADDR_LEN);
8173 	m->isset = true;
8174 	m->next = NULL;
8175 	m->tail = m;
8176 
8177 	return (m);
8178 }
8179 
8180 struct node_mac*
node_mac_from_string_masklen(const char * str,int masklen)8181 node_mac_from_string_masklen(const char *str, int masklen)
8182 {
8183 	struct node_mac *m;
8184 
8185 	if (masklen < 0 || masklen > (ETHER_ADDR_LEN * 8)) {
8186 		yyerror("invalid MAC mask length");
8187 		return (NULL);
8188 	}
8189 
8190 	m = node_mac_from_string(str);
8191 	if (m == NULL)
8192 		return (NULL);
8193 
8194 	memset(m->mask, 0, ETHER_ADDR_LEN);
8195 	for (int i = 0; i < masklen; i++)
8196 		m->mask[i / 8] |= 1 << (i % 8);
8197 
8198 	return (m);
8199 }
8200 
8201 struct node_mac*
node_mac_from_string_mask(const char * str,const char * mask)8202 node_mac_from_string_mask(const char *str, const char *mask)
8203 {
8204 	struct node_mac *m;
8205 
8206 	m = node_mac_from_string(str);
8207 	if (m == NULL)
8208 		return (NULL);
8209 
8210 	if (sscanf(mask, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
8211 	    &m->mask[0], &m->mask[1], &m->mask[2], &m->mask[3], &m->mask[4],
8212 	    &m->mask[5]) != 6) {
8213 		free(m);
8214 		yyerror("invalid MAC mask");
8215 		return (NULL);
8216 	}
8217 
8218 	return (m);
8219 }
8220 
8221 int
filteropts_to_rule(struct pfctl_rule * r,struct filter_opts * opts)8222 filteropts_to_rule(struct pfctl_rule *r, struct filter_opts *opts)
8223 {
8224 	if (opts->marker & FOM_ONCE) {
8225 		if ((r->action != PF_PASS && r->action != PF_DROP) || r->anchor) {
8226 			yyerror("'once' only applies to pass/block rules");
8227 			return (1);
8228 		}
8229 		r->rule_flag |= PFRULE_ONCE;
8230 	}
8231 
8232 	if (opts->statelim.id != PF_STATELIM_ID_NONE && r->action != PF_PASS) {
8233 		yyerror("state limiter only applies to pass rules");
8234 		return (1);
8235 	}
8236 	if (opts->sourcelim.id != PF_SOURCELIM_ID_NONE && r->action != PF_PASS) {
8237 		yyerror("source limiter only applies to pass rules");
8238 		return (1);
8239 	}
8240 
8241 	r->keep_state = opts->keep.action;
8242 	r->pktrate.limit = opts->pktrate.limit;
8243 	r->pktrate.seconds = opts->pktrate.seconds;
8244 	r->prob = opts->prob;
8245 	r->statelim.id = opts->statelim.id;
8246 	r->statelim.limiter_action = opts->statelim.limiter_action;
8247 	r->sourcelim.id = opts->sourcelim.id;
8248 	r->sourcelim.limiter_action = opts->sourcelim.limiter_action;
8249 	r->rtableid = opts->rtableid;
8250 	r->ridentifier = opts->ridentifier;
8251 	r->max_pkt_size = opts->max_pkt_size;
8252 	r->tos = opts->tos;
8253 
8254 	if (opts->nodf)
8255 		r->scrub_flags |= PFSTATE_NODF;
8256 	if (opts->randomid)
8257 		r->scrub_flags |= PFSTATE_RANDOMID;
8258 	if (opts->minttl)
8259 		r->min_ttl = opts->minttl;
8260 	if (opts->max_mss)
8261 		r->max_mss = opts->max_mss;
8262 
8263 	if (opts->tag)
8264 		if (strlcpy(r->tagname, opts->tag,
8265 		    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
8266 			yyerror("tag too long, max %u chars",
8267 			    PF_TAG_NAME_SIZE - 1);
8268 			return (1);
8269 		}
8270 	if (opts->match_tag)
8271 		if (strlcpy(r->match_tagname, opts->match_tag,
8272 		    PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
8273 			yyerror("tag too long, max %u chars",
8274 			    PF_TAG_NAME_SIZE - 1);
8275 			return (1);
8276 		}
8277 	r->match_tag_not = opts->match_tag_not;
8278 
8279 	if (rule_label(r, opts->label))
8280 		return (1);
8281 	for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
8282 		free(opts->label[i]);
8283 
8284 	if (opts->marker & FOM_AFTO)
8285 		r->rule_flag |= PFRULE_AFTO;
8286 	if (opts->marker & FOM_SCRUB_TCP)
8287 		r->scrub_flags |= PFSTATE_SCRUB_TCP;
8288 	if (opts->marker & FOM_PRIO)
8289 		r->prio = opts->prio ? opts->prio : PF_PRIO_ZERO;
8290 	if (opts->marker & FOM_SETPRIO) {
8291 		r->set_prio[0] = opts->set_prio[0];
8292 		r->set_prio[1] = opts->set_prio[1];
8293 		r->scrub_flags |= PFSTATE_SETPRIO;
8294 	}
8295 	if (opts->marker & FOM_SETTOS) {
8296 		r->scrub_flags |= PFSTATE_SETTOS;
8297 		r->set_tos = opts->settos;
8298 	}
8299 
8300 	r->flags = opts->flags.b1;
8301 	r->flagset = opts->flags.b2;
8302 	if ((opts->flags.b1 & opts->flags.b2) != opts->flags.b1) {
8303 		yyerror("flags always false");
8304 		return (1);
8305 	}
8306 
8307 	if (opts->queues.qname != NULL) {
8308 		if (strlcpy(r->qname, opts->queues.qname,
8309 		    sizeof(r->qname)) >= sizeof(r->qname)) {
8310 			yyerror("rule qname too long (max "
8311 			    "%d chars)", sizeof(r->qname)-1);
8312 			return (1);
8313 		}
8314 		free(opts->queues.qname);
8315 	}
8316 	if (opts->queues.pqname != NULL) {
8317 		if (strlcpy(r->pqname, opts->queues.pqname,
8318 		    sizeof(r->pqname)) >= sizeof(r->pqname)) {
8319 			yyerror("rule pqname too long (max "
8320 			    "%d chars)", sizeof(r->pqname)-1);
8321 			return (1);
8322 		}
8323 		free(opts->queues.pqname);
8324 	}
8325 
8326 	if (opts->fragment)
8327 		r->rule_flag |= PFRULE_FRAGMENT;
8328 	r->allow_opts = opts->allowopts;
8329 
8330 	return (0);
8331 }
8332 
8333 static bool
pfctl_setup_anchor(struct pfctl_rule * r,struct pfctl * pf,char * anchorname)8334 pfctl_setup_anchor(struct pfctl_rule *r, struct pfctl *pf, char *anchorname)
8335 {
8336 	char	*p;
8337 
8338 	if (pf->astack[pf->asd + 1]) {
8339 		if (anchorname && strchr(anchorname, '/') != NULL) {
8340 			free(anchorname);
8341 			yyerror("anchor paths containing '/' "
8342 			   "cannot be used for inline anchors.");
8343 			return (false);
8344 		}
8345 
8346 		/* Move inline rules into relative location. */
8347 		pfctl_anchor_setup(r,
8348 		    &pf->astack[pf->asd]->ruleset,
8349 		    anchorname ? anchorname : pf->alast->name);
8350 
8351 		if (r->anchor == NULL)
8352 			err(1, "anchorrule: unable to "
8353 			    "create ruleset");
8354 
8355 		if (pf->alast != r->anchor) {
8356 			if (r->anchor->match) {
8357 				yyerror("inline anchor '%s' "
8358 				    "already exists",
8359 				    r->anchor->name);
8360 				return (false);
8361 			}
8362 			mv_rules(&pf->alast->ruleset,
8363 			    &r->anchor->ruleset);
8364 			mv_tables(pf, &pfr_ktables, r->anchor, pf->alast);
8365 		}
8366 		pf_remove_if_empty_ruleset(&pf->alast->ruleset);
8367 		pf->alast = r->anchor;
8368 	} else {
8369 		if (! anchorname) {
8370 			yyerror("anchors without explicit "
8371 			    "rules must specify a name");
8372 			return (false);
8373 		}
8374 		/*
8375 		 * Don't make non-brace anchors part of the main anchor pool.
8376 		 */
8377 		if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) {
8378 			err(1, "anchorrule: calloc");
8379 		}
8380 		pf_init_ruleset(&r->anchor->ruleset);
8381 		r->anchor->ruleset.anchor = r->anchor;
8382 		if (strlcpy(r->anchor->path, anchorname,
8383 		    sizeof(r->anchor->path)) >= sizeof(r->anchor->path)) {
8384 			errx(1, "anchorrule: strlcpy");
8385 		}
8386 		if ((p = strrchr(anchorname, '/')) != NULL) {
8387 			if (strlen(p) == 1) {
8388 				yyerror("anchorrule: bad anchor name %s",
8389 				    anchorname);
8390 				return (false);
8391 			}
8392 		} else
8393 			p = anchorname;
8394 		if (strlcpy(r->anchor->name, p,
8395 		    sizeof(r->anchor->name)) >= sizeof(r->anchor->name)) {
8396 			errx(1, "anchorrule: strlcpy");
8397 		}
8398 	}
8399 
8400 	return (true);
8401 }
8402