parse.y revision 127082
152845Sphk/*	$OpenBSD: parse.y,v 1.415 2003/09/01 15:07:40 henning Exp $	*/
252845Sphk
352845Sphk/*
452845Sphk * Copyright (c) 2001 Markus Friedl.  All rights reserved.
552845Sphk * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
652845Sphk *
752845Sphk * Redistribution and use in source and binary forms, with or without
852845Sphk * modification, are permitted provided that the following conditions
952845Sphk * are met:
1052845Sphk * 1. Redistributions of source code must retain the above copyright
1152845Sphk *    notice, this list of conditions and the following disclaimer.
1252845Sphk * 2. Redistributions in binary form must reproduce the above copyright
1352845Sphk *    notice, this list of conditions and the following disclaimer in the
1452845Sphk *    documentation and/or other materials provided with the distribution.
1552845Sphk *
1652845Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1752845Sphk * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1852845Sphk * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1952845Sphk * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2052845Sphk * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2152845Sphk * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2252845Sphk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2352845Sphk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2452845Sphk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2552845Sphk * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2652845Sphk */
2752845Sphk%{
2852845Sphk#include <sys/cdefs.h>
2952845Sphk__FBSDID("$FreeBSD: head/contrib/pf/pfctl/parse.y 127082 2004-03-16 17:24:06Z obrien $");
3052845Sphk
3152845Sphk#include <sys/types.h>
3252845Sphk#include <sys/socket.h>
3352845Sphk#include <net/if.h>
3452845Sphk#include <netinet/in.h>
3552845Sphk#include <netinet/in_systm.h>
3652845Sphk#include <netinet/ip.h>
3752845Sphk#include <netinet/ip_icmp.h>
3852845Sphk#include <netinet/icmp6.h>
3952845Sphk#include <net/pfvar.h>
4052845Sphk#include <arpa/inet.h>
4152845Sphk#include <altq/altq.h>
4252845Sphk#include <altq/altq_cbq.h>
4352845Sphk#include <altq/altq_priq.h>
4452845Sphk#include <altq/altq_hfsc.h>
4552845Sphk
4652845Sphk#include <stdio.h>
4752845Sphk#include <stdlib.h>
4852845Sphk#include <netdb.h>
4952845Sphk#include <stdarg.h>
5052845Sphk#include <errno.h>
5153648Sarchie#include <string.h>
5252845Sphk#include <ctype.h>
5352845Sphk#include <err.h>
5452845Sphk#include <limits.h>
5552845Sphk#include <pwd.h>
5652845Sphk#include <grp.h>
5752845Sphk#include <md5.h>
5852845Sphk
5952845Sphk#include "pfctl_parser.h"
6052845Sphk#include "pfctl.h"
6152845Sphk
6252845Sphk#ifdef __FreeBSD__
6352845Sphk#define	HTONL(x)	(x) = htonl((__uint32_t)(x))
6452845Sphk#endif
6552845Sphk
6652845Sphkstatic struct pfctl	*pf = NULL;
6752845Sphkstatic FILE		*fin = NULL;
6852845Sphkstatic int		 debug = 0;
6952845Sphkstatic int		 lineno = 1;
7052845Sphkstatic int		 errors = 0;
7152845Sphkstatic int		 rulestate = 0;
7252845Sphkstatic u_int16_t	 returnicmpdefault =
7352845Sphk			    (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
7452845Sphkstatic u_int16_t	 returnicmp6default =
7552845Sphk			    (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
7652845Sphkstatic int		 blockpolicy = PFRULE_DROP;
7752845Sphkstatic int		 require_order = 1;
7852845Sphk
7952845Sphkenum {
8052845Sphk	PFCTL_STATE_NONE,
8152845Sphk	PFCTL_STATE_OPTION,
8252845Sphk	PFCTL_STATE_SCRUB,
8352845Sphk	PFCTL_STATE_QUEUE,
8452845Sphk	PFCTL_STATE_NAT,
8552845Sphk	PFCTL_STATE_FILTER
8652845Sphk};
8752845Sphk
8852845Sphkstruct node_proto {
8952845Sphk	u_int8_t		 proto;
9052845Sphk	struct node_proto	*next;
9152845Sphk	struct node_proto	*tail;
9252845Sphk};
9352845Sphk
9452845Sphkstruct node_port {
9552845Sphk	u_int16_t		 port[2];
9652845Sphk	u_int8_t		 op;
9752845Sphk	struct node_port	*next;
9852845Sphk	struct node_port	*tail;
9952845Sphk};
10052845Sphk
10152845Sphkstruct node_uid {
10252845Sphk	uid_t			 uid[2];
10352845Sphk	u_int8_t		 op;
10452845Sphk	struct node_uid		*next;
10552845Sphk	struct node_uid		*tail;
10652845Sphk};
10752845Sphk
10852845Sphkstruct node_gid {
10952845Sphk	gid_t			 gid[2];
11052845Sphk	u_int8_t		 op;
11152845Sphk	struct node_gid		*next;
11252845Sphk	struct node_gid		*tail;
11352845Sphk};
11452845Sphk
11552845Sphkstruct node_icmp {
11652845Sphk	u_int8_t		 code;
11752845Sphk	u_int8_t		 type;
11852845Sphk	u_int8_t		 proto;
11952845Sphk	struct node_icmp	*next;
12052845Sphk	struct node_icmp	*tail;
12152845Sphk};
12252845Sphk
12352845Sphkenum	{ PF_STATE_OPT_MAX=0, PF_STATE_OPT_TIMEOUT=1 };
12452845Sphkstruct node_state_opt {
12552845Sphk	int			 type;
12652845Sphk	union {
12752845Sphk		u_int32_t	 max_states;
12852845Sphk		struct {
12952845Sphk			int		number;
13052845Sphk			u_int32_t	seconds;
13153648Sarchie		}		 timeout;
13252845Sphk	}			 data;
13352845Sphk	struct node_state_opt	*next;
134	struct node_state_opt	*tail;
135};
136
137struct peer {
138	struct node_host	*host;
139	struct node_port	*port;
140};
141
142struct node_queue {
143	char			 queue[PF_QNAME_SIZE];
144	char			 parent[PF_QNAME_SIZE];
145	char			 ifname[IFNAMSIZ];
146	int			 scheduler;
147	struct node_queue	*next;
148	struct node_queue	*tail;
149}	*queues = NULL;
150
151struct node_qassign {
152	char		*qname;
153	char		*pqname;
154};
155
156struct filter_opts {
157	int			 marker;
158#define FOM_FLAGS	0x01
159#define FOM_ICMP	0x02
160#define FOM_TOS		0x04
161#define FOM_KEEP	0x08
162	struct node_uid		*uid;
163	struct node_gid		*gid;
164	struct {
165		u_int8_t	 b1;
166		u_int8_t	 b2;
167		u_int16_t	 w;
168		u_int16_t	 w2;
169	} flags;
170	struct node_icmp	*icmpspec;
171	u_int32_t		 tos;
172	struct {
173		int			 action;
174		struct node_state_opt	*options;
175	} keep;
176	int			 fragment;
177	int			 allowopts;
178	char			*label;
179	struct node_qassign	 queues;
180	char			*tag;
181	char			*match_tag;
182	u_int8_t		 match_tag_not;
183} filter_opts;
184
185struct antispoof_opts {
186	char			*label;
187} antispoof_opts;
188
189struct scrub_opts {
190	int			marker;
191#define SOM_MINTTL	0x01
192#define SOM_MAXMSS	0x02
193#define SOM_FRAGCACHE	0x04
194	int			nodf;
195	int			minttl;
196	int			maxmss;
197	int			fragcache;
198	int			randomid;
199	int			reassemble_tcp;
200} scrub_opts;
201
202struct queue_opts {
203	int			marker;
204#define QOM_BWSPEC	0x01
205#define QOM_SCHEDULER	0x02
206#define QOM_PRIORITY	0x04
207#define QOM_TBRSIZE	0x08
208#define QOM_QLIMIT	0x10
209	struct node_queue_bw	queue_bwspec;
210	struct node_queue_opt	scheduler;
211	int			priority;
212	int			tbrsize;
213	int			qlimit;
214} queue_opts;
215
216struct table_opts {
217	int			flags;
218	int			init_addr;
219	struct node_tinithead	init_nodes;
220} table_opts;
221
222struct node_hfsc_opts	hfsc_opts;
223
224int	yyerror(const char *, ...);
225int	disallow_table(struct node_host *, const char *);
226int	rule_consistent(struct pf_rule *);
227int	filter_consistent(struct pf_rule *);
228int	nat_consistent(struct pf_rule *);
229int	rdr_consistent(struct pf_rule *);
230int	process_tabledef(char *, struct table_opts *);
231int	yyparse(void);
232void	expand_label_str(char *, const char *, const char *);
233void	expand_label_if(const char *, char *, const char *);
234void	expand_label_addr(const char *, char *, u_int8_t, struct node_host *);
235void	expand_label_port(const char *, char *, struct node_port *);
236void	expand_label_proto(const char *, char *, u_int8_t);
237void	expand_label_nr(const char *, char *);
238void	expand_label(char *, const char *, u_int8_t, struct node_host *,
239	    struct node_port *, struct node_host *, struct node_port *,
240	    u_int8_t);
241void	expand_rule(struct pf_rule *, struct node_if *, struct node_host *,
242	    struct node_proto *, struct node_os*, struct node_host *,
243	    struct node_port *, struct node_host *, struct node_port *,
244	    struct node_uid *, struct node_gid *, struct node_icmp *);
245int	expand_altq(struct pf_altq *, struct node_if *, struct node_queue *,
246	    struct node_queue_bw bwspec, struct node_queue_opt *);
247int	expand_queue(struct pf_altq *, struct node_if *, struct node_queue *,
248	    struct node_queue_bw, struct node_queue_opt *);
249
250int	 check_rulestate(int);
251int	 kw_cmp(const void *, const void *);
252int	 lookup(char *);
253int	 lgetc(FILE *);
254int	 lungetc(int);
255int	 findeol(void);
256int	 yylex(void);
257int	 atoul(char *, u_long *);
258int	 getservice(char *);
259int	 rule_label(struct pf_rule *, char *);
260
261TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
262struct sym {
263	TAILQ_ENTRY(sym)	 entries;
264	int			 used;
265	int			 persist;
266	char			*nam;
267	char			*val;
268};
269
270
271int	 symset(const char *, const char *, int);
272char	*symget(const char *);
273
274void	 decide_address_family(struct node_host *, sa_family_t *);
275void	 remove_invalid_hosts(struct node_host **, sa_family_t *);
276int	 invalid_redirect(struct node_host *, sa_family_t);
277u_int16_t parseicmpspec(char *, sa_family_t);
278
279TAILQ_HEAD(loadanchorshead, loadanchors)	 loadanchorshead =
280   TAILQ_HEAD_INITIALIZER(loadanchorshead);
281struct loadanchors {
282	TAILQ_ENTRY(loadanchors)	 entries;
283	char				*anchorname;
284	char				*rulesetname;
285	char				*filename;
286};
287
288typedef struct {
289	union {
290		u_int32_t		 number;
291		int			 i;
292		char			*string;
293		struct {
294			u_int8_t	 b1;
295			u_int8_t	 b2;
296			u_int16_t	 w;
297			u_int16_t	 w2;
298		}			 b;
299		struct range {
300			int		 a;
301			int		 b;
302			int		 t;
303		}			 range;
304		struct node_if		*interface;
305		struct node_proto	*proto;
306		struct node_icmp	*icmp;
307		struct node_host	*host;
308		struct node_os		*os;
309		struct node_port	*port;
310		struct node_uid		*uid;
311		struct node_gid		*gid;
312		struct node_state_opt	*state_opt;
313		struct peer		 peer;
314		struct {
315			struct peer	 src, dst;
316			struct node_os	*src_os;
317		}			 fromto;
318		struct pf_poolhashkey	*hashkey;
319		struct {
320			struct node_host	*host;
321			u_int8_t		 rt;
322			u_int8_t		 pool_opts;
323			sa_family_t		 af;
324			struct pf_poolhashkey	*key;
325		}			 route;
326		struct redirection {
327			struct node_host	*host;
328			struct range		 rport;
329		}			*redirection;
330		struct {
331			int			 type;
332			struct pf_poolhashkey	*key;
333		}			 pooltype;
334		struct {
335			int			 action;
336			struct node_state_opt	*options;
337		}			 keep_state;
338		struct {
339			u_int8_t	 log;
340			u_int8_t	 quick;
341		}			 logquick;
342		struct node_queue	*queue;
343		struct node_queue_opt	 queue_options;
344		struct node_queue_bw	 queue_bwspec;
345		struct node_qassign	 qassign;
346		struct filter_opts	 filter_opts;
347		struct antispoof_opts	 antispoof_opts;
348		struct queue_opts	 queue_opts;
349		struct scrub_opts	 scrub_opts;
350		struct table_opts	 table_opts;
351		struct node_hfsc_opts	 hfsc_opts;
352	} v;
353	int lineno;
354} YYSTYPE;
355
356#define PREPARE_ANCHOR_RULE(r, a)				\
357	do {							\
358		memset(&(r), 0, sizeof(r));			\
359		if (strlcpy(r.anchorname, (a),			\
360		    sizeof(r.anchorname)) >=			\
361		    sizeof(r.anchorname)) {			\
362			yyerror("anchor name '%s' too long",	\
363			    (a));				\
364			YYERROR;				\
365		}						\
366	} while (0)
367
368%}
369
370%token	PASS BLOCK SCRUB RETURN IN OS OUT LOG LOGALL QUICK ON FROM TO FLAGS
371%token	RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
372%token	ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
373%token	MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
374%token	NOROUTE FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
375%token	REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
376%token	SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
377%token	REQUIREORDER SYNPROXY FINGERPRINTS
378%token	ANTISPOOF FOR
379%token	BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT
380%token	ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
381%token	QUEUE PRIORITY QLIMIT
382%token	LOAD
383%token	TAGGED TAG
384%token	<v.string>		STRING
385%token	<v.i>			PORTBINARY
386%type	<v.interface>		interface if_list if_item_not if_item
387%type	<v.number>		number icmptype icmp6type uid gid
388%type	<v.number>		tos not yesno natpass
389%type	<v.i>			no dir log af fragcache
390%type	<v.i>			staticport unaryop
391%type	<v.b>			action nataction flags flag blockspec
392%type	<v.range>		port rport
393%type	<v.hashkey>		hashkey
394%type	<v.pooltype>		pooltype
395%type	<v.proto>		proto proto_list proto_item
396%type	<v.icmp>		icmpspec
397%type	<v.icmp>		icmp_list icmp_item
398%type	<v.icmp>		icmp6_list icmp6_item
399%type	<v.fromto>		fromto
400%type	<v.peer>		ipportspec from to
401%type	<v.host>		ipspec xhost host dynaddr host_list
402%type	<v.host>		redir_host_list redirspec
403%type	<v.host>		route_host route_host_list routespec
404%type	<v.os>			os xos os_list
405%type	<v.port>		portspec port_list port_item
406%type	<v.uid>			uids uid_list uid_item
407%type	<v.gid>			gids gid_list gid_item
408%type	<v.route>		route
409%type	<v.redirection>		redirection redirpool
410%type	<v.string>		label string tag
411%type	<v.keep_state>		keep
412%type	<v.state_opt>		state_opt_spec state_opt_list state_opt_item
413%type	<v.logquick>		logquick
414%type	<v.interface>		antispoof_ifspc antispoof_iflst
415%type	<v.qassign>		qname
416%type	<v.queue>		qassign qassign_list qassign_item
417%type	<v.queue_options>	scheduler
418%type	<v.number>		cbqflags_list cbqflags_item
419%type	<v.number>		priqflags_list priqflags_item
420%type	<v.hfsc_opts>		hfscopts_list hfscopts_item hfsc_opts
421%type	<v.queue_bwspec>	bandwidth
422%type	<v.filter_opts>		filter_opts filter_opt filter_opts_l
423%type	<v.antispoof_opts>	antispoof_opts antispoof_opt antispoof_opts_l
424%type	<v.queue_opts>		queue_opts queue_opt queue_opts_l
425%type	<v.scrub_opts>		scrub_opts scrub_opt scrub_opts_l
426%type	<v.table_opts>		table_opts table_opt table_opts_l
427%%
428
429ruleset		: /* empty */
430		| ruleset '\n'
431		| ruleset option '\n'
432		| ruleset scrubrule '\n'
433		| ruleset natrule '\n'
434		| ruleset binatrule '\n'
435		| ruleset pfrule '\n'
436		| ruleset anchorrule '\n'
437		| ruleset loadrule '\n'
438		| ruleset altqif '\n'
439		| ruleset queuespec '\n'
440		| ruleset varset '\n'
441		| ruleset antispoof '\n'
442		| ruleset tabledef '\n'
443		| ruleset error '\n'		{ errors++; }
444		;
445
446option		: SET OPTIMIZATION STRING		{
447			if (check_rulestate(PFCTL_STATE_OPTION))
448				YYERROR;
449			if (pfctl_set_optimization(pf, $3) != 0) {
450				yyerror("unknown optimization %s", $3);
451				YYERROR;
452			}
453		}
454		| SET TIMEOUT timeout_spec
455		| SET TIMEOUT '{' timeout_list '}'
456		| SET LIMIT limit_spec
457		| SET LIMIT '{' limit_list '}'
458		| SET LOGINTERFACE STRING		{
459			if (check_rulestate(PFCTL_STATE_OPTION))
460				YYERROR;
461			if ((ifa_exists($3) == NULL) && strcmp($3, "none")) {
462				yyerror("interface %s doesn't exist", $3);
463				YYERROR;
464			}
465			if (pfctl_set_logif(pf, $3) != 0) {
466				yyerror("error setting loginterface %s", $3);
467				YYERROR;
468			}
469		}
470		| SET BLOCKPOLICY DROP	{
471			if (pf->opts & PF_OPT_VERBOSE)
472				printf("set block-policy drop\n");
473			if (check_rulestate(PFCTL_STATE_OPTION))
474				YYERROR;
475			blockpolicy = PFRULE_DROP;
476		}
477		| SET BLOCKPOLICY RETURN {
478			if (pf->opts & PF_OPT_VERBOSE)
479				printf("set block-policy return\n");
480			if (check_rulestate(PFCTL_STATE_OPTION))
481				YYERROR;
482			blockpolicy = PFRULE_RETURN;
483		}
484		| SET REQUIREORDER yesno {
485			if (pf->opts & PF_OPT_VERBOSE)
486				printf("set require-order %s\n",
487				    $3 == 1 ? "yes" : "no");
488			require_order = $3;
489		}
490		| SET FINGERPRINTS STRING {
491			if (pf->opts & PF_OPT_VERBOSE)
492				printf("fingerprints %s\n", $3);
493			if (check_rulestate(PFCTL_STATE_OPTION))
494				YYERROR;
495			if (pfctl_file_fingerprints(pf->dev, pf->opts, $3)) {
496				yyerror("error loading fingerprints %s", $3);
497				YYERROR;
498			}
499		}
500		;
501
502string		: string STRING				{
503			if (asprintf(&$$, "%s %s", $1, $2) == -1)
504				err(1, "string: asprintf");
505			free($1);
506			free($2);
507		}
508		| STRING
509		;
510
511varset		: STRING '=' string		{
512			if (pf->opts & PF_OPT_VERBOSE)
513				printf("%s = \"%s\"\n", $1, $3);
514			if (symset($1, $3, 0) == -1)
515				err(1, "cannot store variable %s", $1);
516		}
517		;
518
519anchorrule	: ANCHOR string	dir interface af proto fromto {
520			struct pf_rule	r;
521
522			if (check_rulestate(PFCTL_STATE_FILTER))
523				YYERROR;
524
525			PREPARE_ANCHOR_RULE(r, $2);
526			r.direction = $3;
527			r.af = $5;
528
529			decide_address_family($7.src.host, &r.af);
530			decide_address_family($7.dst.host, &r.af);
531
532			expand_rule(&r, $4, NULL, $6, $7.src_os,
533			    $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
534			    0, 0, 0);
535		}
536		| NATANCHOR string interface af proto fromto {
537			struct pf_rule	r;
538
539			if (check_rulestate(PFCTL_STATE_NAT))
540				YYERROR;
541
542			PREPARE_ANCHOR_RULE(r, $2);
543			r.action = PF_NAT;
544			r.af = $4;
545
546			decide_address_family($6.src.host, &r.af);
547			decide_address_family($6.dst.host, &r.af);
548
549			expand_rule(&r, $3, NULL, $5, $6.src_os,
550			    $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
551			    0, 0, 0);
552		}
553		| RDRANCHOR string interface af proto fromto {
554			struct pf_rule	r;
555
556			if (check_rulestate(PFCTL_STATE_NAT))
557				YYERROR;
558
559			PREPARE_ANCHOR_RULE(r, $2);
560			r.action = PF_RDR;
561			r.af = $4;
562
563			decide_address_family($6.src.host, &r.af);
564			decide_address_family($6.dst.host, &r.af);
565
566			if ($6.src.port != NULL) {
567				yyerror("source port parameter not supported"
568				    " in rdr-anchor");
569				YYERROR;
570			}
571			if ($6.dst.port != NULL) {
572				if ($6.dst.port->next != NULL) {
573					yyerror("destination port list "
574					    "expansion not supported in "
575					    "rdr-anchor");
576					YYERROR;
577				} else if ($6.dst.port->op != PF_OP_EQ) {
578					yyerror("destination port operators"
579					    " not supported in rdr-anchor");
580					YYERROR;
581				}
582				r.dst.port[0] = $6.dst.port->port[0];
583				r.dst.port[1] = $6.dst.port->port[1];
584				r.dst.port_op = $6.dst.port->op;
585			}
586
587			expand_rule(&r, $3, NULL, $5, $6.src_os,
588			    $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
589			    0, 0, 0);
590		}
591		| BINATANCHOR string interface af proto fromto {
592			struct pf_rule	r;
593
594			if (check_rulestate(PFCTL_STATE_NAT))
595				YYERROR;
596
597			PREPARE_ANCHOR_RULE(r, $2);
598			r.action = PF_BINAT;
599			r.af = $4;
600			if ($5 != NULL) {
601				if ($5->next != NULL) {
602					yyerror("proto list expansion"
603					    " not supported in binat-anchor");
604					YYERROR;
605				}
606				r.proto = $5->proto;
607				free($5);
608			}
609
610			if ($6.src.host != NULL || $6.src.port != NULL ||
611			    $6.dst.host != NULL || $6.dst.port != NULL) {
612				yyerror("fromto parameter not supported"
613				    " in binat-anchor");
614				YYERROR;
615			}
616
617			decide_address_family($6.src.host, &r.af);
618			decide_address_family($6.dst.host, &r.af);
619
620			pfctl_add_rule(pf, &r);
621		}
622		;
623
624loadrule	: LOAD ANCHOR string FROM string	{
625			char			*t;
626			struct loadanchors	*loadanchor;
627
628			t = strsep(&$3, ":");
629			if (*t == '\0' || *$3 == '\0') {
630				yyerror("anchor '%s' invalid\n", $3);
631				YYERROR;
632			}
633			if (strlen(t) >= PF_ANCHOR_NAME_SIZE) {
634				yyerror("anchorname %s too long, max %u\n",
635				    t, PF_ANCHOR_NAME_SIZE - 1);
636				YYERROR;
637			}
638			if (strlen($3) >= PF_RULESET_NAME_SIZE) {
639				yyerror("rulesetname %s too long, max %u\n",
640				    $3, PF_RULESET_NAME_SIZE - 1);
641				YYERROR;
642			}
643
644			loadanchor = calloc(1, sizeof(struct loadanchors));
645			if (loadanchor == NULL)
646				err(1, "loadrule: calloc");
647			if ((loadanchor->anchorname = strdup(t)) == NULL)
648				err(1, "loadrule: strdup");
649			if ((loadanchor->rulesetname = strdup($3)) == NULL)
650				err(1, "loadrule: strdup");
651			if ((loadanchor->filename = strdup($5)) == NULL)
652				err(1, "loadrule: strdup");
653
654			TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor,
655			    entries);
656
657			free(t); /* not $3 */
658			free($5);
659		};
660
661scrubrule	: SCRUB dir logquick interface af proto fromto scrub_opts
662		{
663			struct pf_rule	r;
664
665			if (check_rulestate(PFCTL_STATE_SCRUB))
666				YYERROR;
667
668			memset(&r, 0, sizeof(r));
669
670			r.action = PF_SCRUB;
671			r.direction = $2;
672
673			r.log = $3.log;
674			if ($3.quick) {
675				yyerror("scrub rules do not support 'quick'");
676				YYERROR;
677			}
678
679			if ($4) {
680				if ($4->not) {
681					yyerror("scrub rules do not support "
682					    "'! <if>'");
683					YYERROR;
684				}
685			}
686			r.af = $5;
687			if ($8.nodf)
688				r.rule_flag |= PFRULE_NODF;
689			if ($8.randomid)
690				r.rule_flag |= PFRULE_RANDOMID;
691			if ($8.reassemble_tcp) {
692				if (r.direction != PF_INOUT) {
693					yyerror("reassemble tcp rules can not "
694					    "specify direction");
695					YYERROR;
696				}
697				r.rule_flag |= PFRULE_REASSEMBLE_TCP;
698			}
699			if ($8.minttl)
700				r.min_ttl = $8.minttl;
701			if ($8.maxmss)
702				r.max_mss = $8.maxmss;
703			if ($8.fragcache)
704				r.rule_flag |= $8.fragcache;
705
706			expand_rule(&r, $4, NULL, $6, $7.src_os,
707			    $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
708			    NULL, NULL, NULL);
709		}
710		;
711
712scrub_opts	:	{
713			bzero(&scrub_opts, sizeof scrub_opts);
714		}
715		  scrub_opts_l
716			{ $$ = scrub_opts; }
717		| /* empty */ {
718			bzero(&scrub_opts, sizeof scrub_opts);
719			$$ = scrub_opts;
720		}
721		;
722
723scrub_opts_l	: scrub_opts_l scrub_opt
724		| scrub_opt
725		;
726
727scrub_opt	: NODF	{
728			if (scrub_opts.nodf) {
729				yyerror("no-df cannot be respecified");
730				YYERROR;
731			}
732			scrub_opts.nodf = 1;
733		}
734		| MINTTL number {
735			if (scrub_opts.marker & SOM_MINTTL) {
736				yyerror("min-ttl cannot be respecified");
737				YYERROR;
738			}
739			if ($2 > 255) {
740				yyerror("illegal min-ttl value %d", $2);
741				YYERROR;
742			}
743			scrub_opts.marker |= SOM_MINTTL;
744			scrub_opts.minttl = $2;
745		}
746		| MAXMSS number {
747			if (scrub_opts.marker & SOM_MAXMSS) {
748				yyerror("max-mss cannot be respecified");
749				YYERROR;
750			}
751			if ($2 > 65535) {
752				yyerror("illegal max-mss value %d", $2);
753				YYERROR;
754			}
755			scrub_opts.marker |= SOM_MAXMSS;
756			scrub_opts.maxmss = $2;
757		}
758		| fragcache {
759			if (scrub_opts.marker & SOM_FRAGCACHE) {
760				yyerror("fragcache cannot be respecified");
761				YYERROR;
762			}
763			scrub_opts.marker |= SOM_FRAGCACHE;
764			scrub_opts.fragcache = $1;
765		}
766		| REASSEMBLE STRING {
767			if (strcasecmp($2, "tcp") != 0)
768				YYERROR;
769			if (scrub_opts.reassemble_tcp) {
770				yyerror("reassemble tcp cannot be respecified");
771				YYERROR;
772			}
773			scrub_opts.reassemble_tcp = 1;
774		}
775		| RANDOMID {
776			if (scrub_opts.randomid) {
777				yyerror("random-id cannot be respecified");
778				YYERROR;
779			}
780			scrub_opts.randomid = 1;
781		}
782		;
783
784fragcache	: FRAGMENT REASSEMBLE	{ $$ = 0; /* default */ }
785		| FRAGMENT FRAGCROP	{ $$ = PFRULE_FRAGCROP; }
786		| FRAGMENT FRAGDROP	{ $$ = PFRULE_FRAGDROP; }
787		;
788
789antispoof	: ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
790			struct pf_rule		 r;
791			struct node_host	*h = NULL;
792			struct node_if		*i, *j;
793
794			if (check_rulestate(PFCTL_STATE_FILTER))
795				YYERROR;
796
797			for (i = $3; i; i = i->next) {
798				bzero(&r, sizeof(r));
799
800				r.action = PF_DROP;
801				r.direction = PF_IN;
802				r.log = $2.log;
803				r.quick = $2.quick;
804				r.af = $4;
805				if (rule_label(&r, $5.label))
806					YYERROR;
807				j = calloc(1, sizeof(struct node_if));
808				if (j == NULL)
809					err(1, "antispoof: calloc");
810				if (strlcpy(j->ifname, i->ifname,
811				    sizeof(j->ifname)) >= sizeof(j->ifname)) {
812					free(j);
813					yyerror("interface name too long");
814					YYERROR;
815				}
816				j->not = 1;
817				h = ifa_lookup(j->ifname, PFCTL_IFLOOKUP_NET);
818
819				expand_rule(&r, j, NULL, NULL, NULL, h, NULL,
820				    NULL, NULL, NULL, NULL, NULL);
821
822				if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
823					bzero(&r, sizeof(r));
824
825					r.action = PF_DROP;
826					r.direction = PF_IN;
827					r.log = $2.log;
828					r.quick = $2.quick;
829					r.af = $4;
830					if (rule_label(&r, $5.label))
831						YYERROR;
832					h = ifa_lookup(i->ifname,
833					    PFCTL_IFLOOKUP_HOST);
834					expand_rule(&r, NULL, NULL, NULL, NULL,
835					    h, NULL, NULL, NULL, NULL, NULL,
836					    NULL);
837				}
838			}
839			free($5.label);
840		}
841		;
842
843antispoof_ifspc	: FOR if_item			{ $$ = $2; }
844		| FOR '{' antispoof_iflst '}'	{ $$ = $3; }
845		;
846
847antispoof_iflst	: if_item			{ $$ = $1; }
848		| antispoof_iflst comma if_item	{
849			$1->tail->next = $3;
850			$1->tail = $3;
851			$$ = $1;
852		}
853		;
854
855antispoof_opts	:	{ bzero(&antispoof_opts, sizeof antispoof_opts); }
856		  antispoof_opts_l
857			{ $$ = antispoof_opts; }
858		| /* empty */	{
859			bzero(&antispoof_opts, sizeof antispoof_opts);
860			$$ = antispoof_opts;
861		}
862		;
863
864antispoof_opts_l	: antispoof_opts_l antispoof_opt
865			| antispoof_opt
866			;
867
868antispoof_opt	: label	{
869			if (antispoof_opts.label) {
870				yyerror("label cannot be redefined");
871				YYERROR;
872			}
873			antispoof_opts.label = $1;
874		}
875		;
876
877not		: '!'		{ $$ = 1; }
878		| /* empty */	{ $$ = 0; }
879
880tabledef	: TABLE '<' STRING '>' table_opts {
881			struct node_host	 *h, *nh;
882			struct node_tinit	 *ti, *nti;
883
884			if (strlen($3) >= PF_TABLE_NAME_SIZE) {
885				yyerror("table name too long, max %d chars",
886				    PF_TABLE_NAME_SIZE - 1);
887				YYERROR;
888			}
889			if (pf->loadopt & PFCTL_FLAG_TABLE)
890				if (process_tabledef($3, &$5))
891					YYERROR;
892			for (ti = SIMPLEQ_FIRST(&$5.init_nodes);
893			    ti != SIMPLEQ_END(&$5.init_nodes); ti = nti) {
894				if (ti->file)
895					free(ti->file);
896				for (h = ti->host; h != NULL; h = nh) {
897					nh = h->next;
898					free(h);
899				}
900				nti = SIMPLEQ_NEXT(ti, entries);
901				free (ti);
902			}
903		}
904		;
905
906table_opts	:	{
907			bzero(&table_opts, sizeof table_opts);
908			SIMPLEQ_INIT(&table_opts.init_nodes);
909		}
910		   table_opts_l
911			{ $$ = table_opts; }
912		| /* empty */
913			{
914			bzero(&table_opts, sizeof table_opts);
915			SIMPLEQ_INIT(&table_opts.init_nodes);
916			$$ = table_opts;
917		}
918		;
919
920table_opts_l	: table_opts_l table_opt
921		| table_opt
922		;
923
924table_opt	: STRING		{
925			if (!strcmp($1, "const"))
926				table_opts.flags |= PFR_TFLAG_CONST;
927			else if (!strcmp($1, "persist"))
928				table_opts.flags |= PFR_TFLAG_PERSIST;
929			else
930				YYERROR;
931		}
932		| '{' '}'		{ table_opts.init_addr = 1; }
933		| '{' host_list '}'	{
934			struct node_host	*n;
935			struct node_tinit	*ti;
936
937			for (n = $2; n != NULL; n = n->next) {
938				switch(n->addr.type) {
939				case PF_ADDR_ADDRMASK:
940					continue; /* ok */
941				case PF_ADDR_DYNIFTL:
942					yyerror("dynamic addresses are not "
943					    "permitted inside tables");
944					break;
945				case PF_ADDR_TABLE:
946					yyerror("tables cannot contain tables");
947					break;
948				case PF_ADDR_NOROUTE:
949					yyerror("\"no-route\" is not permitted "
950					    "inside tables");
951					break;
952				default:
953					yyerror("unknown address type %d",
954					    n->addr.type);
955				}
956				YYERROR;
957			}
958			if (!(ti = calloc(1, sizeof(*ti))))
959				err(1, "table_opt: calloc");
960			ti->host = $2;
961			SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
962			    entries);
963			table_opts.init_addr = 1;
964		}
965		| FILENAME STRING	{
966			struct node_tinit	*ti;
967
968			if (!(ti = calloc(1, sizeof(*ti))))
969				err(1, "table_opt: calloc");
970			ti->file = $2;
971			SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
972			    entries);
973			table_opts.init_addr = 1;
974		}
975		;
976
977altqif		: ALTQ interface queue_opts QUEUE qassign {
978			struct pf_altq	a;
979
980			if (check_rulestate(PFCTL_STATE_QUEUE))
981				YYERROR;
982
983			memset(&a, 0, sizeof(a));
984			if ($3.scheduler.qtype == ALTQT_NONE) {
985				yyerror("no scheduler specified!");
986				YYERROR;
987			}
988			a.scheduler = $3.scheduler.qtype;
989			a.qlimit = $3.qlimit;
990			a.tbrsize = $3.tbrsize;
991			if ($5 == NULL) {
992				yyerror("no child queues specified");
993				YYERROR;
994			}
995			if (expand_altq(&a, $2, $5, $3.queue_bwspec,
996			    &$3.scheduler))
997				YYERROR;
998		}
999		;
1000
1001queuespec	: QUEUE STRING interface queue_opts qassign {
1002			struct pf_altq	a;
1003
1004			if (check_rulestate(PFCTL_STATE_QUEUE))
1005				YYERROR;
1006
1007			memset(&a, 0, sizeof(a));
1008
1009			if (strlcpy(a.qname, $2, sizeof(a.qname)) >=
1010			    sizeof(a.qname)) {
1011				yyerror("queue name too long (max "
1012				    "%d chars)", PF_QNAME_SIZE-1);
1013				YYERROR;
1014			}
1015			if ($4.tbrsize) {
1016				yyerror("cannot specify tbrsize for queue");
1017				YYERROR;
1018			}
1019			if ($4.priority > 255) {
1020				yyerror("priority out of range: max 255");
1021				YYERROR;
1022			}
1023			a.priority = $4.priority;
1024			a.qlimit = $4.qlimit;
1025			a.scheduler = $4.scheduler.qtype;
1026			if (expand_queue(&a, $3, $5, $4.queue_bwspec,
1027			    &$4.scheduler)) {
1028				yyerror("errors in queue definition");
1029				YYERROR;
1030			}
1031		}
1032		;
1033
1034queue_opts	:	{
1035			bzero(&queue_opts, sizeof queue_opts);
1036			queue_opts.priority = DEFAULT_PRIORITY;
1037			queue_opts.qlimit = DEFAULT_QLIMIT;
1038			queue_opts.scheduler.qtype = ALTQT_NONE;
1039			queue_opts.queue_bwspec.bw_percent = 100;
1040		}
1041		  queue_opts_l
1042			{ $$ = queue_opts; }
1043		| /* empty */ {
1044			bzero(&queue_opts, sizeof queue_opts);
1045			queue_opts.priority = DEFAULT_PRIORITY;
1046			queue_opts.qlimit = DEFAULT_QLIMIT;
1047			queue_opts.scheduler.qtype = ALTQT_NONE;
1048			queue_opts.queue_bwspec.bw_percent = 100;
1049			$$ = queue_opts;
1050		}
1051		;
1052
1053queue_opts_l	: queue_opts_l queue_opt
1054		| queue_opt
1055		;
1056
1057queue_opt	: BANDWIDTH bandwidth	{
1058			if (queue_opts.marker & QOM_BWSPEC) {
1059				yyerror("bandwidth cannot be respecified");
1060				YYERROR;
1061			}
1062			queue_opts.marker |= QOM_BWSPEC;
1063			queue_opts.queue_bwspec = $2;
1064		}
1065		| PRIORITY number	{
1066			if (queue_opts.marker & QOM_PRIORITY) {
1067				yyerror("priority cannot be respecified");
1068				YYERROR;
1069			}
1070			if ($2 > 255) {
1071				yyerror("priority out of range: max 255");
1072				YYERROR;
1073			}
1074			queue_opts.marker |= QOM_PRIORITY;
1075			queue_opts.priority = $2;
1076		}
1077		| QLIMIT number	{
1078			if (queue_opts.marker & QOM_QLIMIT) {
1079				yyerror("qlimit cannot be respecified");
1080				YYERROR;
1081			}
1082			if ($2 > 65535) {
1083				yyerror("qlimit out of range: max 65535");
1084				YYERROR;
1085			}
1086			queue_opts.marker |= QOM_QLIMIT;
1087			queue_opts.qlimit = $2;
1088		}
1089		| scheduler	{
1090			if (queue_opts.marker & QOM_SCHEDULER) {
1091				yyerror("scheduler cannot be respecified");
1092				YYERROR;
1093			}
1094			queue_opts.marker |= QOM_SCHEDULER;
1095			queue_opts.scheduler = $1;
1096		}
1097		| TBRSIZE number	{
1098			if (queue_opts.marker & QOM_TBRSIZE) {
1099				yyerror("tbrsize cannot be respecified");
1100				YYERROR;
1101			}
1102			if ($2 > 65535) {
1103				yyerror("tbrsize too big: max 65535");
1104				YYERROR;
1105			}
1106			queue_opts.marker |= QOM_TBRSIZE;
1107			queue_opts.tbrsize = $2;
1108		}
1109		;
1110
1111bandwidth	: STRING {
1112			double	 bps;
1113			char	*cp;
1114
1115			$$.bw_percent = 0;
1116
1117			bps = strtod($1, &cp);
1118			if (cp != NULL) {
1119				if (!strcmp(cp, "b"))
1120					; /* nothing */
1121				else if (!strcmp(cp, "Kb"))
1122					bps *= 1000;
1123				else if (!strcmp(cp, "Mb"))
1124					bps *= 1000 * 1000;
1125				else if (!strcmp(cp, "Gb"))
1126					bps *= 1000 * 1000 * 1000;
1127				else if (!strcmp(cp, "%")) {
1128					if (bps < 0 || bps > 100) {
1129						yyerror("bandwidth spec "
1130						    "out of range");
1131						YYERROR;
1132					}
1133					$$.bw_percent = bps;
1134					bps = 0;
1135				} else {
1136					yyerror("unknown unit %s", cp);
1137					YYERROR;
1138				}
1139			}
1140			$$.bw_absolute = (u_int32_t)bps;
1141		}
1142
1143scheduler	: CBQ				{
1144			$$.qtype = ALTQT_CBQ;
1145			$$.data.cbq_opts.flags = 0;
1146		}
1147		| CBQ '(' cbqflags_list ')'	{
1148			$$.qtype = ALTQT_CBQ;
1149			$$.data.cbq_opts.flags = $3;
1150		}
1151		| PRIQ				{
1152			$$.qtype = ALTQT_PRIQ;
1153			$$.data.priq_opts.flags = 0;
1154		}
1155		| PRIQ '(' priqflags_list ')'	{
1156			$$.qtype = ALTQT_PRIQ;
1157			$$.data.priq_opts.flags = $3;
1158		}
1159		| HFSC				{
1160			$$.qtype = ALTQT_HFSC;
1161			bzero(&$$.data.hfsc_opts,
1162			    sizeof(struct node_hfsc_opts));
1163		}
1164		| HFSC '(' hfsc_opts ')'	{
1165			$$.qtype = ALTQT_HFSC;
1166			$$.data.hfsc_opts = $3;
1167		}
1168		;
1169
1170cbqflags_list	: cbqflags_item				{ $$ |= $1; }
1171		| cbqflags_list comma cbqflags_item	{ $$ |= $3; }
1172		;
1173
1174cbqflags_item	: STRING	{
1175			if (!strcmp($1, "default"))
1176				$$ = CBQCLF_DEFCLASS;
1177			else if (!strcmp($1, "borrow"))
1178				$$ = CBQCLF_BORROW;
1179			else if (!strcmp($1, "red"))
1180				$$ = CBQCLF_RED;
1181			else if (!strcmp($1, "ecn"))
1182				$$ = CBQCLF_RED|CBQCLF_ECN;
1183			else if (!strcmp($1, "rio"))
1184				$$ = CBQCLF_RIO;
1185			else {
1186				yyerror("unknown cbq flag \"%s\"", $1);
1187				YYERROR;
1188			}
1189		}
1190		;
1191
1192priqflags_list	: priqflags_item			{ $$ |= $1; }
1193		| priqflags_list comma priqflags_item	{ $$ |= $3; }
1194		;
1195
1196priqflags_item	: STRING	{
1197			if (!strcmp($1, "default"))
1198				$$ = PRCF_DEFAULTCLASS;
1199			else if (!strcmp($1, "red"))
1200				$$ = PRCF_RED;
1201			else if (!strcmp($1, "ecn"))
1202				$$ = PRCF_RED|PRCF_ECN;
1203			else if (!strcmp($1, "rio"))
1204				$$ = PRCF_RIO;
1205			else {
1206				yyerror("unknown priq flag \"%s\"", $1);
1207				YYERROR;
1208			}
1209		}
1210		;
1211
1212hfsc_opts	:	{
1213				bzero(&hfsc_opts,
1214				    sizeof(struct node_hfsc_opts));
1215			}
1216		  hfscopts_list				{
1217			$$ = hfsc_opts;
1218		}
1219		;
1220
1221hfscopts_list	: hfscopts_item
1222		| hfscopts_list comma hfscopts_item
1223		;
1224
1225hfscopts_item	: LINKSHARE bandwidth				{
1226			if (hfsc_opts.linkshare.used) {
1227				yyerror("linkshare already specified");
1228				YYERROR;
1229			}
1230			hfsc_opts.linkshare.m2 = $2;
1231			hfsc_opts.linkshare.used = 1;
1232		}
1233		| LINKSHARE '(' bandwidth number bandwidth ')'	{
1234			if (hfsc_opts.linkshare.used) {
1235				yyerror("linkshare already specified");
1236				YYERROR;
1237			}
1238			hfsc_opts.linkshare.m1 = $3;
1239			hfsc_opts.linkshare.d = $4;
1240			hfsc_opts.linkshare.m2 = $5;
1241			hfsc_opts.linkshare.used = 1;
1242		}
1243		| REALTIME bandwidth				{
1244			if (hfsc_opts.realtime.used) {
1245				yyerror("realtime already specified");
1246				YYERROR;
1247			}
1248			hfsc_opts.realtime.m2 = $2;
1249			hfsc_opts.realtime.used = 1;
1250		}
1251		| REALTIME '(' bandwidth number bandwidth ')'	{
1252			if (hfsc_opts.realtime.used) {
1253				yyerror("realtime already specified");
1254				YYERROR;
1255			}
1256			hfsc_opts.realtime.m1 = $3;
1257			hfsc_opts.realtime.d = $4;
1258			hfsc_opts.realtime.m2 = $5;
1259			hfsc_opts.realtime.used = 1;
1260		}
1261		| UPPERLIMIT bandwidth				{
1262			if (hfsc_opts.upperlimit.used) {
1263				yyerror("upperlimit already specified");
1264				YYERROR;
1265			}
1266			hfsc_opts.upperlimit.m2 = $2;
1267			hfsc_opts.upperlimit.used = 1;
1268		}
1269		| UPPERLIMIT '(' bandwidth number bandwidth ')'	{
1270			if (hfsc_opts.upperlimit.used) {
1271				yyerror("upperlimit already specified");
1272				YYERROR;
1273			}
1274			hfsc_opts.upperlimit.m1 = $3;
1275			hfsc_opts.upperlimit.d = $4;
1276			hfsc_opts.upperlimit.m2 = $5;
1277			hfsc_opts.upperlimit.used = 1;
1278		}
1279		| STRING	{
1280			if (!strcmp($1, "default"))
1281				hfsc_opts.flags |= HFCF_DEFAULTCLASS;
1282			else if (!strcmp($1, "red"))
1283				hfsc_opts.flags |= HFCF_RED;
1284			else if (!strcmp($1, "ecn"))
1285				hfsc_opts.flags |= HFCF_RED|HFCF_ECN;
1286			else if (!strcmp($1, "rio"))
1287				hfsc_opts.flags |= HFCF_RIO;
1288			else {
1289				yyerror("unknown hfsc flag \"%s\"", $1);
1290				YYERROR;
1291			}
1292		}
1293		;
1294
1295qassign		: /* empty */		{ $$ = NULL; }
1296		| qassign_item		{ $$ = $1; }
1297		| '{' qassign_list '}'	{ $$ = $2; }
1298		;
1299
1300qassign_list	: qassign_item			{ $$ = $1; }
1301		| qassign_list comma qassign_item	{
1302			$1->tail->next = $3;
1303			$1->tail = $3;
1304			$$ = $1;
1305		}
1306		;
1307
1308qassign_item	: STRING			{
1309			$$ = calloc(1, sizeof(struct node_queue));
1310			if ($$ == NULL)
1311				err(1, "qassign_item: calloc");
1312			if (strlcpy($$->queue, $1, sizeof($$->queue)) >=
1313			    sizeof($$->queue)) {
1314				free($$);
1315				yyerror("queue name '%s' too long (max "
1316				    "%d chars)", $1, sizeof($$->queue)-1);
1317				YYERROR;
1318			}
1319			$$->next = NULL;
1320			$$->tail = $$;
1321		}
1322		;
1323
1324pfrule		: action dir logquick interface route af proto fromto
1325		  filter_opts
1326		{
1327			struct pf_rule		 r;
1328			struct node_state_opt	*o;
1329			struct node_proto	*proto;
1330
1331			if (check_rulestate(PFCTL_STATE_FILTER))
1332				YYERROR;
1333
1334			memset(&r, 0, sizeof(r));
1335
1336			r.action = $1.b1;
1337			switch ($1.b2) {
1338			case PFRULE_RETURNRST:
1339				r.rule_flag |= PFRULE_RETURNRST;
1340				r.return_ttl = $1.w;
1341				break;
1342			case PFRULE_RETURNICMP:
1343				r.rule_flag |= PFRULE_RETURNICMP;
1344				r.return_icmp = $1.w;
1345				r.return_icmp6 = $1.w2;
1346				break;
1347			case PFRULE_RETURN:
1348				r.rule_flag |= PFRULE_RETURN;
1349				r.return_icmp = $1.w;
1350				r.return_icmp6 = $1.w2;
1351				break;
1352			}
1353			r.direction = $2;
1354			r.log = $3.log;
1355			r.quick = $3.quick;
1356
1357			r.af = $6;
1358			if ($9.tag)
1359				if (strlcpy(r.tagname, $9.tag,
1360				    PF_TAG_NAME_SIZE) > PF_TAG_NAME_SIZE) {
1361					yyerror("tag too long, max %u chars",
1362					    PF_TAG_NAME_SIZE - 1);
1363					YYERROR;
1364				}
1365			if ($9.match_tag)
1366				if (strlcpy(r.match_tagname, $9.match_tag,
1367				    PF_TAG_NAME_SIZE) > PF_TAG_NAME_SIZE) {
1368					yyerror("tag too long, max %u chars",
1369					    PF_TAG_NAME_SIZE - 1);
1370					YYERROR;
1371				}
1372			r.match_tag_not = $9.match_tag_not;
1373			r.flags = $9.flags.b1;
1374			r.flagset = $9.flags.b2;
1375			if (rule_label(&r, $9.label))
1376				YYERROR;
1377			free($9.label);
1378			if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
1379				for (proto = $7; proto != NULL &&
1380				    proto->proto != IPPROTO_TCP;
1381				    proto = proto->next)
1382					;	/* nothing */
1383				if (proto == NULL && $7 != NULL) {
1384					if ($9.flags.b1 || $9.flags.b2)
1385						yyerror(
1386						    "flags only apply to tcp");
1387					if ($8.src_os)
1388						yyerror(
1389						    "OS fingerprinting only "
1390						    "apply to tcp");
1391					YYERROR;
1392				}
1393#if 0
1394				if (($9.flags.b1 & parse_flags("S")) == 0 &&
1395				    $8.src_os) {
1396					yyerror("OS fingerprinting requires "
1397					     "the SYN TCP flag (flags S/SA)");
1398					YYERROR;
1399				}
1400#endif
1401			}
1402
1403			r.tos = $9.tos;
1404			r.keep_state = $9.keep.action;
1405			o = $9.keep.options;
1406			while (o) {
1407				struct node_state_opt	*p = o;
1408
1409				switch (o->type) {
1410				case PF_STATE_OPT_MAX:
1411					if (r.max_states) {
1412						yyerror("state option 'max' "
1413						    "multiple definitions");
1414						YYERROR;
1415					}
1416					r.max_states = o->data.max_states;
1417					break;
1418				case PF_STATE_OPT_TIMEOUT:
1419					if (r.timeout[o->data.timeout.number]) {
1420						yyerror("state timeout %s "
1421						    "multiple definitions",
1422						    pf_timeouts[o->data.
1423						    timeout.number].name);
1424						YYERROR;
1425					}
1426					r.timeout[o->data.timeout.number] =
1427					    o->data.timeout.seconds;
1428				}
1429				o = o->next;
1430				free(p);
1431			}
1432
1433			if ($9.fragment)
1434				r.rule_flag |= PFRULE_FRAGMENT;
1435			r.allow_opts = $9.allowopts;
1436
1437			decide_address_family($8.src.host, &r.af);
1438			decide_address_family($8.dst.host, &r.af);
1439
1440			if ($5.rt) {
1441				if (!r.direction) {
1442					yyerror("direction must be explicit "
1443					    "with rules that specify routing");
1444					YYERROR;
1445				}
1446				r.rt = $5.rt;
1447				r.rpool.opts = $5.pool_opts;
1448				if ($5.key != NULL)
1449					memcpy(&r.rpool.key, $5.key,
1450					    sizeof(struct pf_poolhashkey));
1451			}
1452			if (r.rt && r.rt != PF_FASTROUTE) {
1453				decide_address_family($5.host, &r.af);
1454				remove_invalid_hosts(&$5.host, &r.af);
1455				if ($5.host == NULL) {
1456					yyerror("no routing address with "
1457					    "matching address family found.");
1458					YYERROR;
1459				}
1460				if (r.rpool.opts == PF_POOL_NONE && (
1461				    $5.host->next != NULL ||
1462				    $5.host->addr.type == PF_ADDR_TABLE))
1463					r.rpool.opts = PF_POOL_ROUNDROBIN;
1464				if (r.rpool.opts != PF_POOL_ROUNDROBIN)
1465					if (disallow_table($5.host, "tables "
1466					    "are only supported in round-robin "
1467					    "routing pools"))
1468						YYERROR;
1469				if ($5.host->next != NULL) {
1470					if (r.rpool.opts !=
1471					    PF_POOL_ROUNDROBIN) {
1472						yyerror("r.rpool.opts must "
1473						    "be PF_POOL_ROUNDROBIN");
1474						YYERROR;
1475					}
1476				}
1477			}
1478			if ($9.queues.qname != NULL) {
1479				if (strlcpy(r.qname, $9.queues.qname,
1480				    sizeof(r.qname)) >= sizeof(r.qname)) {
1481					yyerror("rule qname too long (max "
1482					    "%d chars)", sizeof(r.qname)-1);
1483					YYERROR;
1484				}
1485				free($9.queues.qname);
1486			}
1487			if ($9.queues.pqname != NULL) {
1488				if (strlcpy(r.pqname, $9.queues.pqname,
1489				    sizeof(r.pqname)) >= sizeof(r.pqname)) {
1490					yyerror("rule pqname too long (max "
1491					    "%d chars)", sizeof(r.pqname)-1);
1492					YYERROR;
1493				}
1494				free($9.queues.pqname);
1495			}
1496
1497			expand_rule(&r, $4, $5.host, $7, $8.src_os,
1498			    $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
1499			    $9.uid, $9.gid, $9.icmpspec);
1500		}
1501		;
1502
1503filter_opts	:	{ bzero(&filter_opts, sizeof filter_opts); }
1504		  filter_opts_l
1505			{ $$ = filter_opts; }
1506		| /* empty */	{
1507			bzero(&filter_opts, sizeof filter_opts);
1508			$$ = filter_opts;
1509		}
1510		;
1511
1512filter_opts_l	: filter_opts_l filter_opt
1513		| filter_opt
1514		;
1515
1516filter_opt	: USER uids {
1517			if (filter_opts.uid)
1518				$2->tail->next = filter_opts.uid;
1519			filter_opts.uid = $2;
1520		}
1521		| GROUP gids {
1522			if (filter_opts.gid)
1523				$2->tail->next = filter_opts.gid;
1524			filter_opts.gid = $2;
1525		}
1526		| flags {
1527			if (filter_opts.marker & FOM_FLAGS) {
1528				yyerror("flags cannot be redefined");
1529				YYERROR;
1530			}
1531			filter_opts.marker |= FOM_FLAGS;
1532			filter_opts.flags.b1 |= $1.b1;
1533			filter_opts.flags.b2 |= $1.b2;
1534			filter_opts.flags.w |= $1.w;
1535			filter_opts.flags.w2 |= $1.w2;
1536		}
1537		| icmpspec {
1538			if (filter_opts.marker & FOM_ICMP) {
1539				yyerror("icmp-type cannot be redefined");
1540				YYERROR;
1541			}
1542			filter_opts.marker |= FOM_ICMP;
1543			filter_opts.icmpspec = $1;
1544		}
1545		| tos {
1546			if (filter_opts.marker & FOM_TOS) {
1547				yyerror("tos cannot be redefined");
1548				YYERROR;
1549			}
1550			filter_opts.marker |= FOM_TOS;
1551			filter_opts.tos = $1;
1552		}
1553		| keep {
1554			if (filter_opts.marker & FOM_KEEP) {
1555				yyerror("modulate or keep cannot be redefined");
1556				YYERROR;
1557			}
1558			filter_opts.marker |= FOM_KEEP;
1559			filter_opts.keep.action = $1.action;
1560			filter_opts.keep.options = $1.options;
1561		}
1562		| FRAGMENT {
1563			filter_opts.fragment = 1;
1564		}
1565		| ALLOWOPTS {
1566			filter_opts.allowopts = 1;
1567		}
1568		| label	{
1569			if (filter_opts.label) {
1570				yyerror("label cannot be redefined");
1571				YYERROR;
1572			}
1573			filter_opts.label = $1;
1574		}
1575		| qname	{
1576			if (filter_opts.queues.qname) {
1577				yyerror("queue cannot be redefined");
1578				YYERROR;
1579			}
1580			filter_opts.queues = $1;
1581		}
1582		| TAG string				{
1583			filter_opts.tag = $2;
1584		}
1585		| not TAGGED string			{
1586			filter_opts.match_tag = $3;
1587			filter_opts.match_tag_not = $1;
1588		}
1589		;
1590
1591action		: PASS			{ $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
1592		| BLOCK blockspec	{ $$ = $2; $$.b1 = PF_DROP; }
1593		;
1594
1595blockspec	: /* empty */		{
1596			$$.b2 = blockpolicy;
1597			$$.w = returnicmpdefault;
1598			$$.w2 = returnicmp6default;
1599		}
1600		| DROP			{
1601			$$.b2 = PFRULE_DROP;
1602			$$.w = 0;
1603			$$.w2 = 0;
1604		}
1605		| RETURNRST		{
1606			$$.b2 = PFRULE_RETURNRST;
1607			$$.w = 0;
1608			$$.w2 = 0;
1609		}
1610		| RETURNRST '(' TTL number ')'	{
1611			if ($4 > 255) {
1612				yyerror("illegal ttl value %d", $4);
1613				YYERROR;
1614			}
1615			$$.b2 = PFRULE_RETURNRST;
1616			$$.w = $4;
1617			$$.w2 = 0;
1618		}
1619		| RETURNICMP		{
1620			$$.b2 = PFRULE_RETURNICMP;
1621			$$.w = returnicmpdefault;
1622			$$.w2 = returnicmp6default;
1623		}
1624		| RETURNICMP6		{
1625			$$.b2 = PFRULE_RETURNICMP;
1626			$$.w = returnicmpdefault;
1627			$$.w2 = returnicmp6default;
1628		}
1629		| RETURNICMP '(' STRING ')'	{
1630			$$.b2 = PFRULE_RETURNICMP;
1631			if (!($$.w = parseicmpspec($3, AF_INET)))
1632				YYERROR;
1633			$$.w2 = returnicmp6default;
1634		}
1635		| RETURNICMP6 '(' STRING ')'	{
1636			$$.b2 = PFRULE_RETURNICMP;
1637			$$.w = returnicmpdefault;
1638			if (!($$.w2 = parseicmpspec($3, AF_INET6)))
1639				YYERROR;
1640		}
1641		| RETURNICMP '(' STRING comma STRING ')' {
1642			$$.b2 = PFRULE_RETURNICMP;
1643			if (!($$.w = parseicmpspec($3, AF_INET)))
1644				YYERROR;
1645			if (!($$.w2 = parseicmpspec($5, AF_INET6)))
1646				YYERROR;
1647		}
1648		| RETURN {
1649			$$.b2 = PFRULE_RETURN;
1650			$$.w = returnicmpdefault;
1651			$$.w2 = returnicmp6default;
1652		}
1653		;
1654
1655dir		: /* empty */			{ $$ = 0; }
1656		| IN				{ $$ = PF_IN; }
1657		| OUT				{ $$ = PF_OUT; }
1658		;
1659
1660logquick	: /* empty */			{ $$.log = 0; $$.quick = 0; }
1661		| log				{ $$.log = $1; $$.quick = 0; }
1662		| QUICK				{ $$.log = 0; $$.quick = 1; }
1663		| log QUICK			{ $$.log = $1; $$.quick = 1; }
1664		| QUICK log			{ $$.log = $2; $$.quick = 1; }
1665		;
1666
1667log		: LOG				{ $$ = 1; }
1668		| LOGALL			{ $$ = 2; }
1669		;
1670
1671interface	: /* empty */			{ $$ = NULL; }
1672		| ON if_item_not		{ $$ = $2; }
1673		| ON '{' if_list '}'		{ $$ = $3; }
1674		;
1675
1676if_list		: if_item_not			{ $$ = $1; }
1677		| if_list comma if_item_not	{
1678			$1->tail->next = $3;
1679			$1->tail = $3;
1680			$$ = $1;
1681		}
1682		;
1683
1684if_item_not	: not if_item			{ $$ = $2; $$->not = $1; }
1685		;
1686
1687if_item		: STRING			{
1688			struct node_host	*n;
1689
1690			if ((n = ifa_exists($1)) == NULL) {
1691				yyerror("unknown interface %s", $1);
1692				YYERROR;
1693			}
1694			$$ = calloc(1, sizeof(struct node_if));
1695			if ($$ == NULL)
1696				err(1, "if_item: calloc");
1697			if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >=
1698			    sizeof($$->ifname)) {
1699				free($$);
1700				yyerror("interface name too long");
1701				YYERROR;
1702			}
1703			$$->ifa_flags = n->ifa_flags;
1704			$$->not = 0;
1705			$$->next = NULL;
1706			$$->tail = $$;
1707		}
1708		;
1709
1710af		: /* empty */			{ $$ = 0; }
1711		| INET				{ $$ = AF_INET; }
1712		| INET6				{ $$ = AF_INET6; }
1713
1714proto		: /* empty */			{ $$ = NULL; }
1715		| PROTO proto_item		{ $$ = $2; }
1716		| PROTO '{' proto_list '}'	{ $$ = $3; }
1717		;
1718
1719proto_list	: proto_item			{ $$ = $1; }
1720		| proto_list comma proto_item	{
1721			$1->tail->next = $3;
1722			$1->tail = $3;
1723			$$ = $1;
1724		}
1725		;
1726
1727proto_item	: STRING			{
1728			u_int8_t	pr;
1729			u_long		ulval;
1730
1731			if (atoul($1, &ulval) == 0) {
1732				if (ulval > 255) {
1733					yyerror("protocol outside range");
1734					YYERROR;
1735				}
1736				pr = (u_int8_t)ulval;
1737			} else {
1738				struct protoent	*p;
1739
1740				p = getprotobyname($1);
1741				if (p == NULL) {
1742					yyerror("unknown protocol %s", $1);
1743					YYERROR;
1744				}
1745				pr = p->p_proto;
1746			}
1747			if (pr == 0) {
1748				yyerror("proto 0 cannot be used");
1749				YYERROR;
1750			}
1751			$$ = calloc(1, sizeof(struct node_proto));
1752			if ($$ == NULL)
1753				err(1, "proto_item: calloc");
1754			$$->proto = pr;
1755			$$->next = NULL;
1756			$$->tail = $$;
1757		}
1758		;
1759
1760fromto		: ALL				{
1761			$$.src.host = NULL;
1762			$$.src.port = NULL;
1763			$$.dst.host = NULL;
1764			$$.dst.port = NULL;
1765			$$.src_os = NULL;
1766		}
1767		| from os to			{
1768			$$.src = $1;
1769			$$.src_os = $2;
1770			$$.dst = $3;
1771		}
1772		;
1773
1774os		: /* empty */			{ $$ = NULL; }
1775		| OS xos			{ $$ = $2; }
1776		| OS '{' os_list '}'		{ $$ = $3; }
1777		;
1778
1779xos		: STRING {
1780			$$ = calloc(1, sizeof(struct node_os));
1781			if ($$ == NULL)
1782				err(1, "os: calloc");
1783			$$->os = $1;
1784			$$->tail = $$;
1785		}
1786		;
1787
1788os_list		: xos				{ $$ = $1; }
1789		| os_list comma xos		{
1790			$1->tail->next = $3;
1791			$1->tail = $3;
1792			$$ = $1;
1793		}
1794		;
1795
1796from		: /* empty */			{
1797			$$.host = NULL;
1798			$$.port = NULL;
1799		}
1800		| FROM ipportspec		{
1801			$$ = $2;
1802		}
1803		;
1804
1805to		: /* empty */			{
1806			$$.host = NULL;
1807			$$.port = NULL;
1808		}
1809		| TO ipportspec		{
1810			$$ = $2;
1811		}
1812		;
1813
1814ipportspec	: ipspec			{
1815			$$.host = $1;
1816			$$.port = NULL;
1817		}
1818		| ipspec PORT portspec		{
1819			$$.host = $1;
1820			$$.port = $3;
1821		}
1822		| PORT portspec			{
1823			$$.host = NULL;
1824			$$.port = $2;
1825		}
1826		;
1827
1828ipspec		: ANY				{ $$ = NULL; }
1829		| xhost				{ $$ = $1; }
1830		| '{' host_list '}'		{ $$ = $2; }
1831		;
1832
1833host_list	: xhost				{ $$ = $1; }
1834		| host_list comma xhost		{
1835			if ($3 == NULL)
1836				$$ = $1;
1837			else if ($1 == NULL)
1838				$$ = $3;
1839			else {
1840				$1->tail->next = $3;
1841				$1->tail = $3->tail;
1842				$$ = $1;
1843			}
1844		}
1845		;
1846
1847xhost		: not host			{
1848			struct node_host	*n;
1849
1850			for (n = $2; n != NULL; n = n->next)
1851				n->not = $1;
1852			$$ = $2;
1853		}
1854		| NOROUTE			{
1855			$$ = calloc(1, sizeof(struct node_host));
1856			if ($$ == NULL)
1857				err(1, "xhost: calloc");
1858			$$->addr.type = PF_ADDR_NOROUTE;
1859			$$->next = NULL;
1860			$$->tail = $$;
1861		}
1862		;
1863
1864host		: STRING			{
1865			if (($$ = host($1)) == NULL)	{
1866				/* error. "any" is handled elsewhere */
1867				yyerror("could not parse host specification");
1868				YYERROR;
1869			}
1870
1871		}
1872		| STRING '/' number		{
1873			char	*buf;
1874
1875			if (asprintf(&buf, "%s/%u", $1, $3) == -1)
1876				err(1, "host: asprintf");
1877			if (($$ = host(buf)) == NULL)	{
1878				/* error. "any" is handled elsewhere */
1879				free(buf);
1880				yyerror("could not parse host specification");
1881				YYERROR;
1882			}
1883			free(buf);
1884		}
1885		| dynaddr
1886		| dynaddr '/' number		{
1887			struct node_host	*n;
1888
1889			$$ = $1;
1890			for (n = $1; n != NULL; n = n->next)
1891				set_ipmask(n, $3);
1892		}
1893		| '<' STRING '>'	{
1894			if (strlen($2) >= PF_TABLE_NAME_SIZE) {
1895				yyerror("table name '%s' too long");
1896				YYERROR;
1897			}
1898			$$ = calloc(1, sizeof(struct node_host));
1899			if ($$ == NULL)
1900				err(1, "host: calloc");
1901			$$->addr.type = PF_ADDR_TABLE;
1902			if (strlcpy($$->addr.v.tblname, $2,
1903			    sizeof($$->addr.v.tblname)) >=
1904			    sizeof($$->addr.v.tblname))
1905				errx(1, "host: strlcpy");
1906			$$->next = NULL;
1907			$$->tail = $$;
1908		}
1909		;
1910
1911number		: STRING			{
1912			u_long	ulval;
1913
1914			if (atoul($1, &ulval) == -1) {
1915				yyerror("%s is not a number", $1);
1916				YYERROR;
1917			} else
1918				$$ = ulval;
1919		}
1920		;
1921
1922dynaddr		: '(' STRING ')'		{
1923			if (ifa_exists($2) == NULL) {
1924				yyerror("interface %s does not exist", $2);
1925				YYERROR;
1926			}
1927			$$ = calloc(1, sizeof(struct node_host));
1928			if ($$ == NULL)
1929				err(1, "address: calloc");
1930			$$->af = 0;
1931			set_ipmask($$, 128);
1932			$$->addr.type = PF_ADDR_DYNIFTL;
1933			if (strlcpy($$->addr.v.ifname, $2,
1934			    sizeof($$->addr.v.ifname)) >=
1935			    sizeof($$->addr.v.ifname)) {
1936				free($$);
1937				yyerror("interface name too long");
1938				YYERROR;
1939			}
1940			$$->next = NULL;
1941			$$->tail = $$;
1942		}
1943		;
1944
1945portspec	: port_item			{ $$ = $1; }
1946		| '{' port_list '}'		{ $$ = $2; }
1947		;
1948
1949port_list	: port_item			{ $$ = $1; }
1950		| port_list comma port_item	{
1951			$1->tail->next = $3;
1952			$1->tail = $3;
1953			$$ = $1;
1954		}
1955		;
1956
1957port_item	: port				{
1958			$$ = calloc(1, sizeof(struct node_port));
1959			if ($$ == NULL)
1960				err(1, "port_item: calloc");
1961			$$->port[0] = $1.a;
1962			$$->port[1] = $1.b;
1963			if ($1.t)
1964				$$->op = PF_OP_RRG;
1965			else
1966				$$->op = PF_OP_EQ;
1967			$$->next = NULL;
1968			$$->tail = $$;
1969		}
1970		| unaryop port		{
1971			if ($2.t) {
1972				yyerror("':' cannot be used with an other "
1973				    "port operator");
1974				YYERROR;
1975			}
1976			$$ = calloc(1, sizeof(struct node_port));
1977			if ($$ == NULL)
1978				err(1, "port_item: calloc");
1979			$$->port[0] = $2.a;
1980			$$->port[1] = $2.b;
1981			$$->op = $1;
1982			$$->next = NULL;
1983			$$->tail = $$;
1984		}
1985		| port PORTBINARY port		{
1986			if ($1.t || $3.t) {
1987				yyerror("':' cannot be used with an other "
1988				    "port operator");
1989				YYERROR;
1990			}
1991			$$ = calloc(1, sizeof(struct node_port));
1992			if ($$ == NULL)
1993				err(1, "port_item: calloc");
1994			$$->port[0] = $1.a;
1995			$$->port[1] = $3.a;
1996			$$->op = $2;
1997			$$->next = NULL;
1998			$$->tail = $$;
1999		}
2000		;
2001
2002port		: STRING			{
2003			char	*p = strchr($1, ':');
2004			struct servent	*s = NULL;
2005			u_long		 ulval;
2006
2007			if (p == NULL) {
2008				if (atoul($1, &ulval) == 0) {
2009					if (ulval > 65535) {
2010						yyerror("illegal port value %d",
2011						    ulval);
2012						YYERROR;
2013					}
2014					$$.a = htons(ulval);
2015				} else {
2016					s = getservbyname($1, "tcp");
2017					if (s == NULL)
2018						s = getservbyname($1, "udp");
2019					if (s == NULL) {
2020						yyerror("unknown port %s", $1);
2021						YYERROR;
2022					}
2023					$$.a = s->s_port;
2024				}
2025				$$.b = 0;
2026				$$.t = 0;
2027			} else {
2028				int port[2];
2029
2030				*p++ = 0;
2031				if ((port[0] = getservice($1)) == -1 ||
2032				    (port[1] = getservice(p)) == -1)
2033					YYERROR;
2034				$$.a = port[0];
2035				$$.b = port[1];
2036				$$.t = PF_OP_RRG;
2037			}
2038		}
2039		;
2040
2041uids		: uid_item			{ $$ = $1; }
2042		| '{' uid_list '}'		{ $$ = $2; }
2043		;
2044
2045uid_list	: uid_item			{ $$ = $1; }
2046		| uid_list comma uid_item	{
2047			$1->tail->next = $3;
2048			$1->tail = $3;
2049			$$ = $1;
2050		}
2051		;
2052
2053uid_item	: uid				{
2054			$$ = calloc(1, sizeof(struct node_uid));
2055			if ($$ == NULL)
2056				err(1, "uid_item: calloc");
2057			$$->uid[0] = $1;
2058			$$->uid[1] = $1;
2059			$$->op = PF_OP_EQ;
2060			$$->next = NULL;
2061			$$->tail = $$;
2062		}
2063		| unaryop uid			{
2064			if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
2065				yyerror("user unknown requires operator = or "
2066				    "!=");
2067				YYERROR;
2068			}
2069			$$ = calloc(1, sizeof(struct node_uid));
2070			if ($$ == NULL)
2071				err(1, "uid_item: calloc");
2072			$$->uid[0] = $2;
2073			$$->uid[1] = $2;
2074			$$->op = $1;
2075			$$->next = NULL;
2076			$$->tail = $$;
2077		}
2078		| uid PORTBINARY uid		{
2079			if ($1 == UID_MAX || $3 == UID_MAX) {
2080				yyerror("user unknown requires operator = or "
2081				    "!=");
2082				YYERROR;
2083			}
2084			$$ = calloc(1, sizeof(struct node_uid));
2085			if ($$ == NULL)
2086				err(1, "uid_item: calloc");
2087			$$->uid[0] = $1;
2088			$$->uid[1] = $3;
2089			$$->op = $2;
2090			$$->next = NULL;
2091			$$->tail = $$;
2092		}
2093		;
2094
2095uid		: STRING			{
2096			u_long	ulval;
2097
2098			if (atoul($1, &ulval) == -1) {
2099				if (!strcmp($1, "unknown"))
2100					$$ = UID_MAX;
2101				else {
2102					struct passwd	*pw;
2103
2104					if ((pw = getpwnam($1)) == NULL) {
2105						yyerror("unknown user %s", $1);
2106						YYERROR;
2107					}
2108					$$ = pw->pw_uid;
2109				}
2110			} else {
2111				if (ulval >= UID_MAX) {
2112					yyerror("illegal uid value %lu", ulval);
2113					YYERROR;
2114				}
2115				$$ = ulval;
2116			}
2117		}
2118		;
2119
2120gids		: gid_item			{ $$ = $1; }
2121		| '{' gid_list '}'		{ $$ = $2; }
2122		;
2123
2124gid_list	: gid_item			{ $$ = $1; }
2125		| gid_list comma gid_item	{
2126			$1->tail->next = $3;
2127			$1->tail = $3;
2128			$$ = $1;
2129		}
2130		;
2131
2132gid_item	: gid				{
2133			$$ = calloc(1, sizeof(struct node_gid));
2134			if ($$ == NULL)
2135				err(1, "gid_item: calloc");
2136			$$->gid[0] = $1;
2137			$$->gid[1] = $1;
2138			$$->op = PF_OP_EQ;
2139			$$->next = NULL;
2140			$$->tail = $$;
2141		}
2142		| unaryop gid			{
2143			if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
2144				yyerror("group unknown requires operator = or "
2145				    "!=");
2146				YYERROR;
2147			}
2148			$$ = calloc(1, sizeof(struct node_gid));
2149			if ($$ == NULL)
2150				err(1, "gid_item: calloc");
2151			$$->gid[0] = $2;
2152			$$->gid[1] = $2;
2153			$$->op = $1;
2154			$$->next = NULL;
2155			$$->tail = $$;
2156		}
2157		| gid PORTBINARY gid		{
2158			if ($1 == GID_MAX || $3 == GID_MAX) {
2159				yyerror("group unknown requires operator = or "
2160				    "!=");
2161				YYERROR;
2162			}
2163			$$ = calloc(1, sizeof(struct node_gid));
2164			if ($$ == NULL)
2165				err(1, "gid_item: calloc");
2166			$$->gid[0] = $1;
2167			$$->gid[1] = $3;
2168			$$->op = $2;
2169			$$->next = NULL;
2170			$$->tail = $$;
2171		}
2172		;
2173
2174gid		: STRING			{
2175			u_long	ulval;
2176
2177			if (atoul($1, &ulval) == -1) {
2178				if (!strcmp($1, "unknown"))
2179					$$ = GID_MAX;
2180				else {
2181					struct group	*grp;
2182
2183					if ((grp = getgrnam($1)) == NULL) {
2184						yyerror("unknown group %s", $1);
2185						YYERROR;
2186					}
2187					$$ = grp->gr_gid;
2188				}
2189			} else {
2190				if (ulval >= GID_MAX) {
2191					yyerror("illegal gid value %lu", ulval);
2192					YYERROR;
2193				}
2194				$$ = ulval;
2195			}
2196		}
2197		;
2198
2199flag		: STRING			{
2200			int	f;
2201
2202			if ((f = parse_flags($1)) < 0) {
2203				yyerror("bad flags %s", $1);
2204				YYERROR;
2205			}
2206			$$.b1 = f;
2207		}
2208		;
2209
2210flags		: FLAGS flag '/' flag	{ $$.b1 = $2.b1; $$.b2 = $4.b1; }
2211		| FLAGS '/' flag	{ $$.b1 = 0; $$.b2 = $3.b1; }
2212		;
2213
2214icmpspec	: ICMPTYPE icmp_item		{ $$ = $2; }
2215		| ICMPTYPE '{' icmp_list '}'	{ $$ = $3; }
2216		| ICMP6TYPE icmp6_item		{ $$ = $2; }
2217		| ICMP6TYPE '{' icmp6_list '}'	{ $$ = $3; }
2218		;
2219
2220icmp_list	: icmp_item			{ $$ = $1; }
2221		| icmp_list comma icmp_item	{
2222			$1->tail->next = $3;
2223			$1->tail = $3;
2224			$$ = $1;
2225		}
2226		;
2227
2228icmp6_list	: icmp6_item			{ $$ = $1; }
2229		| icmp6_list comma icmp6_item	{
2230			$1->tail->next = $3;
2231			$1->tail = $3;
2232			$$ = $1;
2233		}
2234		;
2235
2236icmp_item	: icmptype		{
2237			$$ = calloc(1, sizeof(struct node_icmp));
2238			if ($$ == NULL)
2239				err(1, "icmp_item: calloc");
2240			$$->type = $1;
2241			$$->code = 0;
2242			$$->proto = IPPROTO_ICMP;
2243			$$->next = NULL;
2244			$$->tail = $$;
2245		}
2246		| icmptype CODE STRING	{
2247			const struct icmpcodeent	*p;
2248			u_long				 ulval;
2249
2250			if (atoul($3, &ulval) == 0) {
2251				if (ulval > 255) {
2252					yyerror("illegal icmp-code %d", ulval);
2253					YYERROR;
2254				}
2255			} else {
2256				if ((p = geticmpcodebyname($1-1, $3,
2257				    AF_INET)) == NULL) {
2258					yyerror("unknown icmp-code %s", $3);
2259					YYERROR;
2260				}
2261				ulval = p->code;
2262			}
2263			$$ = calloc(1, sizeof(struct node_icmp));
2264			if ($$ == NULL)
2265				err(1, "icmp_item: calloc");
2266			$$->type = $1;
2267			$$->code = ulval + 1;
2268			$$->proto = IPPROTO_ICMP;
2269			$$->next = NULL;
2270			$$->tail = $$;
2271		}
2272		;
2273
2274icmp6_item	: icmp6type		{
2275			$$ = calloc(1, sizeof(struct node_icmp));
2276			if ($$ == NULL)
2277				err(1, "icmp_item: calloc");
2278			$$->type = $1;
2279			$$->code = 0;
2280			$$->proto = IPPROTO_ICMPV6;
2281			$$->next = NULL;
2282			$$->tail = $$;
2283		}
2284		| icmp6type CODE STRING	{
2285			const struct icmpcodeent	*p;
2286			u_long				 ulval;
2287
2288			if (atoul($3, &ulval) == 0) {
2289				if (ulval > 255) {
2290					yyerror("illegal icmp6-code %ld",
2291					    ulval);
2292					YYERROR;
2293				}
2294			} else {
2295				if ((p = geticmpcodebyname($1-1, $3,
2296				    AF_INET6)) == NULL) {
2297					yyerror("unknown icmp6-code %s", $3);
2298					YYERROR;
2299				}
2300				ulval = p->code;
2301			}
2302			$$ = calloc(1, sizeof(struct node_icmp));
2303			if ($$ == NULL)
2304				err(1, "icmp_item: calloc");
2305			$$->type = $1;
2306			$$->code = ulval + 1;
2307			$$->proto = IPPROTO_ICMPV6;
2308			$$->next = NULL;
2309			$$->tail = $$;
2310		}
2311		;
2312
2313icmptype	: STRING			{
2314			const struct icmptypeent	*p;
2315			u_long				 ulval;
2316
2317			if (atoul($1, &ulval) == 0) {
2318				if (ulval > 255) {
2319					yyerror("illegal icmp-type %d", ulval);
2320					YYERROR;
2321				}
2322				$$ = ulval + 1;
2323			} else {
2324				if ((p = geticmptypebyname($1, AF_INET)) ==
2325				    NULL) {
2326					yyerror("unknown icmp-type %s", $1);
2327					YYERROR;
2328				}
2329				$$ = p->type + 1;
2330			}
2331		}
2332		;
2333
2334icmp6type	: STRING			{
2335			const struct icmptypeent	*p;
2336			u_long				 ulval;
2337
2338			if (atoul($1, &ulval) == 0) {
2339				if (ulval > 255) {
2340					yyerror("illegal icmp6-type %d", ulval);
2341					YYERROR;
2342				}
2343				$$ = ulval + 1;
2344			} else {
2345				if ((p = geticmptypebyname($1, AF_INET6)) ==
2346				    NULL) {
2347					yyerror("unknown icmp6-type %s", $1);
2348					YYERROR;
2349				}
2350				$$ = p->type + 1;
2351			}
2352		}
2353		;
2354
2355tos		: TOS STRING			{
2356			if (!strcmp($2, "lowdelay"))
2357				$$ = IPTOS_LOWDELAY;
2358			else if (!strcmp($2, "throughput"))
2359				$$ = IPTOS_THROUGHPUT;
2360			else if (!strcmp($2, "reliability"))
2361				$$ = IPTOS_RELIABILITY;
2362			else if ($2[0] == '0' && $2[1] == 'x')
2363				$$ = strtoul($2, NULL, 16);
2364			else
2365				$$ = strtoul($2, NULL, 10);
2366			if (!$$ || $$ > 255) {
2367				yyerror("illegal tos value %s", $2);
2368				YYERROR;
2369			}
2370		}
2371		;
2372
2373keep		: KEEP STATE state_opt_spec	{
2374			$$.action = PF_STATE_NORMAL;
2375			$$.options = $3;
2376		}
2377		| MODULATE STATE state_opt_spec	{
2378			$$.action = PF_STATE_MODULATE;
2379			$$.options = $3;
2380		}
2381		| SYNPROXY STATE state_opt_spec {
2382			$$.action = PF_STATE_SYNPROXY;
2383			$$.options = $3;
2384		}
2385		;
2386
2387state_opt_spec	: '(' state_opt_list ')'	{ $$ = $2; }
2388		| /* empty */			{ $$ = NULL; }
2389		;
2390
2391state_opt_list	: state_opt_item		{ $$ = $1; }
2392		| state_opt_list comma state_opt_item {
2393			$1->tail->next = $3;
2394			$1->tail = $3;
2395			$$ = $1;
2396		}
2397		;
2398
2399state_opt_item	: MAXIMUM number		{
2400			$$ = calloc(1, sizeof(struct node_state_opt));
2401			if ($$ == NULL)
2402				err(1, "state_opt_item: calloc");
2403			$$->type = PF_STATE_OPT_MAX;
2404			$$->data.max_states = $2;
2405			$$->next = NULL;
2406			$$->tail = $$;
2407		}
2408		| STRING number			{
2409			int	i;
2410
2411			for (i = 0; pf_timeouts[i].name &&
2412			    strcmp(pf_timeouts[i].name, $1); ++i)
2413				;	/* nothing */
2414			if (!pf_timeouts[i].name) {
2415				yyerror("illegal timeout name %s", $1);
2416				YYERROR;
2417			}
2418			if (strchr(pf_timeouts[i].name, '.') == NULL) {
2419				yyerror("illegal state timeout %s", $1);
2420				YYERROR;
2421			}
2422			$$ = calloc(1, sizeof(struct node_state_opt));
2423			if ($$ == NULL)
2424				err(1, "state_opt_item: calloc");
2425			$$->type = PF_STATE_OPT_TIMEOUT;
2426			$$->data.timeout.number = pf_timeouts[i].timeout;
2427			$$->data.timeout.seconds = $2;
2428			$$->next = NULL;
2429			$$->tail = $$;
2430		}
2431		;
2432
2433label		: LABEL STRING			{
2434			if (($$ = strdup($2)) == NULL)
2435				err(1, "rule label strdup() failed");
2436		}
2437		;
2438
2439qname		: QUEUE STRING				{
2440			if (($$.qname = strdup($2)) == NULL)
2441				err(1, "qname strdup() failed");
2442		}
2443		| QUEUE '(' STRING ')'			{
2444			if (($$.qname = strdup($3)) == NULL)
2445				err(1, "qname strdup() failed");
2446		}
2447		| QUEUE '(' STRING comma STRING ')'	{
2448			if (($$.qname = strdup($3)) == NULL ||
2449			    ($$.pqname = strdup($5)) == NULL)
2450				err(1, "qname strdup() failed");
2451		}
2452		;
2453
2454no		: /* empty */			{ $$ = 0; }
2455		| NO				{ $$ = 1; }
2456		;
2457
2458rport		: STRING			{
2459			char	*p = strchr($1, ':');
2460
2461			if (p == NULL) {
2462				if (($$.a = getservice($1)) == -1)
2463					YYERROR;
2464				$$.b = $$.t = 0;
2465			} else if (!strcmp(p+1, "*")) {
2466				*p = 0;
2467				if (($$.a = getservice($1)) == -1)
2468					YYERROR;
2469				$$.b = 0;
2470				$$.t = 1;
2471			} else {
2472				*p++ = 0;
2473				if (($$.a = getservice($1)) == -1 ||
2474				    ($$.b = getservice(p)) == -1)
2475					YYERROR;
2476				if ($$.a == $$.b)
2477					$$.b = 0;
2478				$$.t = 0;
2479			}
2480		}
2481		;
2482
2483redirspec	: host				{ $$ = $1; }
2484		| '{' redir_host_list '}'	{ $$ = $2; }
2485		;
2486
2487redir_host_list	: host				{ $$ = $1; }
2488		| redir_host_list comma host	{
2489			$1->tail->next = $3;
2490			$1->tail = $3->tail;
2491			$$ = $1;
2492		}
2493		;
2494
2495redirpool	: /* empty */			{ $$ = NULL; }
2496		| ARROW redirspec		{
2497			$$ = calloc(1, sizeof(struct redirection));
2498			if ($$ == NULL)
2499				err(1, "redirection: calloc");
2500			$$->host = $2;
2501			$$->rport.a = $$->rport.b = $$->rport.t = 0;
2502		}
2503		| ARROW redirspec PORT rport	{
2504			$$ = calloc(1, sizeof(struct redirection));
2505			if ($$ == NULL)
2506				err(1, "redirection: calloc");
2507			$$->host = $2;
2508			$$->rport = $4;
2509		}
2510		;
2511
2512hashkey		: /* empty */
2513		{
2514			$$ = calloc(1, sizeof(struct pf_poolhashkey));
2515			if ($$ == NULL)
2516				err(1, "hashkey: calloc");
2517			$$->key32[0] = arc4random();
2518			$$->key32[1] = arc4random();
2519			$$->key32[2] = arc4random();
2520			$$->key32[3] = arc4random();
2521		}
2522		| string
2523		{
2524			if (!strncmp($1, "0x", 2)) {
2525				if (strlen($1) != 34) {
2526					yyerror("hex key must be 128 bits "
2527						"(32 hex digits) long");
2528					YYERROR;
2529				}
2530				$$ = calloc(1, sizeof(struct pf_poolhashkey));
2531				if ($$ == NULL)
2532					err(1, "hashkey: calloc");
2533
2534				if (sscanf($1, "0x%8x%8x%8x%8x",
2535				    &$$->key32[0], &$$->key32[1],
2536				    &$$->key32[2], &$$->key32[3]) != 4) {
2537					free($$);
2538					yyerror("invalid hex key");
2539					YYERROR;
2540				}
2541			} else {
2542				MD5_CTX	context;
2543
2544				$$ = calloc(1, sizeof(struct pf_poolhashkey));
2545				if ($$ == NULL)
2546					err(1, "hashkey: calloc");
2547				MD5Init(&context);
2548				MD5Update(&context, (unsigned char *)$1,
2549				    strlen($1));
2550				MD5Final((unsigned char *)$$, &context);
2551				HTONL($$->key32[0]);
2552				HTONL($$->key32[1]);
2553				HTONL($$->key32[2]);
2554				HTONL($$->key32[3]);
2555			}
2556		}
2557		;
2558
2559pooltype	: /* empty */
2560		{
2561			$$.type = PF_POOL_NONE;
2562			$$.key = NULL;
2563		}
2564		| BITMASK
2565		{
2566			$$.type = PF_POOL_BITMASK;
2567			$$.key = NULL;
2568		}
2569		| RANDOM
2570		{
2571			$$.type = PF_POOL_RANDOM;
2572			$$.key = NULL;
2573		}
2574		| SOURCEHASH hashkey
2575		{
2576			$$.type = PF_POOL_SRCHASH;
2577			$$.key = $2;
2578		}
2579		| ROUNDROBIN
2580		{
2581			$$.type = PF_POOL_ROUNDROBIN;
2582			$$.key = NULL;
2583		}
2584		;
2585
2586staticport	: /* empty */			{ $$ = 0; }
2587		| STATICPORT			{ $$ = 1; }
2588		;
2589
2590redirection	: /* empty */			{ $$ = NULL; }
2591		| ARROW host			{
2592			$$ = calloc(1, sizeof(struct redirection));
2593			if ($$ == NULL)
2594				err(1, "redirection: calloc");
2595			$$->host = $2;
2596			$$->rport.a = $$->rport.b = $$->rport.t = 0;
2597		}
2598		| ARROW host PORT rport	{
2599			$$ = calloc(1, sizeof(struct redirection));
2600			if ($$ == NULL)
2601				err(1, "redirection: calloc");
2602			$$->host = $2;
2603			$$->rport = $4;
2604		}
2605		;
2606
2607natpass		: /* empty */	{ $$ = 0; }
2608		| PASS		{ $$ = 1; }
2609		;
2610
2611nataction	: no NAT natpass {
2612			$$.b2 = $$.w = 0;
2613			if ($1)
2614				$$.b1 = PF_NONAT;
2615			else
2616				$$.b1 = PF_NAT;
2617			$$.b2 = $3;
2618		}
2619		| no RDR natpass {
2620			$$.b2 = $$.w = 0;
2621			if ($1)
2622				$$.b1 = PF_NORDR;
2623			else
2624				$$.b1 = PF_RDR;
2625			$$.b2 = $3;
2626		}
2627		;
2628
2629natrule		: nataction interface af proto fromto tag redirpool pooltype
2630		  staticport
2631		{
2632			struct pf_rule	r;
2633
2634			if (check_rulestate(PFCTL_STATE_NAT))
2635				YYERROR;
2636
2637			memset(&r, 0, sizeof(r));
2638
2639			r.action = $1.b1;
2640			r.natpass = $1.b2;
2641			r.af = $3;
2642
2643			if (!r.af) {
2644				if ($5.src.host && $5.src.host->af &&
2645				    !$5.src.host->ifindex)
2646					r.af = $5.src.host->af;
2647				else if ($5.dst.host && $5.dst.host->af &&
2648				    !$5.dst.host->ifindex)
2649					r.af = $5.dst.host->af;
2650			}
2651
2652			if ($6 != NULL)
2653				if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) >
2654				    PF_TAG_NAME_SIZE) {
2655					yyerror("tag too long, max %u chars",
2656					    PF_TAG_NAME_SIZE - 1);
2657					YYERROR;
2658				}
2659
2660			if (r.action == PF_NONAT || r.action == PF_NORDR) {
2661				if ($7 != NULL) {
2662					yyerror("translation rule with 'no' "
2663					    "does not need '->'");
2664					YYERROR;
2665				}
2666			} else {
2667				if ($7 == NULL || $7->host == NULL) {
2668					yyerror("translation rule requires '-> "
2669					    "address'");
2670					YYERROR;
2671				}
2672				if (!r.af && ! $7->host->ifindex)
2673					r.af = $7->host->af;
2674
2675				remove_invalid_hosts(&$7->host, &r.af);
2676				if (invalid_redirect($7->host, r.af))
2677					YYERROR;
2678				if (check_netmask($7->host, r.af))
2679					YYERROR;
2680
2681				r.rpool.proxy_port[0] = ntohs($7->rport.a);
2682
2683				switch (r.action) {
2684				case PF_RDR:
2685					if (!$7->rport.b && $7->rport.t &&
2686					    $5.dst.port != NULL) {
2687						r.rpool.proxy_port[1] =
2688						    ntohs($7->rport.a) +
2689						    (ntohs($5.dst.port->port[1]) -
2690						    ntohs($5.dst.port->port[0]));
2691					} else
2692						r.rpool.proxy_port[1] =
2693						    ntohs($7->rport.b);
2694					break;
2695				case PF_NAT:
2696					r.rpool.proxy_port[1] = ntohs($7->rport.b);
2697					if (!r.rpool.proxy_port[0] &&
2698					    !r.rpool.proxy_port[1]) {
2699						r.rpool.proxy_port[0] =
2700						    PF_NAT_PROXY_PORT_LOW;
2701						r.rpool.proxy_port[1] =
2702						    PF_NAT_PROXY_PORT_HIGH;
2703					} else if (!r.rpool.proxy_port[1])
2704						r.rpool.proxy_port[1] =
2705						    r.rpool.proxy_port[0];
2706					break;
2707				default:
2708					break;
2709				}
2710
2711				r.rpool.opts = $8.type;
2712				if (r.rpool.opts == PF_POOL_NONE)
2713					r.rpool.opts = PF_POOL_ROUNDROBIN;
2714				if (r.rpool.opts != PF_POOL_ROUNDROBIN)
2715					if (disallow_table($7->host, "tables "
2716					    "are only supported in round-robin "
2717					    "redirection pools"))
2718						YYERROR;
2719				if ($7->host->next) {
2720					if (r.rpool.opts !=
2721					    PF_POOL_ROUNDROBIN) {
2722						yyerror("only round-robin "
2723						    "valid for multiple "
2724						    "redirection addresses");
2725						YYERROR;
2726					}
2727				} else {
2728					if ((r.af == AF_INET &&
2729					    unmask(&$7->host->addr.v.a.mask,
2730					    r.af) == 32) ||
2731					    (r.af == AF_INET6 &&
2732					    unmask(&$7->host->addr.v.a.mask,
2733					    r.af) == 128)) {
2734						r.rpool.opts = PF_POOL_NONE;
2735					}
2736				}
2737			}
2738
2739			if ($8.key != NULL)
2740				memcpy(&r.rpool.key, $8.key,
2741				    sizeof(struct pf_poolhashkey));
2742
2743			if ($9 != 0) {
2744				if (r.action != PF_NAT) {
2745					yyerror("the 'static-port' option is "
2746					    "only valid with nat rules");
2747					YYERROR;
2748				}
2749				if (r.rpool.proxy_port[0] !=
2750				    PF_NAT_PROXY_PORT_LOW &&
2751				    r.rpool.proxy_port[1] !=
2752				    PF_NAT_PROXY_PORT_HIGH) {
2753					yyerror("the 'static-port' option can't"
2754					    " be used when specifying a port"
2755					    " range");
2756					YYERROR;
2757				}
2758				r.rpool.proxy_port[0] = 0;
2759				r.rpool.proxy_port[1] = 0;
2760			}
2761
2762			expand_rule(&r, $2, $7 == NULL ? NULL : $7->host, $4,
2763			    $5.src_os, $5.src.host, $5.src.port, $5.dst.host,
2764			    $5.dst.port, 0, 0, 0);
2765			free($7);
2766		}
2767		;
2768
2769binatrule	: no BINAT natpass interface af proto FROM host TO ipspec tag
2770		  redirection
2771		{
2772			struct pf_rule		binat;
2773			struct pf_pooladdr	*pa;
2774
2775			if (check_rulestate(PFCTL_STATE_NAT))
2776				YYERROR;
2777
2778			memset(&binat, 0, sizeof(binat));
2779
2780			if ($1)
2781				binat.action = PF_NOBINAT;
2782			else
2783				binat.action = PF_BINAT;
2784			binat.natpass = $3;
2785			binat.af = $5;
2786			if (!binat.af && $8 != NULL && $8->af)
2787				binat.af = $8->af;
2788			if (!binat.af && $10 != NULL && $10->af)
2789				binat.af = $10->af;
2790			if (!binat.af && $12 != NULL && $12->host)
2791				binat.af = $12->host->af;
2792			if (!binat.af) {
2793				yyerror("address family (inet/inet6) "
2794				    "undefined");
2795				YYERROR;
2796			}
2797
2798			if ($4 != NULL) {
2799				memcpy(binat.ifname, $4->ifname,
2800				    sizeof(binat.ifname));
2801				free($4);
2802			}
2803			if ($11 != NULL)
2804				if (strlcpy(binat.tagname, $11,
2805				    PF_TAG_NAME_SIZE) > PF_TAG_NAME_SIZE) {
2806					yyerror("tag too long, max %u chars",
2807					    PF_TAG_NAME_SIZE - 1);
2808					YYERROR;
2809				}
2810
2811			if ($6 != NULL) {
2812				binat.proto = $6->proto;
2813				free($6);
2814			}
2815
2816			if ($8 != NULL && disallow_table($8, "invalid use of "
2817			    "table <%s> as the source address of a binat rule"))
2818				YYERROR;
2819			if ($12 != NULL && $12->host != NULL && disallow_table(
2820			    $12->host, "invalid use of table <%s> as the "
2821			    "redirect address of a binat rule"))
2822				YYERROR;
2823
2824			if ($8 != NULL) {
2825				if ($8->next) {
2826					yyerror("multiple binat ip addresses");
2827					YYERROR;
2828				}
2829				if ($8->addr.type == PF_ADDR_DYNIFTL)
2830					$8->af = binat.af;
2831				if ($8->af != binat.af) {
2832					yyerror("binat ip versions must match");
2833					YYERROR;
2834				}
2835				if (check_netmask($8, binat.af))
2836					YYERROR;
2837				memcpy(&binat.src.addr, &$8->addr,
2838				    sizeof(binat.src.addr));
2839				free($8);
2840			}
2841			if ($10 != NULL) {
2842				if ($10->next) {
2843					yyerror("multiple binat ip addresses");
2844					YYERROR;
2845				}
2846				if ($10->af != binat.af && $10->af) {
2847					yyerror("binat ip versions must match");
2848					YYERROR;
2849				}
2850				if (check_netmask($10, binat.af))
2851					YYERROR;
2852				memcpy(&binat.dst.addr, &$10->addr,
2853				    sizeof(binat.dst.addr));
2854				binat.dst.not = $10->not;
2855				free($10);
2856			}
2857
2858			if (binat.action == PF_NOBINAT) {
2859				if ($12 != NULL) {
2860					yyerror("'no binat' rule does not need"
2861					    " '->'");
2862					YYERROR;
2863				}
2864			} else {
2865				if ($12 == NULL || $12->host == NULL) {
2866					yyerror("'binat' rule requires"
2867					    " '-> address'");
2868					YYERROR;
2869				}
2870
2871				remove_invalid_hosts(&$12->host, &binat.af);
2872				if (invalid_redirect($12->host, binat.af))
2873					YYERROR;
2874				if ($12->host->next != NULL) {
2875					yyerror("binat rule must redirect to "
2876					    "a single address");
2877					YYERROR;
2878				}
2879				if (check_netmask($12->host, binat.af))
2880					YYERROR;
2881
2882				if (!PF_AZERO(&binat.src.addr.v.a.mask,
2883				    binat.af) &&
2884				    !PF_AEQ(&binat.src.addr.v.a.mask,
2885				    &$12->host->addr.v.a.mask, binat.af)) {
2886					yyerror("'binat' source mask and "
2887					    "redirect mask must be the same");
2888					YYERROR;
2889				}
2890
2891				TAILQ_INIT(&binat.rpool.list);
2892				pa = calloc(1, sizeof(struct pf_pooladdr));
2893				if (pa == NULL)
2894					err(1, "binat: calloc");
2895				pa->addr = $12->host->addr;
2896				pa->ifname[0] = 0;
2897				TAILQ_INSERT_TAIL(&binat.rpool.list,
2898				    pa, entries);
2899
2900				free($12);
2901			}
2902
2903			pfctl_add_rule(pf, &binat);
2904		}
2905		;
2906
2907tag		: /* empty */		{ $$ = NULL; }
2908		| TAG STRING		{ $$ = $2; }
2909
2910route_host	: STRING			{
2911			struct node_host	*n;
2912
2913			$$ = calloc(1, sizeof(struct node_host));
2914			if ($$ == NULL)
2915				err(1, "route_host: calloc");
2916			if (($$->ifname = strdup($1)) == NULL)
2917				err(1, "routeto: strdup");
2918			if ((n = ifa_exists($$->ifname)) == NULL) {
2919				yyerror("routeto: unknown interface %s",
2920				    $$->ifname);
2921				YYERROR;
2922			}
2923			set_ipmask($$, 128);
2924			$$->next = NULL;
2925			$$->tail = $$;
2926		}
2927		| '(' STRING host ')'		{
2928			struct node_host	*n;
2929
2930			$$ = $3;
2931			if (($$->ifname = strdup($2)) == NULL)
2932				err(1, "routeto: strdup");
2933			if ((n = ifa_exists($$->ifname)) == NULL) {
2934				yyerror("routeto: unknown interface %s",
2935				    $$->ifname);
2936				YYERROR;
2937			}
2938		}
2939		;
2940
2941route_host_list	: route_host				{ $$ = $1; }
2942		| route_host_list comma route_host	{
2943			if ($1->af == 0)
2944				$1->af = $3->af;
2945			if ($1->af != $3->af) {
2946				yyerror("all pool addresses must be in the "
2947				    "same address family");
2948				YYERROR;
2949			}
2950			$1->tail->next = $3;
2951			$1->tail = $3->tail;
2952			$$ = $1;
2953		}
2954		;
2955
2956routespec	: route_host			{ $$ = $1; }
2957		| '{' route_host_list '}'	{ $$ = $2; }
2958		;
2959
2960route		: /* empty */			{
2961			$$.host = NULL;
2962			$$.rt = 0;
2963			$$.pool_opts = 0;
2964		}
2965		| FASTROUTE {
2966			$$.host = NULL;
2967			$$.rt = PF_FASTROUTE;
2968			$$.pool_opts = 0;
2969		}
2970		| ROUTETO routespec pooltype {
2971			$$.host = $2;
2972			$$.rt = PF_ROUTETO;
2973			$$.pool_opts = $3.type;
2974			if ($3.key != NULL)
2975				$$.key = $3.key;
2976		}
2977		| REPLYTO routespec pooltype {
2978			$$.host = $2;
2979			$$.rt = PF_REPLYTO;
2980			$$.pool_opts = $3.type;
2981			if ($3.key != NULL)
2982				$$.key = $3.key;
2983		}
2984		| DUPTO routespec pooltype {
2985			$$.host = $2;
2986			$$.rt = PF_DUPTO;
2987			$$.pool_opts = $3.type;
2988			if ($3.key != NULL)
2989				$$.key = $3.key;
2990		}
2991		;
2992
2993timeout_spec	: STRING number
2994		{
2995			if (check_rulestate(PFCTL_STATE_OPTION))
2996				YYERROR;
2997			if (pfctl_set_timeout(pf, $1, $2, 0) != 0) {
2998				yyerror("unknown timeout %s", $1);
2999				YYERROR;
3000			}
3001		}
3002		;
3003
3004timeout_list	: timeout_list comma timeout_spec
3005		| timeout_spec
3006		;
3007
3008limit_spec	: STRING number
3009		{
3010			if (check_rulestate(PFCTL_STATE_OPTION))
3011				YYERROR;
3012			if (pfctl_set_limit(pf, $1, $2) != 0) {
3013				yyerror("unable to set limit %s %u", $1, $2);
3014				YYERROR;
3015			}
3016		}
3017
3018limit_list	: limit_list comma limit_spec
3019		| limit_spec
3020		;
3021
3022comma		: ','
3023		| /* empty */
3024		;
3025
3026yesno		: NO			{ $$ = 0; }
3027		| STRING		{
3028			if (!strcmp($1, "yes"))
3029				$$ = 1;
3030			else
3031				YYERROR;
3032		}
3033
3034unaryop		: '='		{ $$ = PF_OP_EQ; }
3035		| '!' '='	{ $$ = PF_OP_NE; }
3036		| '<' '='	{ $$ = PF_OP_LE; }
3037		| '<'		{ $$ = PF_OP_LT; }
3038		| '>' '='	{ $$ = PF_OP_GE; }
3039		| '>'		{ $$ = PF_OP_GT; }
3040		;
3041
3042%%
3043
3044int
3045yyerror(const char *fmt, ...)
3046{
3047	va_list		 ap;
3048	extern char	*infile;
3049
3050	errors = 1;
3051	va_start(ap, fmt);
3052	fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
3053	vfprintf(stderr, fmt, ap);
3054	fprintf(stderr, "\n");
3055	va_end(ap);
3056	return (0);
3057}
3058
3059int
3060disallow_table(struct node_host *h, const char *fmt)
3061{
3062	for (; h != NULL; h = h->next)
3063		if (h->addr.type == PF_ADDR_TABLE) {
3064			yyerror(fmt, h->addr.v.tblname);
3065			return (1);
3066		}
3067	return (0);
3068}
3069
3070int
3071rule_consistent(struct pf_rule *r)
3072{
3073	int	problems = 0;
3074
3075	switch (r->action) {
3076	case PF_PASS:
3077	case PF_DROP:
3078	case PF_SCRUB:
3079		problems = filter_consistent(r);
3080		break;
3081	case PF_NAT:
3082	case PF_NONAT:
3083		problems = nat_consistent(r);
3084		break;
3085	case PF_RDR:
3086	case PF_NORDR:
3087		problems = rdr_consistent(r);
3088		break;
3089	case PF_BINAT:
3090	case PF_NOBINAT:
3091	default:
3092		break;
3093	}
3094	return (problems);
3095}
3096
3097int
3098filter_consistent(struct pf_rule *r)
3099{
3100	int	problems = 0;
3101
3102	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
3103	    (r->src.port_op || r->dst.port_op)) {
3104		yyerror("port only applies to tcp/udp");
3105		problems++;
3106	}
3107	if (r->src.port_op == PF_OP_RRG || r->dst.port_op == PF_OP_RRG) {
3108		yyerror("the ':' port operator only applies to rdr");
3109		problems++;
3110	}
3111	if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
3112	    (r->type || r->code)) {
3113		yyerror("icmp-type/code only applies to icmp");
3114		problems++;
3115	}
3116	if (!r->af && (r->type || r->code)) {
3117		yyerror("must indicate address family with icmp-type/code");
3118		problems++;
3119	}
3120	if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
3121	    (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
3122		yyerror("proto %s doesn't match address family %s",
3123		    r->proto == IPPROTO_ICMP ? "icmp" : "icmp6",
3124		    r->af == AF_INET ? "inet" : "inet6");
3125		problems++;
3126	}
3127	if ((r->keep_state == PF_STATE_MODULATE || r->keep_state ==
3128	    PF_STATE_SYNPROXY) && r->proto && r->proto != IPPROTO_TCP) {
3129		yyerror("modulate/synproxy state can only be applied to "
3130		    "TCP rules");
3131		problems++;
3132	}
3133	if (r->allow_opts && r->action != PF_PASS) {
3134		yyerror("allow-opts can only be specified for pass rules");
3135		problems++;
3136	}
3137	if (!r->af && (r->src.addr.type == PF_ADDR_DYNIFTL ||
3138	    r->dst.addr.type == PF_ADDR_DYNIFTL)) {
3139		yyerror("dynamic addresses require address family "
3140		    "(inet/inet6)");
3141		problems++;
3142	}
3143	if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
3144	    r->dst.port_op || r->flagset || r->type || r->code)) {
3145		yyerror("fragments can be filtered only on IP header fields");
3146		problems++;
3147	}
3148	if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) {
3149		yyerror("return-rst can only be applied to TCP rules");
3150		problems++;
3151	}
3152	if (r->action == PF_DROP && r->keep_state) {
3153		yyerror("keep state on block rules doesn't make sense");
3154		problems++;
3155	}
3156	if ((r->tagname[0] || r->match_tagname[0]) && !r->keep_state &&
3157	    r->action == PF_PASS) {
3158		yyerror("tags cannot be used without keep state");
3159		problems++;
3160	}
3161	return (-problems);
3162}
3163
3164int
3165nat_consistent(struct pf_rule *r)
3166{
3167	int			 problems = 0;
3168	struct pf_pooladdr	*pa;
3169
3170	if (r->src.port_op == PF_OP_RRG || r->dst.port_op == PF_OP_RRG) {
3171		yyerror("the ':' port operator only applies to rdr");
3172		problems++;
3173	}
3174	if (!r->af) {
3175		TAILQ_FOREACH(pa, &r->rpool.list, entries) {
3176			if (pa->addr.type == PF_ADDR_DYNIFTL) {
3177				yyerror("dynamic addresses require "
3178				    "address family (inet/inet6)");
3179				problems++;
3180				break;
3181			}
3182		}
3183	}
3184	return (-problems);
3185}
3186
3187int
3188rdr_consistent(struct pf_rule *r)
3189{
3190	int			 problems = 0;
3191	struct pf_pooladdr	*pa;
3192
3193	if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP) {
3194		if (r->src.port_op) {
3195			yyerror("src port only applies to tcp/udp");
3196			problems++;
3197		}
3198		if (r->dst.port_op) {
3199			yyerror("dst port only applies to tcp/udp");
3200			problems++;
3201		}
3202		if (r->rpool.proxy_port[0]) {
3203			yyerror("rpool port only applies to tcp/udp");
3204			problems++;
3205		}
3206	}
3207	if (r->dst.port_op &&
3208	    r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) {
3209		yyerror("invalid port operator for rdr destination port");
3210		problems++;
3211	}
3212	if (r->src.port_op == PF_OP_RRG) {
3213		yyerror("the ':' port operator only applies to rdr "
3214		    "destination port");
3215		problems++;
3216	}
3217	if (!r->af) {
3218		if (r->src.addr.type == PF_ADDR_DYNIFTL ||
3219		    r->dst.addr.type == PF_ADDR_DYNIFTL) {
3220			yyerror("dynamic addresses require address family "
3221			    "(inet/inet6)");
3222			problems++;
3223		} else {
3224			TAILQ_FOREACH(pa, &r->rpool.list, entries) {
3225				if (pa->addr.type == PF_ADDR_DYNIFTL) {
3226					yyerror("dynamic addresses require "
3227					    "address family (inet/inet6)");
3228					problems++;
3229					break;
3230				}
3231			}
3232		}
3233	}
3234	return (-problems);
3235}
3236
3237int
3238process_tabledef(char *name, struct table_opts *opts)
3239{
3240	struct pfr_buffer	 ab;
3241	struct node_tinit	*ti;
3242
3243	bzero(&ab, sizeof(ab));
3244	ab.pfrb_type = PFRB_ADDRS;
3245	SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) {
3246		if (ti->file)
3247			if (pfr_buf_load(&ab, ti->file, 0, append_addr)) {
3248				if (errno)
3249					yyerror("cannot load \"%s\": %s",
3250					    ti->file, strerror(errno));
3251				else
3252					yyerror("file \"%s\" contains bad data",
3253					    ti->file);
3254				goto _error;
3255			}
3256		if (ti->host)
3257			if (append_addr_host(&ab, ti->host, 0, 0)) {
3258				yyerror("cannot create address buffer: %s",
3259				    strerror(errno));
3260				goto _error;
3261			}
3262	}
3263	if (pf->opts & PF_OPT_VERBOSE)
3264		print_tabledef(name, opts->flags, opts->init_addr,
3265		    &opts->init_nodes);
3266	if (!(pf->opts & PF_OPT_NOACTION) &&
3267	    pfctl_define_table(name, opts->flags, opts->init_addr,
3268	    pf->anchor, pf->ruleset, &ab, pf->tticket)) {
3269		yyerror("cannot define table %s: %s", name,
3270		    pfr_strerror(errno));
3271		goto _error;
3272	}
3273	pf->tdirty = 1;
3274	pfr_buf_clear(&ab);
3275	return (0);
3276_error:
3277	pfr_buf_clear(&ab);
3278	return (-1);
3279}
3280
3281struct keywords {
3282	const char	*k_name;
3283	int		 k_val;
3284};
3285
3286/* macro gore, but you should've seen the prior indentation nightmare... */
3287
3288#define FREE_LIST(T,r) \
3289	do { \
3290		T *p, *node = r; \
3291		while (node != NULL) { \
3292			p = node; \
3293			node = node->next; \
3294			free(p); \
3295		} \
3296	} while (0)
3297
3298#define LOOP_THROUGH(T,n,r,C) \
3299	do { \
3300		T *n; \
3301		if (r == NULL) { \
3302			r = calloc(1, sizeof(T)); \
3303			if (r == NULL) \
3304				err(1, "LOOP: calloc"); \
3305			r->next = NULL; \
3306		} \
3307		n = r; \
3308		while (n != NULL) { \
3309			do { \
3310				C; \
3311			} while (0); \
3312			n = n->next; \
3313		} \
3314	} while (0)
3315
3316void
3317expand_label_str(char *label, const char *srch, const char *repl)
3318{
3319	char tmp[PF_RULE_LABEL_SIZE] = "";
3320	char *p, *q;
3321
3322	p = q = label;
3323	while ((q = strstr(p, srch)) != NULL) {
3324		*q = '\0';
3325		if ((strlcat(tmp, p, sizeof(tmp)) >= sizeof(tmp)) ||
3326		    (strlcat(tmp, repl, sizeof(tmp)) >= sizeof(tmp)))
3327			err(1, "expand_label: label too long");
3328		q += strlen(srch);
3329		p = q;
3330	}
3331	if (strlcat(tmp, p, sizeof(tmp)) >= sizeof(tmp))
3332		err(1, "expand_label: label too long");
3333	strlcpy(label, tmp, PF_RULE_LABEL_SIZE);	/* always fits */
3334}
3335
3336void
3337expand_label_if(const char *name, char *label, const char *ifname)
3338{
3339	if (strstr(label, name) != NULL) {
3340		if (!*ifname)
3341			expand_label_str(label, name, "any");
3342		else
3343			expand_label_str(label, name, ifname);
3344	}
3345}
3346
3347void
3348expand_label_addr(const char *name, char *label, sa_family_t af,
3349    struct node_host *h)
3350{
3351	char tmp[64], tmp_not[66];
3352
3353	if (strstr(label, name) != NULL) {
3354		switch (h->addr.type) {
3355		case PF_ADDR_DYNIFTL:
3356			snprintf(tmp, sizeof(tmp), "(%s)", h->addr.v.ifname);
3357			break;
3358		case PF_ADDR_TABLE:
3359			snprintf(tmp, sizeof(tmp), "<%s>", h->addr.v.tblname);
3360			break;
3361		case PF_ADDR_NOROUTE:
3362			snprintf(tmp, sizeof(tmp), "no-route");
3363			break;
3364		case PF_ADDR_ADDRMASK:
3365			if (!af || (PF_AZERO(&h->addr.v.a.addr, af) &&
3366			    PF_AZERO(&h->addr.v.a.mask, af)))
3367				snprintf(tmp, sizeof(tmp), "any");
3368			else {
3369				char	a[48];
3370				int	bits;
3371
3372				if (inet_ntop(af, &h->addr.v.a.addr, a,
3373				    sizeof(a)) == NULL)
3374					snprintf(tmp, sizeof(tmp), "?");
3375				else {
3376					bits = unmask(&h->addr.v.a.mask, af);
3377					if ((af == AF_INET && bits < 32) ||
3378					    (af == AF_INET6 && bits < 128))
3379						snprintf(tmp, sizeof(tmp),
3380						   "%s/%d", a, bits);
3381					else
3382						snprintf(tmp, sizeof(tmp),
3383						    "%s", a);
3384				}
3385			}
3386			break;
3387		default:
3388			snprintf(tmp, sizeof(tmp), "?");
3389			break;
3390		}
3391
3392		if (h->not) {
3393			snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp);
3394			expand_label_str(label, name, tmp_not);
3395		} else
3396			expand_label_str(label, name, tmp);
3397	}
3398}
3399
3400void
3401expand_label_port(const char *name, char *label, struct node_port *port)
3402{
3403	char	 a1[6], a2[6], op[13] = "";
3404
3405	if (strstr(label, name) != NULL) {
3406		snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0]));
3407		snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1]));
3408		if (!port->op)
3409			;
3410		else if (port->op == PF_OP_IRG)
3411			snprintf(op, sizeof(op), "%s><%s", a1, a2);
3412		else if (port->op == PF_OP_XRG)
3413			snprintf(op, sizeof(op), "%s<>%s", a1, a2);
3414		else if (port->op == PF_OP_EQ)
3415			snprintf(op, sizeof(op), "%s", a1);
3416		else if (port->op == PF_OP_NE)
3417			snprintf(op, sizeof(op), "!=%s", a1);
3418		else if (port->op == PF_OP_LT)
3419			snprintf(op, sizeof(op), "<%s", a1);
3420		else if (port->op == PF_OP_LE)
3421			snprintf(op, sizeof(op), "<=%s", a1);
3422		else if (port->op == PF_OP_GT)
3423			snprintf(op, sizeof(op), ">%s", a1);
3424		else if (port->op == PF_OP_GE)
3425			snprintf(op, sizeof(op), ">=%s", a1);
3426		expand_label_str(label, name, op);
3427	}
3428}
3429
3430void
3431expand_label_proto(const char *name, char *label, u_int8_t proto)
3432{
3433	struct protoent *pe;
3434	char n[4];
3435
3436	if (strstr(label, name) != NULL) {
3437		pe = getprotobynumber(proto);
3438		if (pe != NULL)
3439			expand_label_str(label, name, pe->p_name);
3440		else {
3441			snprintf(n, sizeof(n), "%u", proto);
3442			expand_label_str(label, name, n);
3443		}
3444	}
3445}
3446
3447void
3448expand_label_nr(const char *name, char *label)
3449{
3450	char n[11];
3451
3452	if (strstr(label, name) != NULL) {
3453		snprintf(n, sizeof(n), "%u", pf->rule_nr);
3454		expand_label_str(label, name, n);
3455	}
3456}
3457
3458void
3459expand_label(char *label, const char *ifname, sa_family_t af,
3460    struct node_host *src_host, struct node_port *src_port,
3461    struct node_host *dst_host, struct node_port *dst_port,
3462    u_int8_t proto)
3463{
3464	expand_label_if("$if", label, ifname);
3465	expand_label_addr("$srcaddr", label, af, src_host);
3466	expand_label_addr("$dstaddr", label, af, dst_host);
3467	expand_label_port("$srcport", label, src_port);
3468	expand_label_port("$dstport", label, dst_port);
3469	expand_label_proto("$proto", label, proto);
3470	expand_label_nr("$nr", label);
3471}
3472
3473int
3474expand_altq(struct pf_altq *a, struct node_if *interfaces,
3475    struct node_queue *nqueues, struct node_queue_bw bwspec,
3476    struct node_queue_opt *opts)
3477{
3478	struct pf_altq		 pa, pb;
3479	char			 qname[PF_QNAME_SIZE];
3480	struct node_queue	*n;
3481	struct node_queue_bw	 bw;
3482	int			 errs = 0;
3483
3484	if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
3485		FREE_LIST(struct node_if, interfaces);
3486		FREE_LIST(struct node_queue, nqueues);
3487		return (0);
3488	}
3489
3490	LOOP_THROUGH(struct node_if, interface, interfaces,
3491		memcpy(&pa, a, sizeof(struct pf_altq));
3492		if (strlcpy(pa.ifname, interface->ifname,
3493		    sizeof(pa.ifname)) >= sizeof(pa.ifname))
3494			errx(1, "expand_altq: strlcpy");
3495
3496		if (interface->not) {
3497			yyerror("altq on ! <interface> is not supported");
3498			errs++;
3499		} else {
3500			if (eval_pfaltq(pf, &pa, &bwspec, opts))
3501				errs++;
3502			else
3503				if (pfctl_add_altq(pf, &pa))
3504					errs++;
3505
3506			if (pf->opts & PF_OPT_VERBOSE) {
3507				print_altq(&pf->paltq->altq, 0,
3508				    &bwspec, opts);
3509				if (nqueues && nqueues->tail) {
3510					printf("queue { ");
3511					LOOP_THROUGH(struct node_queue, queue,
3512					    nqueues,
3513						printf("%s ",
3514						    queue->queue);
3515					);
3516					printf("}");
3517				}
3518				printf("\n");
3519			}
3520
3521			if (pa.scheduler == ALTQT_CBQ ||
3522			    pa.scheduler == ALTQT_HFSC) {
3523				/* now create a root queue */
3524				memset(&pb, 0, sizeof(struct pf_altq));
3525				if (strlcpy(qname, "root_", sizeof(qname)) >=
3526				    sizeof(qname))
3527					errx(1, "expand_altq: strlcpy");
3528				if (strlcat(qname, interface->ifname,
3529				    sizeof(qname)) >= sizeof(qname))
3530					errx(1, "expand_altq: strlcat");
3531				if (strlcpy(pb.qname, qname,
3532				    sizeof(pb.qname)) >= sizeof(pb.qname))
3533					errx(1, "expand_altq: strlcpy");
3534				if (strlcpy(pb.ifname, interface->ifname,
3535				    sizeof(pb.ifname)) >= sizeof(pb.ifname))
3536					errx(1, "expand_altq: strlcpy");
3537				pb.qlimit = pa.qlimit;
3538				pb.scheduler = pa.scheduler;
3539				bw.bw_absolute = pa.ifbandwidth;
3540				bw.bw_percent = 0;
3541				if (eval_pfqueue(pf, &pb, &bw, opts))
3542					errs++;
3543				else
3544					if (pfctl_add_altq(pf, &pb))
3545						errs++;
3546			}
3547
3548			LOOP_THROUGH(struct node_queue, queue, nqueues,
3549				n = calloc(1, sizeof(struct node_queue));
3550				if (n == NULL)
3551					err(1, "expand_altq: calloc");
3552				if (pa.scheduler == ALTQT_CBQ ||
3553				    pa.scheduler == ALTQT_HFSC)
3554					if (strlcpy(n->parent, qname,
3555					    sizeof(n->parent)) >=
3556					    sizeof(n->parent))
3557						errx(1, "expand_altq: strlcpy");
3558				if (strlcpy(n->queue, queue->queue,
3559				    sizeof(n->queue)) >= sizeof(n->queue))
3560					errx(1, "expand_altq: strlcpy");
3561				if (strlcpy(n->ifname, interface->ifname,
3562				    sizeof(n->ifname)) >= sizeof(n->ifname))
3563					errx(1, "expand_altq: strlcpy");
3564				n->scheduler = pa.scheduler;
3565				n->next = NULL;
3566				n->tail = n;
3567				if (queues == NULL)
3568					queues = n;
3569				else {
3570					queues->tail->next = n;
3571					queues->tail = n;
3572				}
3573			);
3574		}
3575	);
3576	FREE_LIST(struct node_if, interfaces);
3577	FREE_LIST(struct node_queue, nqueues);
3578
3579	return (errs);
3580}
3581
3582int
3583expand_queue(struct pf_altq *a, struct node_if *interfaces,
3584    struct node_queue *nqueues, struct node_queue_bw bwspec,
3585    struct node_queue_opt *opts)
3586{
3587	struct node_queue	*n, *nq;
3588	struct pf_altq		 pa;
3589	u_int8_t		 found = 0;
3590	u_int8_t		 errs = 0;
3591
3592	if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
3593		FREE_LIST(struct node_queue, nqueues);
3594		return (0);
3595	}
3596
3597	if (queues == NULL) {
3598		yyerror("queue %s has no parent", a->qname);
3599		FREE_LIST(struct node_queue, nqueues);
3600		return (1);
3601	}
3602
3603	LOOP_THROUGH(struct node_if, interface, interfaces,
3604		LOOP_THROUGH(struct node_queue, tqueue, queues,
3605			if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE) &&
3606			    (interface->ifname[0] == 0 ||
3607			    (!interface->not && !strncmp(interface->ifname,
3608			    tqueue->ifname, IFNAMSIZ)) ||
3609			    (interface->not && strncmp(interface->ifname,
3610			    tqueue->ifname, IFNAMSIZ)))) {
3611				/* found ourself in queues */
3612				found++;
3613
3614				memcpy(&pa, a, sizeof(struct pf_altq));
3615
3616				if (pa.scheduler != ALTQT_NONE &&
3617				    pa.scheduler != tqueue->scheduler) {
3618					yyerror("exactly one scheduler type "
3619					    "per interface allowed");
3620					return (1);
3621				}
3622				pa.scheduler = tqueue->scheduler;
3623
3624				/* scheduler dependent error checking */
3625				switch (pa.scheduler) {
3626				case ALTQT_PRIQ:
3627					if (nqueues != NULL) {
3628						yyerror("priq queues cannot "
3629						    "have child queues");
3630						return (1);
3631					}
3632					if (bwspec.bw_absolute > 0 ||
3633					    bwspec.bw_percent < 100) {
3634						yyerror("priq doesn't take "
3635						    "bandwidth");
3636						return (1);
3637					}
3638					break;
3639				default:
3640					break;
3641				}
3642
3643				if (strlcpy(pa.ifname, tqueue->ifname,
3644				    sizeof(pa.ifname)) >= sizeof(pa.ifname))
3645					errx(1, "expand_queue: strlcpy");
3646				if (strlcpy(pa.parent, tqueue->parent,
3647				    sizeof(pa.parent)) >= sizeof(pa.parent))
3648					errx(1, "expand_queue: strlcpy");
3649
3650				if (eval_pfqueue(pf, &pa, &bwspec, opts))
3651					errs++;
3652				else
3653					if (pfctl_add_altq(pf, &pa))
3654						errs++;
3655
3656				for (nq = nqueues; nq != NULL; nq = nq->next) {
3657					if (!strcmp(a->qname, nq->queue)) {
3658						yyerror("queue cannot have "
3659						    "itself as child");
3660						errs++;
3661						continue;
3662					}
3663					n = calloc(1,
3664					    sizeof(struct node_queue));
3665					if (n == NULL)
3666						err(1, "expand_queue: calloc");
3667					if (strlcpy(n->parent, a->qname,
3668					    sizeof(n->parent)) >=
3669					    sizeof(n->parent))
3670						errx(1, "expand_queue strlcpy");
3671					if (strlcpy(n->queue, nq->queue,
3672					    sizeof(n->queue)) >=
3673					    sizeof(n->queue))
3674						errx(1, "expand_queue strlcpy");
3675					if (strlcpy(n->ifname, tqueue->ifname,
3676					    sizeof(n->ifname)) >=
3677					    sizeof(n->ifname))
3678						errx(1, "expand_queue strlcpy");
3679					n->scheduler = tqueue->scheduler;
3680					n->next = NULL;
3681					n->tail = n;
3682					if (queues == NULL)
3683						queues = n;
3684					else {
3685						queues->tail->next = n;
3686						queues->tail = n;
3687					}
3688				}
3689				if ((pf->opts & PF_OPT_VERBOSE) && (
3690				    (found == 1 && interface->ifname[0] == 0) ||
3691				    (found > 0 && interface->ifname[0] != 0))) {
3692					print_queue(&pf->paltq->altq, 0,
3693					    &bwspec, interface->ifname[0] != 0,
3694					    opts);
3695					if (nqueues && nqueues->tail) {
3696						printf("{ ");
3697						LOOP_THROUGH(struct node_queue,
3698						    queue, nqueues,
3699							printf("%s ",
3700							    queue->queue);
3701						);
3702						printf("}");
3703					}
3704					printf("\n");
3705				}
3706			}
3707		);
3708	);
3709
3710	FREE_LIST(struct node_queue, nqueues);
3711	FREE_LIST(struct node_if, interfaces);
3712
3713	if (!found) {
3714		yyerror("queue %s has no parent", a->qname);
3715		errs++;
3716	}
3717
3718	if (errs)
3719		return (1);
3720	else
3721		return (0);
3722}
3723
3724void
3725expand_rule(struct pf_rule *r,
3726    struct node_if *interfaces, struct node_host *rpool_hosts,
3727    struct node_proto *protos, struct node_os *src_oses,
3728    struct node_host *src_hosts, struct node_port *src_ports,
3729    struct node_host *dst_hosts, struct node_port *dst_ports,
3730    struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types)
3731{
3732	sa_family_t		 af = r->af;
3733	int			 added = 0, error = 0;
3734	char			 ifname[IF_NAMESIZE];
3735	char			 label[PF_RULE_LABEL_SIZE];
3736	struct pf_pooladdr	*pa;
3737	struct node_host	*h;
3738	u_int8_t		 flags, flagset;
3739
3740	if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label))
3741		errx(1, "expand_rule: strlcpy");
3742	flags = r->flags;
3743	flagset = r->flagset;
3744
3745	LOOP_THROUGH(struct node_if, interface, interfaces,
3746	LOOP_THROUGH(struct node_proto, proto, protos,
3747	LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
3748	LOOP_THROUGH(struct node_host, src_host, src_hosts,
3749	LOOP_THROUGH(struct node_port, src_port, src_ports,
3750	LOOP_THROUGH(struct node_os, src_os, src_oses,
3751	LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
3752	LOOP_THROUGH(struct node_port, dst_port, dst_ports,
3753	LOOP_THROUGH(struct node_uid, uid, uids,
3754	LOOP_THROUGH(struct node_gid, gid, gids,
3755
3756		r->af = af;
3757		/* for link-local IPv6 address, interface must match up */
3758		if ((r->af && src_host->af && r->af != src_host->af) ||
3759		    (r->af && dst_host->af && r->af != dst_host->af) ||
3760		    (src_host->af && dst_host->af &&
3761		    src_host->af != dst_host->af) ||
3762		    (src_host->ifindex && dst_host->ifindex &&
3763		    src_host->ifindex != dst_host->ifindex) ||
3764		    (src_host->ifindex && if_nametoindex(interface->ifname) &&
3765		    src_host->ifindex != if_nametoindex(interface->ifname)) ||
3766		    (dst_host->ifindex && if_nametoindex(interface->ifname) &&
3767		    dst_host->ifindex != if_nametoindex(interface->ifname)))
3768			continue;
3769		if (!r->af && src_host->af)
3770			r->af = src_host->af;
3771		else if (!r->af && dst_host->af)
3772			r->af = dst_host->af;
3773
3774		if (if_indextoname(src_host->ifindex, ifname))
3775			memcpy(r->ifname, ifname, sizeof(r->ifname));
3776		else if (if_indextoname(dst_host->ifindex, ifname))
3777			memcpy(r->ifname, ifname, sizeof(r->ifname));
3778		else
3779			memcpy(r->ifname, interface->ifname, sizeof(r->ifname));
3780
3781		if (strlcpy(r->label, label, sizeof(r->label)) >=
3782		    sizeof(r->label))
3783			errx(1, "expand_rule: strlcpy");
3784		expand_label(r->label, r->ifname, r->af, src_host, src_port,
3785		    dst_host, dst_port, proto->proto);
3786
3787		error += check_netmask(src_host, r->af);
3788		error += check_netmask(dst_host, r->af);
3789
3790		r->ifnot = interface->not;
3791		r->proto = proto->proto;
3792		r->src.addr = src_host->addr;
3793		r->src.not = src_host->not;
3794		r->src.port[0] = src_port->port[0];
3795		r->src.port[1] = src_port->port[1];
3796		r->src.port_op = src_port->op;
3797		r->dst.addr = dst_host->addr;
3798		r->dst.not = dst_host->not;
3799		r->dst.port[0] = dst_port->port[0];
3800		r->dst.port[1] = dst_port->port[1];
3801		r->dst.port_op = dst_port->op;
3802		r->uid.op = uid->op;
3803		r->uid.uid[0] = uid->uid[0];
3804		r->uid.uid[1] = uid->uid[1];
3805		r->gid.op = gid->op;
3806		r->gid.gid[0] = gid->gid[0];
3807		r->gid.gid[1] = gid->gid[1];
3808		r->type = icmp_type->type;
3809		r->code = icmp_type->code;
3810
3811		if (r->proto && r->proto != IPPROTO_TCP) {
3812			r->flags = 0;
3813			r->flagset = 0;
3814		} else {
3815			r->flags = flags;
3816			r->flagset = flagset;
3817		}
3818		if (icmp_type->proto && r->proto != icmp_type->proto) {
3819			yyerror("icmp-type mismatch");
3820			error++;
3821		}
3822
3823		if (src_os && src_os->os) {
3824			r->os_fingerprint = pfctl_get_fingerprint(src_os->os);
3825			if ((pf->opts & PF_OPT_VERBOSE2) &&
3826			    r->os_fingerprint == PF_OSFP_NOMATCH)
3827				fprintf(stderr,
3828				    "warning: unknown '%s' OS fingerprint\n",
3829				    src_os->os);
3830		} else {
3831			r->os_fingerprint = PF_OSFP_ANY;
3832		}
3833
3834		TAILQ_INIT(&r->rpool.list);
3835		for (h = rpool_hosts; h != NULL; h = h->next) {
3836			pa = calloc(1, sizeof(struct pf_pooladdr));
3837			if (pa == NULL)
3838				err(1, "expand_rule: calloc");
3839			pa->addr = h->addr;
3840			if (h->ifname != NULL) {
3841				if (strlcpy(pa->ifname, h->ifname,
3842				    sizeof(pa->ifname)) >=
3843				    sizeof(pa->ifname))
3844					errx(1, "expand_rule: strlcpy");
3845			} else
3846				pa->ifname[0] = 0;
3847			TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries);
3848		}
3849
3850		if (rule_consistent(r) < 0 || error)
3851			yyerror("skipping rule due to errors");
3852		else {
3853			r->nr = pf->rule_nr++;
3854			pfctl_add_rule(pf, r);
3855			added++;
3856		}
3857
3858	))))))))));
3859
3860	FREE_LIST(struct node_if, interfaces);
3861	FREE_LIST(struct node_proto, protos);
3862	FREE_LIST(struct node_host, src_hosts);
3863	FREE_LIST(struct node_port, src_ports);
3864	FREE_LIST(struct node_os, src_oses);
3865	FREE_LIST(struct node_host, dst_hosts);
3866	FREE_LIST(struct node_port, dst_ports);
3867	FREE_LIST(struct node_uid, uids);
3868	FREE_LIST(struct node_gid, gids);
3869	FREE_LIST(struct node_icmp, icmp_types);
3870	FREE_LIST(struct node_host, rpool_hosts);
3871
3872	if (!added)
3873		yyerror("rule expands to no valid combination");
3874}
3875
3876#undef FREE_LIST
3877#undef LOOP_THROUGH
3878
3879int
3880check_rulestate(int desired_state)
3881{
3882	if (require_order && (rulestate > desired_state)) {
3883		yyerror("Rules must be in order: options, normalization, "
3884		    "queueing, translation, filtering");
3885		return (1);
3886	}
3887	rulestate = desired_state;
3888	return (0);
3889}
3890
3891int
3892kw_cmp(const void *k, const void *e)
3893{
3894	return (strcmp(k, ((const struct keywords *)e)->k_name));
3895}
3896
3897int
3898lookup(char *s)
3899{
3900	/* this has to be sorted always */
3901	static const struct keywords keywords[] = {
3902		{ "all",		ALL},
3903		{ "allow-opts",		ALLOWOPTS},
3904		{ "altq",		ALTQ},
3905		{ "anchor",		ANCHOR},
3906		{ "antispoof",		ANTISPOOF},
3907		{ "any",		ANY},
3908		{ "bandwidth",		BANDWIDTH},
3909		{ "binat",		BINAT},
3910		{ "binat-anchor",	BINATANCHOR},
3911		{ "bitmask",		BITMASK},
3912		{ "block",		BLOCK},
3913		{ "block-policy",	BLOCKPOLICY},
3914		{ "cbq",		CBQ},
3915		{ "code",		CODE},
3916		{ "crop",		FRAGCROP},
3917		{ "drop",		DROP},
3918		{ "drop-ovl",		FRAGDROP},
3919		{ "dup-to",		DUPTO},
3920		{ "fastroute",		FASTROUTE},
3921		{ "file",		FILENAME},
3922		{ "fingerprints",	FINGERPRINTS},
3923		{ "flags",		FLAGS},
3924		{ "for",		FOR},
3925		{ "fragment",		FRAGMENT},
3926		{ "from",		FROM},
3927		{ "group",		GROUP},
3928		{ "hfsc",		HFSC},
3929		{ "icmp-type",		ICMPTYPE},
3930		{ "icmp6-type",		ICMP6TYPE},
3931		{ "in",			IN},
3932		{ "inet",		INET},
3933		{ "inet6",		INET6},
3934		{ "keep",		KEEP},
3935		{ "label",		LABEL},
3936		{ "limit",		LIMIT},
3937		{ "linkshare",		LINKSHARE},
3938		{ "load",		LOAD},
3939		{ "log",		LOG},
3940		{ "log-all",		LOGALL},
3941		{ "loginterface",	LOGINTERFACE},
3942		{ "max",		MAXIMUM},
3943		{ "max-mss",		MAXMSS},
3944		{ "min-ttl",		MINTTL},
3945		{ "modulate",		MODULATE},
3946		{ "nat",		NAT},
3947		{ "nat-anchor",		NATANCHOR},
3948		{ "no",			NO},
3949		{ "no-df",		NODF},
3950		{ "no-route",		NOROUTE},
3951		{ "on",			ON},
3952		{ "optimization",	OPTIMIZATION},
3953		{ "os",			OS},
3954		{ "out",		OUT},
3955		{ "pass",		PASS},
3956		{ "port",		PORT},
3957		{ "priority",		PRIORITY},
3958		{ "priq",		PRIQ},
3959		{ "proto",		PROTO},
3960		{ "qlimit",		QLIMIT},
3961		{ "queue",		QUEUE},
3962		{ "quick",		QUICK},
3963		{ "random",		RANDOM},
3964		{ "random-id",		RANDOMID},
3965		{ "rdr",		RDR},
3966		{ "rdr-anchor",		RDRANCHOR},
3967		{ "realtime",		REALTIME},
3968		{ "reassemble",		REASSEMBLE},
3969		{ "reply-to",		REPLYTO},
3970		{ "require-order",	REQUIREORDER},
3971		{ "return",		RETURN},
3972		{ "return-icmp",	RETURNICMP},
3973		{ "return-icmp6",	RETURNICMP6},
3974		{ "return-rst",		RETURNRST},
3975		{ "round-robin",	ROUNDROBIN},
3976		{ "route-to",		ROUTETO},
3977		{ "scrub",		SCRUB},
3978		{ "set",		SET},
3979		{ "source-hash",	SOURCEHASH},
3980		{ "state",		STATE},
3981		{ "static-port",	STATICPORT},
3982		{ "synproxy",		SYNPROXY},
3983		{ "table",		TABLE},
3984		{ "tag",		TAG},
3985		{ "tagged",		TAGGED},
3986		{ "tbrsize",		TBRSIZE},
3987		{ "timeout",		TIMEOUT},
3988		{ "to",			TO},
3989		{ "tos",		TOS},
3990		{ "ttl",		TTL},
3991		{ "upperlimit",		UPPERLIMIT},
3992		{ "user",		USER},
3993	};
3994	const struct keywords	*p;
3995
3996	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
3997	    sizeof(keywords[0]), kw_cmp);
3998
3999	if (p) {
4000		if (debug > 1)
4001			fprintf(stderr, "%s: %d\n", s, p->k_val);
4002		return (p->k_val);
4003	} else {
4004		if (debug > 1)
4005			fprintf(stderr, "string: %s\n", s);
4006		return (STRING);
4007	}
4008}
4009
4010#define MAXPUSHBACK	128
4011
4012char	*parsebuf;
4013int	 parseindex;
4014char	 pushback_buffer[MAXPUSHBACK];
4015int	 pushback_index = 0;
4016
4017int
4018lgetc(FILE *f)
4019{
4020	int	c, next;
4021
4022	if (parsebuf) {
4023		/* Read character from the parsebuffer instead of input. */
4024		if (parseindex >= 0) {
4025			c = parsebuf[parseindex++];
4026			if (c != '\0')
4027				return (c);
4028			parsebuf = NULL;
4029		} else
4030			parseindex++;
4031	}
4032
4033	if (pushback_index)
4034		return (pushback_buffer[--pushback_index]);
4035
4036	while ((c = getc(f)) == '\\') {
4037		next = getc(f);
4038		if (next != '\n') {
4039			if (isspace(next))
4040				yyerror("whitespace after \\");
4041			ungetc(next, f);
4042			break;
4043		}
4044		yylval.lineno = lineno;
4045		lineno++;
4046	}
4047	if (c == '\t' || c == ' ') {
4048		/* Compress blanks to a single space. */
4049		do {
4050			c = getc(f);
4051		} while (c == '\t' || c == ' ');
4052		ungetc(c, f);
4053		c = ' ';
4054	}
4055
4056	return (c);
4057}
4058
4059int
4060lungetc(int c)
4061{
4062	if (c == EOF)
4063		return (EOF);
4064	if (parsebuf) {
4065		parseindex--;
4066		if (parseindex >= 0)
4067			return (c);
4068	}
4069	if (pushback_index < MAXPUSHBACK-1)
4070		return (pushback_buffer[pushback_index++] = c);
4071	else
4072		return (EOF);
4073}
4074
4075int
4076findeol(void)
4077{
4078	int	c;
4079
4080	parsebuf = NULL;
4081	pushback_index = 0;
4082
4083	/* skip to either EOF or the first real EOL */
4084	while (1) {
4085		c = lgetc(fin);
4086		if (c == '\n') {
4087			lineno++;
4088			break;
4089		}
4090		if (c == EOF)
4091			break;
4092	}
4093	return (ERROR);
4094}
4095
4096int
4097yylex(void)
4098{
4099	char	 buf[8096];
4100	char	*p, *val;
4101	int	 endc, c, next;
4102	int	 token;
4103
4104top:
4105	p = buf;
4106	while ((c = lgetc(fin)) == ' ')
4107		; /* nothing */
4108
4109	yylval.lineno = lineno;
4110	if (c == '#')
4111		while ((c = lgetc(fin)) != '\n' && c != EOF)
4112			; /* nothing */
4113	if (c == '$' && parsebuf == NULL) {
4114		while (1) {
4115			if ((c = lgetc(fin)) == EOF)
4116				return (0);
4117
4118			if (p + 1 >= buf + sizeof(buf) - 1) {
4119				yyerror("string too long");
4120				return (findeol());
4121			}
4122			if (isalnum(c) || c == '_') {
4123				*p++ = (char)c;
4124				continue;
4125			}
4126			*p = '\0';
4127			lungetc(c);
4128			break;
4129		}
4130		val = symget(buf);
4131		if (val == NULL) {
4132			yyerror("macro '%s' not defined", buf);
4133			return (findeol());
4134		}
4135		parsebuf = val;
4136		parseindex = 0;
4137		goto top;
4138	}
4139
4140	switch (c) {
4141	case '\'':
4142	case '"':
4143		endc = c;
4144		while (1) {
4145			if ((c = lgetc(fin)) == EOF)
4146				return (0);
4147			if (c == endc) {
4148				*p = '\0';
4149				break;
4150			}
4151			if (c == '\n') {
4152				lineno++;
4153				continue;
4154			}
4155			if (p + 1 >= buf + sizeof(buf) - 1) {
4156				yyerror("string too long");
4157				return (findeol());
4158			}
4159			*p++ = (char)c;
4160		}
4161		yylval.v.string = strdup(buf);
4162		if (yylval.v.string == NULL)
4163			err(1, "yylex: strdup");
4164		return (STRING);
4165	case '<':
4166		next = lgetc(fin);
4167		if (next == '>') {
4168			yylval.v.i = PF_OP_XRG;
4169			return (PORTBINARY);
4170		}
4171		lungetc(next);
4172		break;
4173	case '>':
4174		next = lgetc(fin);
4175		if (next == '<') {
4176			yylval.v.i = PF_OP_IRG;
4177			return (PORTBINARY);
4178		}
4179		lungetc(next);
4180		break;
4181	case '-':
4182		next = lgetc(fin);
4183		if (next == '>')
4184			return (ARROW);
4185		lungetc(next);
4186		break;
4187	}
4188
4189#define allowed_in_string(x) \
4190	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
4191	x != '{' && x != '}' && x != '<' && x != '>' && \
4192	x != '!' && x != '=' && x != '/' && x != '#' && \
4193	x != ','))
4194
4195	if (isalnum(c) || c == ':' || c == '_') {
4196		do {
4197			*p++ = c;
4198			if ((unsigned)(p-buf) >= sizeof(buf)) {
4199				yyerror("string too long");
4200				return (findeol());
4201			}
4202		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
4203		lungetc(c);
4204		*p = '\0';
4205		token = lookup(buf);
4206		yylval.v.string = strdup(buf);
4207		if (yylval.v.string == NULL)
4208			err(1, "yylex: strdup");
4209		return (token);
4210	}
4211	if (c == '\n') {
4212		yylval.lineno = lineno;
4213		lineno++;
4214	}
4215	if (c == EOF)
4216		return (0);
4217	return (c);
4218}
4219
4220int
4221parse_rules(FILE *input, struct pfctl *xpf)
4222{
4223	struct sym	*sym;
4224
4225	fin = input;
4226	pf = xpf;
4227	lineno = 1;
4228	errors = 0;
4229	rulestate = PFCTL_STATE_NONE;
4230	returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
4231	returnicmp6default =
4232	    (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
4233	blockpolicy = PFRULE_DROP;
4234	require_order = 1;
4235
4236	yyparse();
4237
4238	/* Free macros and check which have not been used. */
4239	TAILQ_FOREACH(sym, &symhead, entries) {
4240		if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used)
4241			fprintf(stderr, "warning: macro '%s' not "
4242			    "used\n", sym->nam);
4243		free(sym->nam);
4244		free(sym->val);
4245		TAILQ_REMOVE(&symhead, sym, entries);
4246	}
4247
4248	return (errors ? -1 : 0);
4249}
4250
4251/*
4252 * Over-designed efficiency is a French and German concept, so how about
4253 * we wait until they discover this ugliness and make it all fancy.
4254 */
4255int
4256symset(const char *nam, const char *val, int persist)
4257{
4258	struct sym	*sym;
4259
4260	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
4261	    sym = TAILQ_NEXT(sym, entries))
4262		;	/* nothing */
4263
4264	if (sym != NULL) {
4265		if (sym->persist == 1)
4266			return (0);
4267		else {
4268			free(sym->nam);
4269			free(sym->val);
4270			TAILQ_REMOVE(&symhead, sym, entries);
4271			free(sym);
4272		}
4273	}
4274	if ((sym = calloc(1, sizeof(*sym))) == NULL)
4275		return (-1);
4276
4277	sym->nam = strdup(nam);
4278	if (sym->nam == NULL) {
4279		free(sym);
4280		return (-1);
4281	}
4282	sym->val = strdup(val);
4283	if (sym->val == NULL) {
4284		free(sym->nam);
4285		free(sym);
4286		return (-1);
4287	}
4288	sym->used = 0;
4289	sym->persist = persist;
4290	TAILQ_INSERT_TAIL(&symhead, sym, entries);
4291	return (0);
4292}
4293
4294int
4295pfctl_cmdline_symset(char *s)
4296{
4297	char	*sym, *val;
4298	int	 ret;
4299
4300	if ((val = strrchr(s, '=')) == NULL)
4301		return (-1);
4302
4303	if ((sym = malloc(strlen(s) - strlen(val) + 1)) == NULL)
4304		err(1, "pfctl_cmdline_symset: malloc");
4305
4306	strlcpy(sym, s, strlen(s) - strlen(val) + 1);
4307
4308	ret = symset(sym, val + 1, 1);
4309	free(sym);
4310
4311	return (ret);
4312}
4313
4314char *
4315symget(const char *nam)
4316{
4317	struct sym	*sym;
4318
4319	TAILQ_FOREACH(sym, &symhead, entries)
4320		if (strcmp(nam, sym->nam) == 0) {
4321			sym->used = 1;
4322			return (sym->val);
4323		}
4324	return (NULL);
4325}
4326
4327void
4328decide_address_family(struct node_host *n, sa_family_t *af)
4329{
4330	sa_family_t	target_af = 0;
4331
4332	while (!*af && n != NULL) {
4333		if (n->af) {
4334			if (target_af == 0)
4335				target_af = n->af;
4336			if (target_af != n->af)
4337				return;
4338		}
4339		n = n->next;
4340	}
4341	if (!*af && target_af)
4342		*af = target_af;
4343}
4344
4345void
4346remove_invalid_hosts(struct node_host **nh, sa_family_t *af)
4347{
4348	struct node_host	*n = *nh, *prev = NULL;
4349
4350	while (n != NULL) {
4351		if (*af && n->af && n->af != *af) {
4352			/* unlink and free n */
4353			struct node_host *next = n->next;
4354
4355			/* adjust tail pointer */
4356			if (n == (*nh)->tail)
4357				(*nh)->tail = prev;
4358			/* adjust previous node's next pointer */
4359			if (prev == NULL)
4360				*nh = next;
4361			else
4362				prev->next = next;
4363			/* free node */
4364			if (n->ifname != NULL)
4365				free(n->ifname);
4366			free(n);
4367			n = next;
4368		} else {
4369			if (n->af && !*af)
4370				*af = n->af;
4371			prev = n;
4372			n = n->next;
4373		}
4374	}
4375}
4376
4377int
4378invalid_redirect(struct node_host *nh, sa_family_t af)
4379{
4380	if (!af) {
4381		struct node_host *n;
4382
4383		/* only tables are ok without an address family */
4384		for (n = nh; n != NULL; n = n->next) {
4385			if (n->addr.type != PF_ADDR_TABLE) {
4386				yyerror("address family not given and "
4387				    "translation address expands to multiple "
4388				    "address families");
4389				return (1);
4390			}
4391		}
4392	}
4393	if (nh == NULL) {
4394		yyerror("no translation address with matching address family "
4395		    "found.");
4396		return (1);
4397	}
4398	return (0);
4399}
4400
4401int
4402atoul(char *s, u_long *ulvalp)
4403{
4404	u_long	 ulval;
4405	char	*ep;
4406
4407	errno = 0;
4408	ulval = strtoul(s, &ep, 0);
4409	if (s[0] == '\0' || *ep != '\0')
4410		return (-1);
4411	if (errno == ERANGE && ulval == ULONG_MAX)
4412		return (-1);
4413	*ulvalp = ulval;
4414	return (0);
4415}
4416
4417int
4418getservice(char *n)
4419{
4420	struct servent	*s;
4421	u_long		 ulval;
4422
4423	if (atoul(n, &ulval) == 0) {
4424		if (ulval > 65535) {
4425			yyerror("illegal port value %d", ulval);
4426			return (-1);
4427		}
4428		return (htons(ulval));
4429	} else {
4430		s = getservbyname(n, "tcp");
4431		if (s == NULL)
4432			s = getservbyname(n, "udp");
4433		if (s == NULL) {
4434			yyerror("unknown port %s", n);
4435			return (-1);
4436		}
4437		return (s->s_port);
4438	}
4439}
4440
4441int
4442rule_label(struct pf_rule *r, char *s)
4443{
4444	if (s) {
4445		if (strlcpy(r->label, s, sizeof(r->label)) >=
4446		    sizeof(r->label)) {
4447			yyerror("rule label too long (max %d chars)",
4448			    sizeof(r->label)-1);
4449			return (-1);
4450		}
4451	}
4452	return (0);
4453}
4454
4455u_int16_t
4456parseicmpspec(char *w, sa_family_t af)
4457{
4458	const struct icmpcodeent	*p;
4459	u_long				 ulval;
4460	u_int8_t			 icmptype;
4461
4462	if (af == AF_INET)
4463		icmptype = returnicmpdefault >> 8;
4464	else
4465		icmptype = returnicmp6default >> 8;
4466
4467	if (atoul(w, &ulval) == -1) {
4468		if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
4469			yyerror("unknown icmp code %s", w);
4470			return (0);
4471		}
4472		ulval = p->code;
4473	}
4474	if (ulval > 255) {
4475		yyerror("invalid icmp code %ld", ulval);
4476		return (0);
4477	}
4478	return (icmptype << 8 | ulval);
4479}
4480
4481int
4482pfctl_load_anchors(int dev, int opts)
4483{
4484	struct loadanchors	*la;
4485
4486	TAILQ_FOREACH(la, &loadanchorshead, entries) {
4487		if (opts & PF_OPT_VERBOSE)
4488			fprintf(stderr, "\nLoading anchor %s:%s from %s\n",
4489			    la->anchorname, la->rulesetname, la->filename);
4490		if (pfctl_rules(dev, la->filename, opts, la->anchorname,
4491		    la->rulesetname) == -1)
4492			return (-1);
4493	}
4494
4495	return (0);
4496}
4497
4498