parse.y revision 1.251
1/*	$OpenBSD: parse.y,v 1.251 2021/01/09 08:53:57 denis Exp $	*/
2
3/*
4 * Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
6 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
7 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
8 * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
9 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
10 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
11 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
12 * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
13 *
14 * Permission to use, copy, modify, and distribute this software for any
15 * purpose with or without fee is hereby granted, provided that the above
16 * copyright notice and this permission notice appear in all copies.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 */
26
27%{
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <sys/stat.h>
31#include <sys/queue.h>
32#include <sys/ioctl.h>
33#include <sys/time.h>
34#include <sys/tree.h>
35
36#include <netinet/in.h>
37#include <arpa/inet.h>
38#include <net/if.h>
39#include <net/pfvar.h>
40#include <net/route.h>
41
42#include <agentx.h>
43#include <stdint.h>
44#include <stdarg.h>
45#include <stdio.h>
46#include <unistd.h>
47#include <ctype.h>
48#include <err.h>
49#include <endian.h>
50#include <errno.h>
51#include <limits.h>
52#include <netdb.h>
53#include <string.h>
54#include <ifaddrs.h>
55#include <syslog.h>
56#include <md5.h>
57
58#include "relayd.h"
59#include "http.h"
60
61TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
62static struct file {
63	TAILQ_ENTRY(file)	 entry;
64	FILE			*stream;
65	char			*name;
66	size_t			 ungetpos;
67	size_t			 ungetsize;
68	u_char			*ungetbuf;
69	int			 eof_reached;
70	int			 lineno;
71	int			 errors;
72} *file, *topfile;
73struct file	*pushfile(const char *, int);
74int		 popfile(void);
75int		 check_file_secrecy(int, const char *);
76int		 yyparse(void);
77int		 yylex(void);
78int		 yyerror(const char *, ...)
79    __attribute__((__format__ (printf, 1, 2)))
80    __attribute__((__nonnull__ (1)));
81int		 kw_cmp(const void *, const void *);
82int		 lookup(char *);
83int		 igetc(void);
84int		 lgetc(int);
85void		 lungetc(int);
86int		 findeol(void);
87
88TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
89struct sym {
90	TAILQ_ENTRY(sym)	 entry;
91	int			 used;
92	int			 persist;
93	char			*nam;
94	char			*val;
95};
96int		 symset(const char *, const char *, int);
97char		*symget(const char *);
98
99struct relayd		*conf = NULL;
100static int		 errors = 0;
101static int		 loadcfg = 0;
102objid_t			 last_rdr_id = 0;
103objid_t			 last_table_id = 0;
104objid_t			 last_host_id = 0;
105objid_t			 last_relay_id = 0;
106objid_t			 last_proto_id = 0;
107objid_t			 last_rt_id = 0;
108objid_t			 last_nr_id = 0;
109
110static struct rdr	*rdr = NULL;
111static struct table	*table = NULL;
112static struct relay	*rlay = NULL;
113static struct host	*hst = NULL;
114struct relaylist	 relays;
115static struct protocol	*proto = NULL;
116static struct relay_rule *rule = NULL;
117static struct router	*router = NULL;
118static int		 label = 0;
119static int		 tagged = 0;
120static int		 tag = 0;
121static in_port_t	 tableport = 0;
122static int		 dstmode;
123static enum key_type	 keytype = KEY_TYPE_NONE;
124static enum direction	 dir = RELAY_DIR_ANY;
125static char		*rulefile = NULL;
126static union hashkey	*hashkey = NULL;
127
128struct address	*host_ip(const char *);
129int		 host_dns(const char *, struct addresslist *,
130		    int, struct portrange *, const char *, int);
131int		 host_if(const char *, struct addresslist *,
132		    int, struct portrange *, const char *, int);
133int		 host(const char *, struct addresslist *,
134		    int, struct portrange *, const char *, int);
135void		 host_free(struct addresslist *);
136
137struct table	*table_inherit(struct table *);
138int		 relay_id(struct relay *);
139struct relay	*relay_inherit(struct relay *, struct relay *);
140int		 getservice(char *);
141int		 is_if_in_group(const char *, const char *);
142
143typedef struct {
144	union {
145		int64_t			 number;
146		char			*string;
147		struct host		*host;
148		struct timeval		 tv;
149		struct table		*table;
150		struct portrange	 port;
151		struct {
152			union hashkey	 key;
153			int		 keyset;
154		}			 key;
155		enum direction		 dir;
156		struct {
157			struct sockaddr_storage	 ss;
158			int			 prefixlen;
159			char			 name[HOST_NAME_MAX+1];
160		}			 addr;
161		struct {
162			enum digest_type type;
163			char		*digest;
164		}			 digest;
165	} v;
166	int lineno;
167} YYSTYPE;
168
169%}
170
171%token	AGENTX APPEND BACKLOG BACKUP BINARY BUFFER CA CACHE SET CHECK CIPHERS
172%token	CODE COOKIE DEMOTE DIGEST DISABLE ERROR EXPECT PASS BLOCK EXTERNAL
173%token	FILENAME FORWARD FROM HASH HEADER HEADERLEN HOST HTTP ICMP INCLUDE INET
174%token	INET6 INTERFACE INTERVAL IP KEYPAIR LABEL LISTEN VALUE LOADBALANCE LOG
175%token	LOOKUP METHOD MODE NAT NO DESTINATION NODELAY NOTHING ON PARENT PATH
176%token	PFTAG PORT PREFORK PRIORITY PROTO QUERYSTR REAL REDIRECT RELAY REMOVE
177%token	REQUEST RESPONSE RETRY QUICK RETURN ROUNDROBIN ROUTE SACK SCRIPT SEND
178%token	SESSION SOCKET SPLICE SSL STICKYADDR STRIP STYLE TABLE TAG TAGGED TCP
179%token	TIMEOUT TLS TO ROUTER RTLABEL TRANSPARENT URL WITH TTL RTABLE
180%token	MATCH PARAMS RANDOM LEASTSTATES SRCHASH KEY CERTIFICATE PASSWORD ECDHE
181%token	EDH TICKETS CONNECTION CONNECTIONS CONTEXT ERRORS STATE CHANGES CHECKS
182%token	WEBSOCKETS
183%token	<v.string>	STRING
184%token  <v.number>	NUMBER
185%type	<v.string>	context hostname interface table value path
186%type	<v.number>	http_type loglevel quick
187%type	<v.number>	dstmode flag forwardmode retry
188%type	<v.number>	opttls opttlsclient
189%type	<v.number>	redirect_proto relay_proto match
190%type	<v.number>	action ruleaf key_option
191%type	<v.port>	port
192%type	<v.host>	host
193%type	<v.addr>	address rulesrc ruledst addrprefix
194%type	<v.tv>		timeout
195%type	<v.digest>	digest optdigest
196%type	<v.table>	tablespec
197%type	<v.dir>		dir
198%type	<v.key>		hashkey
199
200%%
201
202grammar		: /* empty */
203		| grammar include '\n'
204		| grammar '\n'
205		| grammar varset '\n'
206		| grammar main '\n'
207		| grammar rdr '\n'
208		| grammar tabledef '\n'
209		| grammar relay '\n'
210		| grammar proto '\n'
211		| grammar router '\n'
212		| grammar error '\n'		{ file->errors++; }
213		;
214
215include		: INCLUDE STRING		{
216			struct file	*nfile;
217
218			if ((nfile = pushfile($2, 0)) == NULL) {
219				yyerror("failed to include file %s", $2);
220				free($2);
221				YYERROR;
222			}
223			free($2);
224
225			file = nfile;
226			lungetc('\n');
227		}
228		;
229
230ssltls		: SSL		{
231			log_warnx("%s:%d: %s",
232			    file->name, yylval.lineno,
233			    "please use the \"tls\" keyword"
234			    " instead of \"ssl\"");
235		}
236		| TLS
237		;
238
239opttls		: /*empty*/	{ $$ = 0; }
240		| ssltls	{ $$ = 1; }
241		;
242
243opttlsclient	: /*empty*/	{ $$ = 0; }
244		| WITH ssltls	{ $$ = 1; }
245		;
246
247http_type	: HTTP		{ $$ = 0; }
248		| STRING	{
249			if (strcmp("https", $1) == 0) {
250				$$ = 1;
251			} else {
252				yyerror("invalid check type: %s", $1);
253				free($1);
254				YYERROR;
255			}
256			free($1);
257		}
258		;
259
260hostname	: /* empty */		{
261			$$ = strdup("");
262			if ($$ == NULL)
263				fatal("calloc");
264		}
265		| HOST STRING	{
266			if (asprintf(&$$, "Host: %s\r\nConnection: close\r\n",
267			    $2) == -1)
268				fatal("asprintf");
269		}
270		;
271
272relay_proto	: /* empty */			{ $$ = RELAY_PROTO_TCP; }
273		| TCP				{ $$ = RELAY_PROTO_TCP; }
274		| HTTP				{ $$ = RELAY_PROTO_HTTP; }
275		| STRING			{
276			if (strcmp("dns", $1) == 0) {
277				$$ = RELAY_PROTO_DNS;
278			} else {
279				yyerror("invalid protocol type: %s", $1);
280				free($1);
281				YYERROR;
282			}
283			free($1);
284		}
285		;
286
287redirect_proto	: /* empty */			{ $$ = IPPROTO_TCP; }
288		| TCP				{ $$ = IPPROTO_TCP; }
289		| STRING			{
290			struct protoent	*p;
291
292			if ((p = getprotobyname($1)) == NULL) {
293				yyerror("invalid protocol: %s", $1);
294				free($1);
295				YYERROR;
296			}
297			free($1);
298
299			$$ = p->p_proto;
300		}
301		;
302
303eflags_l	: eflags comma eflags_l
304		| eflags
305		;
306
307opteflags	: /* nothing */
308		| eflags
309		;
310
311eflags		: STYLE STRING
312		{
313			if ((proto->style = strdup($2)) == NULL)
314				fatal("out of memory");
315			free($2);
316		}
317		;
318
319port		: PORT HTTP {
320			int p = 0;
321			$$.op = PF_OP_EQ;
322			if ((p = getservice("http")) == -1)
323				YYERROR;
324			$$.val[0] = p;
325			$$.val[1] = 0;
326		}
327		| PORT STRING {
328			char		*a, *b;
329			int		 p[2];
330
331			p[0] = p[1] = 0;
332
333			a = $2;
334			b = strchr($2, ':');
335			if (b == NULL)
336				$$.op = PF_OP_EQ;
337			else {
338				*b++ = '\0';
339				if ((p[1] = getservice(b)) == -1) {
340					free($2);
341					YYERROR;
342				}
343				$$.op = PF_OP_RRG;
344			}
345			if ((p[0] = getservice(a)) == -1) {
346				free($2);
347				YYERROR;
348			}
349			$$.val[0] = p[0];
350			$$.val[1] = p[1];
351			free($2);
352		}
353		| PORT NUMBER {
354			if ($2 <= 0 || $2 > (int)USHRT_MAX) {
355				yyerror("invalid port: %lld", $2);
356				YYERROR;
357			}
358			$$.val[0] = htons($2);
359			$$.op = PF_OP_EQ;
360		}
361		;
362
363varset		: STRING '=' STRING	{
364			char *s = $1;
365			while (*s++) {
366				if (isspace((unsigned char)*s)) {
367					yyerror("macro name cannot contain "
368					    "whitespace");
369					free($1);
370					free($3);
371					YYERROR;
372				}
373			}
374			if (symset($1, $3, 0) == -1)
375				fatal("cannot store variable");
376			free($1);
377			free($3);
378		}
379		;
380
381sendbuf		: NOTHING		{
382			table->sendbuf = NULL;
383		}
384		| STRING		{
385			table->sendbuf = strdup($1);
386			if (table->sendbuf == NULL)
387				fatal("out of memory");
388			free($1);
389		}
390		;
391
392sendbinbuf	: NOTHING		{
393			table->sendbinbuf = NULL;
394		}
395		| STRING		{
396			if (strlen($1) == 0) {
397				yyerror("empty binary send data");
398				free($1);
399				YYERROR;
400			}
401			table->sendbuf = strdup($1);
402			if (table->sendbuf == NULL)
403				fatal("out of memory");
404			table->sendbinbuf = string2binary($1);
405			if (table->sendbinbuf == NULL)
406				fatal("failed in binary send data");
407			free($1);
408		}
409		;
410
411main		: INTERVAL NUMBER	{
412			if ((conf->sc_conf.interval.tv_sec = $2) < 0) {
413				yyerror("invalid interval: %lld", $2);
414				YYERROR;
415			}
416		}
417		| LOG loglevel		{
418			conf->sc_conf.opts |= $2;
419		}
420		| TIMEOUT timeout	{
421			bcopy(&$2, &conf->sc_conf.timeout,
422			    sizeof(struct timeval));
423		}
424		| PREFORK NUMBER	{
425			if ($2 <= 0 || $2 > PROC_MAX_INSTANCES) {
426				yyerror("invalid number of preforked "
427				    "relays: %lld", $2);
428				YYERROR;
429			}
430			conf->sc_conf.prefork_relay = $2;
431		}
432		| AGENTX context path {
433			conf->sc_conf.flags |= F_AGENTX;
434			if ($2 != NULL) {
435				if (strlcpy(conf->sc_conf.agentx_context, $2,
436				    sizeof(conf->sc_conf.agentx_context)) >=
437				    sizeof(conf->sc_conf.agentx_context)) {
438					yyerror("agentx context too long");
439					free($2);
440					free($3);
441					YYERROR;
442				}
443				free($2);
444			} else
445				conf->sc_conf.agentx_context[0] = '\0';
446			if ($3 != NULL) {
447				if (strlcpy(conf->sc_conf.agentx_path, $3,
448				    sizeof(conf->sc_conf.agentx_path)) >=
449				    sizeof(conf->sc_conf.agentx_path)) {
450					yyerror("agentx path too long");
451					free($3);
452					YYERROR;
453				}
454				free($3);
455			} else
456				(void)strlcpy(conf->sc_conf.agentx_path,
457				    AGENTX_MASTER_PATH,
458				    sizeof(conf->sc_conf.agentx_path));
459		}
460		| SOCKET STRING {
461			conf->sc_ps->ps_csock.cs_name = $2;
462		}
463		;
464
465path		: /* nothing */		{ $$ = NULL; }
466		| PATH STRING		{ $$ = $2; }
467
468context		: /* nothing */		{ $$ = NULL; }
469		| CONTEXT STRING	{ $$ = $2; }
470
471loglevel	: STATE CHANGES		{ $$ = RELAYD_OPT_LOGUPDATE; }
472		| HOST CHECKS		{ $$ = RELAYD_OPT_LOGHOSTCHECK; }
473		| CONNECTION		{ $$ = (RELAYD_OPT_LOGCON |
474						RELAYD_OPT_LOGCONERR); }
475		| CONNECTION ERRORS	{ $$ = RELAYD_OPT_LOGCONERR; }
476		;
477
478rdr		: REDIRECT STRING	{
479			struct rdr *srv;
480
481			conf->sc_conf.flags |= F_NEEDPF;
482
483			if (!loadcfg) {
484				free($2);
485				YYACCEPT;
486			}
487
488			TAILQ_FOREACH(srv, conf->sc_rdrs, entry)
489				if (!strcmp(srv->conf.name, $2))
490					break;
491			if (srv != NULL) {
492				yyerror("redirection %s defined twice", $2);
493				free($2);
494				YYERROR;
495			}
496			if ((srv = calloc(1, sizeof (*srv))) == NULL)
497				fatal("out of memory");
498
499			if (strlcpy(srv->conf.name, $2,
500			    sizeof(srv->conf.name)) >=
501			    sizeof(srv->conf.name)) {
502				yyerror("redirection name truncated");
503				free($2);
504				free(srv);
505				YYERROR;
506			}
507			free($2);
508			srv->conf.id = ++last_rdr_id;
509			srv->conf.timeout.tv_sec = RELAY_TIMEOUT;
510			if (last_rdr_id == INT_MAX) {
511				yyerror("too many redirections defined");
512				free(srv);
513				YYERROR;
514			}
515			rdr = srv;
516		} '{' optnl rdropts_l '}'	{
517			if (rdr->table == NULL) {
518				yyerror("redirection %s has no table",
519				    rdr->conf.name);
520				YYERROR;
521			}
522			if (TAILQ_EMPTY(&rdr->virts)) {
523				yyerror("redirection %s has no virtual ip",
524				    rdr->conf.name);
525				YYERROR;
526			}
527			conf->sc_rdrcount++;
528			if (rdr->backup == NULL) {
529				rdr->conf.backup_id =
530				    conf->sc_empty_table.conf.id;
531				rdr->backup = &conf->sc_empty_table;
532			} else if (rdr->backup->conf.port !=
533			    rdr->table->conf.port) {
534				yyerror("redirection %s uses two different "
535				    "ports for its table and backup table",
536				    rdr->conf.name);
537				YYERROR;
538			}
539			if (!(rdr->conf.flags & F_DISABLE))
540				rdr->conf.flags |= F_ADD;
541			TAILQ_INSERT_TAIL(conf->sc_rdrs, rdr, entry);
542			tableport = 0;
543			rdr = NULL;
544		}
545		;
546
547rdropts_l	: rdropts_l rdroptsl nl
548		| rdroptsl optnl
549		;
550
551rdroptsl	: forwardmode TO tablespec interface	{
552			if (hashkey != NULL) {
553				memcpy(&rdr->conf.key,
554				    hashkey, sizeof(rdr->conf.key));
555				rdr->conf.flags |= F_HASHKEY;
556				free(hashkey);
557				hashkey = NULL;
558			}
559
560			switch ($1) {
561			case FWD_NORMAL:
562				if ($4 == NULL)
563					break;
564				yyerror("superfluous interface");
565				free($4);
566				YYERROR;
567			case FWD_ROUTE:
568				if ($4 != NULL)
569					break;
570				yyerror("missing interface to route to");
571				free($4);
572				YYERROR;
573			case FWD_TRANS:
574				yyerror("no transparent forward here");
575				if ($4 != NULL)
576					free($4);
577				YYERROR;
578			}
579			if ($4 != NULL) {
580				if (strlcpy($3->conf.ifname, $4,
581				    sizeof($3->conf.ifname)) >=
582				    sizeof($3->conf.ifname)) {
583					yyerror("interface name truncated");
584					free($4);
585					YYERROR;
586				}
587				free($4);
588			}
589
590			if ($3->conf.check == CHECK_NOCHECK) {
591				yyerror("table %s has no check", $3->conf.name);
592				purge_table(conf, conf->sc_tables, $3);
593				YYERROR;
594			}
595			if (rdr->backup) {
596				yyerror("only one backup table is allowed");
597				purge_table(conf, conf->sc_tables, $3);
598				YYERROR;
599			}
600			if (rdr->table) {
601				rdr->backup = $3;
602				rdr->conf.backup_id = $3->conf.id;
603				if (dstmode != rdr->conf.mode) {
604					yyerror("backup table for %s with "
605					    "different mode", rdr->conf.name);
606					YYERROR;
607				}
608			} else {
609				rdr->table = $3;
610				rdr->conf.table_id = $3->conf.id;
611				rdr->conf.mode = dstmode;
612			}
613			$3->conf.fwdmode = $1;
614			$3->conf.rdrid = rdr->conf.id;
615			$3->conf.flags |= F_USED;
616		}
617		| LISTEN ON STRING redirect_proto port interface {
618			if (host($3, &rdr->virts,
619			    SRV_MAX_VIRTS, &$5, $6, $4) <= 0) {
620				yyerror("invalid virtual ip: %s", $3);
621				free($3);
622				free($6);
623				YYERROR;
624			}
625			free($3);
626			free($6);
627			if (rdr->conf.port == 0)
628				rdr->conf.port = $5.val[0];
629			tableport = rdr->conf.port;
630		}
631		| DISABLE		{ rdr->conf.flags |= F_DISABLE; }
632		| STICKYADDR		{ rdr->conf.flags |= F_STICKY; }
633		| match PFTAG STRING {
634			conf->sc_conf.flags |= F_NEEDPF;
635			if (strlcpy(rdr->conf.tag, $3,
636			    sizeof(rdr->conf.tag)) >=
637			    sizeof(rdr->conf.tag)) {
638				yyerror("redirection tag name truncated");
639				free($3);
640				YYERROR;
641			}
642			if ($1)
643				rdr->conf.flags |= F_MATCH;
644			free($3);
645		}
646		| SESSION TIMEOUT NUMBER		{
647			if ((rdr->conf.timeout.tv_sec = $3) < 0) {
648				yyerror("invalid timeout: %lld", $3);
649				YYERROR;
650			}
651			if (rdr->conf.timeout.tv_sec > INT_MAX) {
652				yyerror("timeout too large: %lld", $3);
653				YYERROR;
654			}
655		}
656		| include
657		;
658
659match		: /* empty */		{ $$ = 0; }
660		| MATCH			{ $$ = 1; }
661		;
662
663forwardmode	: FORWARD		{ $$ = FWD_NORMAL; }
664		| ROUTE			{ $$ = FWD_ROUTE; }
665		| TRANSPARENT FORWARD	{ $$ = FWD_TRANS; }
666		;
667
668table		: '<' STRING '>'	{
669			if (strlen($2) >= TABLE_NAME_SIZE) {
670				yyerror("invalid table name");
671				free($2);
672				YYERROR;
673			}
674			$$ = $2;
675		}
676		;
677
678tabledef	: TABLE table		{
679			struct table *tb;
680
681			if (!loadcfg) {
682				free($2);
683				YYACCEPT;
684			}
685
686			TAILQ_FOREACH(tb, conf->sc_tables, entry)
687				if (!strcmp(tb->conf.name, $2))
688					break;
689			if (tb != NULL) {
690				yyerror("table %s defined twice", $2);
691				free($2);
692				YYERROR;
693			}
694
695			if ((tb = calloc(1, sizeof (*tb))) == NULL)
696				fatal("out of memory");
697
698			if (strlcpy(tb->conf.name, $2,
699			    sizeof(tb->conf.name)) >= sizeof(tb->conf.name)) {
700				yyerror("table name truncated");
701				free($2);
702				YYERROR;
703			}
704			free($2);
705
706			tb->conf.id = 0; /* will be set later */
707			bcopy(&conf->sc_conf.timeout, &tb->conf.timeout,
708			    sizeof(struct timeval));
709			TAILQ_INIT(&tb->hosts);
710			table = tb;
711			dstmode = RELAY_DSTMODE_DEFAULT;
712		} tabledefopts_l	{
713			if (TAILQ_EMPTY(&table->hosts)) {
714				yyerror("table %s has no hosts",
715				    table->conf.name);
716				YYERROR;
717			}
718			conf->sc_tablecount++;
719			TAILQ_INSERT_TAIL(conf->sc_tables, table, entry);
720		}
721		;
722
723tabledefopts_l	: tabledefopts_l tabledefopts
724		| tabledefopts
725		;
726
727tabledefopts	: DISABLE		{ table->conf.flags |= F_DISABLE; }
728		| '{' optnl tablelist_l '}'
729		;
730
731tablelist_l	: tablelist comma tablelist_l
732		| tablelist optnl
733		;
734
735tablelist	: host			{
736			$1->conf.tableid = table->conf.id;
737			$1->tablename = table->conf.name;
738			TAILQ_INSERT_TAIL(&table->hosts, $1, entry);
739		}
740		| include
741		;
742
743tablespec	: table			{
744			struct table	*tb;
745			if ((tb = calloc(1, sizeof (*tb))) == NULL)
746				fatal("out of memory");
747			if (strlcpy(tb->conf.name, $1,
748			    sizeof(tb->conf.name)) >= sizeof(tb->conf.name)) {
749				yyerror("table name truncated");
750				free($1);
751				YYERROR;
752			}
753			free($1);
754			table = tb;
755			dstmode = RELAY_DSTMODE_DEFAULT;
756			hashkey = NULL;
757		} tableopts_l		{
758			struct table	*tb;
759			if (table->conf.port == 0)
760				table->conf.port = tableport;
761			else
762				table->conf.flags |= F_PORT;
763			if ((tb = table_inherit(table)) == NULL)
764				YYERROR;
765			$$ = tb;
766		}
767		;
768
769tableopts_l	: tableopts tableopts_l
770		| tableopts
771		;
772
773tableopts	: CHECK tablecheck
774		| port			{
775			if ($1.op != PF_OP_EQ) {
776				yyerror("invalid port");
777				YYERROR;
778			}
779			table->conf.port = $1.val[0];
780		}
781		| TIMEOUT timeout	{
782			bcopy(&$2, &table->conf.timeout,
783			    sizeof(struct timeval));
784		}
785		| DEMOTE STRING		{
786			table->conf.flags |= F_DEMOTE;
787			if (strlcpy(table->conf.demote_group, $2,
788			    sizeof(table->conf.demote_group))
789			    >= sizeof(table->conf.demote_group)) {
790				yyerror("yyparse: demote group name too long");
791				free($2);
792				YYERROR;
793			}
794			free($2);
795			if (carp_demote_init(table->conf.demote_group, 1)
796			    == -1) {
797				yyerror("yyparse: error initializing group "
798				    "'%s'", table->conf.demote_group);
799				YYERROR;
800			}
801		}
802		| INTERVAL NUMBER	{
803			if ($2 < conf->sc_conf.interval.tv_sec ||
804			    $2 % conf->sc_conf.interval.tv_sec) {
805				yyerror("table interval must be "
806				    "divisible by global interval");
807				YYERROR;
808			}
809			table->conf.skip_cnt =
810			    ($2 / conf->sc_conf.interval.tv_sec) - 1;
811		}
812		| MODE dstmode hashkey	{
813			switch ($2) {
814			case RELAY_DSTMODE_LOADBALANCE:
815			case RELAY_DSTMODE_HASH:
816			case RELAY_DSTMODE_SRCHASH:
817				if (hashkey != NULL) {
818					yyerror("key already specified");
819					free(hashkey);
820					YYERROR;
821				}
822				if ((hashkey = calloc(1,
823				    sizeof(*hashkey))) == NULL)
824					fatal("out of memory");
825				memcpy(hashkey, &$3.key, sizeof(*hashkey));
826				break;
827			default:
828				if ($3.keyset) {
829					yyerror("key not supported by mode");
830					YYERROR;
831				}
832				hashkey = NULL;
833				break;
834			}
835
836			switch ($2) {
837			case RELAY_DSTMODE_LOADBALANCE:
838			case RELAY_DSTMODE_HASH:
839				if (rdr != NULL) {
840					yyerror("mode not supported "
841					    "for redirections");
842					YYERROR;
843				}
844				/* FALLTHROUGH */
845			case RELAY_DSTMODE_RANDOM:
846			case RELAY_DSTMODE_ROUNDROBIN:
847			case RELAY_DSTMODE_SRCHASH:
848				dstmode = $2;
849				break;
850			case RELAY_DSTMODE_LEASTSTATES:
851				if (rdr == NULL) {
852					yyerror("mode not supported "
853					    "for relays");
854					YYERROR;
855				}
856				dstmode = $2;
857				break;
858			}
859		}
860		;
861
862/* should be in sync with sbin/pfctl/parse.y's hashkey */
863hashkey		: /* empty */		{
864			$$.keyset = 0;
865			$$.key.data[0] = arc4random();
866			$$.key.data[1] = arc4random();
867			$$.key.data[2] = arc4random();
868			$$.key.data[3] = arc4random();
869		}
870		| STRING		{
871			/* manual key configuration */
872			$$.keyset = 1;
873
874			if (!strncmp($1, "0x", 2)) {
875				if (strlen($1) != 34) {
876					free($1);
877					yyerror("hex key must be 128 bits "
878					    "(32 hex digits) long");
879					YYERROR;
880				}
881
882				if (sscanf($1, "0x%8x%8x%8x%8x",
883				    &$$.key.data[0], &$$.key.data[1],
884				    &$$.key.data[2], &$$.key.data[3]) != 4) {
885					free($1);
886					yyerror("invalid hex key");
887					YYERROR;
888				}
889			} else {
890				MD5_CTX	context;
891
892				MD5Init(&context);
893				MD5Update(&context, (unsigned char *)$1,
894				    strlen($1));
895				MD5Final((unsigned char *)$$.key.data,
896				    &context);
897				HTONL($$.key.data[0]);
898				HTONL($$.key.data[1]);
899				HTONL($$.key.data[2]);
900				HTONL($$.key.data[3]);
901			}
902			free($1);
903		}
904		;
905
906tablecheck	: ICMP			{ table->conf.check = CHECK_ICMP; }
907		| TCP			{ table->conf.check = CHECK_TCP; }
908		| ssltls		{
909			table->conf.check = CHECK_TCP;
910			conf->sc_conf.flags |= F_TLS;
911			table->conf.flags |= F_TLS;
912		}
913		| http_type STRING hostname CODE NUMBER {
914			if ($1) {
915				conf->sc_conf.flags |= F_TLS;
916				table->conf.flags |= F_TLS;
917			}
918			table->conf.check = CHECK_HTTP_CODE;
919			if ((table->conf.retcode = $5) <= 0) {
920				yyerror("invalid HTTP code: %lld", $5);
921				free($2);
922				free($3);
923				YYERROR;
924			}
925			if (asprintf(&table->sendbuf,
926			    "HEAD %s HTTP/1.%c\r\n%s\r\n",
927			    $2, strlen($3) ? '1' : '0', $3) == -1)
928				fatal("asprintf");
929			free($2);
930			free($3);
931			if (table->sendbuf == NULL)
932				fatal("out of memory");
933		}
934		| http_type STRING hostname digest {
935			if ($1) {
936				conf->sc_conf.flags |= F_TLS;
937				table->conf.flags |= F_TLS;
938			}
939			table->conf.check = CHECK_HTTP_DIGEST;
940			if (asprintf(&table->sendbuf,
941			    "GET %s HTTP/1.%c\r\n%s\r\n",
942			    $2, strlen($3) ? '1' : '0', $3) == -1)
943				fatal("asprintf");
944			free($2);
945			free($3);
946			if (table->sendbuf == NULL)
947				fatal("out of memory");
948			if (strlcpy(table->conf.digest, $4.digest,
949			    sizeof(table->conf.digest)) >=
950			    sizeof(table->conf.digest)) {
951				yyerror("digest truncated");
952				free($4.digest);
953				YYERROR;
954			}
955			table->conf.digest_type = $4.type;
956			free($4.digest);
957		}
958		| SEND sendbuf EXPECT STRING opttls {
959			table->conf.check = CHECK_SEND_EXPECT;
960			if ($5) {
961				conf->sc_conf.flags |= F_TLS;
962				table->conf.flags |= F_TLS;
963			}
964			if (strlcpy(table->conf.exbuf, $4,
965			    sizeof(table->conf.exbuf))
966			    >= sizeof(table->conf.exbuf)) {
967				yyerror("yyparse: expect buffer truncated");
968				free($4);
969				YYERROR;
970			}
971			translate_string(table->conf.exbuf);
972			free($4);
973		}
974		| BINARY SEND sendbinbuf EXPECT STRING opttls {
975			table->conf.check = CHECK_BINSEND_EXPECT;
976			if ($6) {
977				conf->sc_conf.flags |= F_TLS;
978				table->conf.flags |= F_TLS;
979			}
980			if (strlen($5) == 0) {
981				yyerror("empty binary expect data");
982				free($5);
983				YYERROR;
984			}
985			if (strlcpy(table->conf.exbuf, $5,
986			    sizeof(table->conf.exbuf))
987			    >= sizeof(table->conf.exbuf)) {
988				yyerror("expect buffer truncated");
989				free($5);
990				YYERROR;
991			}
992			struct ibuf *ibuf = string2binary($5);
993			if (ibuf == NULL) {
994				yyerror("failed in binary expect data buffer");
995				ibuf_free(ibuf);
996				free($5);
997				YYERROR;
998			}
999			memcpy(table->conf.exbinbuf, ibuf->buf,
1000			    ibuf_size(ibuf));
1001			ibuf_free(ibuf);
1002			free($5);
1003		}
1004		| SCRIPT STRING {
1005			table->conf.check = CHECK_SCRIPT;
1006			if (strlcpy(table->conf.path, $2,
1007			    sizeof(table->conf.path)) >=
1008			    sizeof(table->conf.path)) {
1009				yyerror("script path truncated");
1010				free($2);
1011				YYERROR;
1012			}
1013			conf->sc_conf.flags |= F_SCRIPT;
1014			free($2);
1015		}
1016		;
1017
1018digest		: DIGEST STRING
1019		{
1020			switch (strlen($2)) {
1021			case 40:
1022				$$.type = DIGEST_SHA1;
1023				break;
1024			case 32:
1025				$$.type = DIGEST_MD5;
1026				break;
1027			default:
1028				yyerror("invalid http digest");
1029				free($2);
1030				YYERROR;
1031			}
1032			$$.digest = $2;
1033		}
1034		;
1035
1036optdigest	: digest			{
1037			$$.digest = $1.digest;
1038			$$.type = $1.type;
1039		}
1040		| STRING			{
1041			$$.digest = $1;
1042			$$.type = DIGEST_NONE;
1043		}
1044		;
1045
1046proto		: relay_proto PROTO STRING	{
1047			struct protocol	*p;
1048
1049			if (!loadcfg) {
1050				free($3);
1051				YYACCEPT;
1052			}
1053
1054			if (strcmp($3, "default") == 0) {
1055				p = &conf->sc_proto_default;
1056			} else {
1057				TAILQ_FOREACH(p, conf->sc_protos, entry)
1058					if (!strcmp(p->name, $3))
1059						break;
1060			}
1061			if (p != NULL) {
1062				yyerror("protocol %s defined twice", $3);
1063				free($3);
1064				YYERROR;
1065			}
1066			if ((p = calloc(1, sizeof (*p))) == NULL)
1067				fatal("out of memory");
1068
1069			if (strlcpy(p->name, $3, sizeof(p->name)) >=
1070			    sizeof(p->name)) {
1071				yyerror("protocol name truncated");
1072				free($3);
1073				free(p);
1074				YYERROR;
1075			}
1076			free($3);
1077			p->id = ++last_proto_id;
1078			p->type = $1;
1079			p->tcpflags = TCPFLAG_DEFAULT;
1080			p->tlsflags = TLSFLAG_DEFAULT;
1081			p->tcpbacklog = RELAY_BACKLOG;
1082			p->httpheaderlen = RELAY_DEFHEADERLENGTH;
1083			TAILQ_INIT(&p->rules);
1084			TAILQ_INIT(&p->tlscerts);
1085			(void)strlcpy(p->tlsciphers, TLSCIPHERS_DEFAULT,
1086			    sizeof(p->tlsciphers));
1087			(void)strlcpy(p->tlsecdhecurves, TLSECDHECURVES_DEFAULT,
1088			    sizeof(p->tlsecdhecurves));
1089			(void)strlcpy(p->tlsdhparams, TLSDHPARAM_DEFAULT,
1090			    sizeof(p->tlsdhparams));
1091			if (last_proto_id == INT_MAX) {
1092				yyerror("too many protocols defined");
1093				free(p);
1094				YYERROR;
1095			}
1096			proto = p;
1097		} protopts_n			{
1098			conf->sc_protocount++;
1099
1100			if ((proto->tlsflags & TLSFLAG_VERSION) == 0) {
1101				yyerror("invalid TLS protocol");
1102				YYERROR;
1103			}
1104			TAILQ_INSERT_TAIL(conf->sc_protos, proto, entry);
1105		}
1106		;
1107
1108protopts_n	: /* empty */
1109		| '{' '}'
1110		| '{' optnl protopts_l '}'
1111		;
1112
1113protopts_l	: protopts_l protoptsl nl
1114		| protoptsl optnl
1115		;
1116
1117protoptsl	: ssltls {
1118			if (!(proto->type == RELAY_PROTO_TCP ||
1119			    proto->type == RELAY_PROTO_HTTP)) {
1120				yyerror("can set tls options only for "
1121				    "tcp or http protocols");
1122				YYERROR;
1123			}
1124		} tlsflags
1125		| ssltls {
1126			if (!(proto->type == RELAY_PROTO_TCP ||
1127			    proto->type == RELAY_PROTO_HTTP)) {
1128				yyerror("can set tls options only for "
1129				    "tcp or http protocols");
1130				YYERROR;
1131			}
1132		} '{' tlsflags_l '}'
1133		| TCP {
1134			if (!(proto->type == RELAY_PROTO_TCP ||
1135			    proto->type == RELAY_PROTO_HTTP)) {
1136				yyerror("can set tcp options only for "
1137				    "tcp or http protocols");
1138				YYERROR;
1139			}
1140		} tcpflags
1141		| TCP {
1142			if (!(proto->type == RELAY_PROTO_TCP ||
1143			    proto->type == RELAY_PROTO_HTTP)) {
1144				yyerror("can set tcp options only for "
1145				    "tcp or http protocols");
1146				YYERROR;
1147			}
1148		} '{' tcpflags_l '}'
1149		| HTTP {
1150			if (proto->type != RELAY_PROTO_HTTP) {
1151				yyerror("can set http options only for "
1152				    "http protocol");
1153				YYERROR;
1154			}
1155		} httpflags
1156		| HTTP  {
1157			if (proto->type != RELAY_PROTO_HTTP) {
1158				yyerror("can set http options only for "
1159				    "http protocol");
1160				YYERROR;
1161			}
1162		} '{' httpflags_l '}'
1163		| RETURN ERROR opteflags	{ proto->flags |= F_RETURN; }
1164		| RETURN ERROR '{' eflags_l '}'	{ proto->flags |= F_RETURN; }
1165		| filterrule
1166		| include
1167		;
1168
1169
1170httpflags_l	: httpflags comma httpflags_l
1171		| httpflags
1172		;
1173
1174httpflags	: HEADERLEN NUMBER	{
1175			if ($2 < 0 || $2 > RELAY_MAXHEADERLENGTH) {
1176				yyerror("invalid headerlen: %lld", $2);
1177				YYERROR;
1178			}
1179			proto->httpheaderlen = $2;
1180		}
1181		| WEBSOCKETS	{ proto->httpflags |= HTTPFLAG_WEBSOCKETS; }
1182		| NO WEBSOCKETS	{ proto->httpflags &= ~HTTPFLAG_WEBSOCKETS; }
1183		;
1184
1185tcpflags_l	: tcpflags comma tcpflags_l
1186		| tcpflags
1187		;
1188
1189tcpflags	: SACK			{ proto->tcpflags |= TCPFLAG_SACK; }
1190		| NO SACK		{ proto->tcpflags |= TCPFLAG_NSACK; }
1191		| NODELAY		{ proto->tcpflags |= TCPFLAG_NODELAY; }
1192		| NO NODELAY		{ proto->tcpflags |= TCPFLAG_NNODELAY; }
1193		| SPLICE		{ /* default */ }
1194		| NO SPLICE		{ proto->tcpflags |= TCPFLAG_NSPLICE; }
1195		| BACKLOG NUMBER	{
1196			if ($2 < 0 || $2 > RELAY_MAX_BACKLOG) {
1197				yyerror("invalid backlog: %lld", $2);
1198				YYERROR;
1199			}
1200			proto->tcpbacklog = $2;
1201		}
1202		| SOCKET BUFFER NUMBER	{
1203			proto->tcpflags |= TCPFLAG_BUFSIZ;
1204			if ((proto->tcpbufsiz = $3) < 0) {
1205				yyerror("invalid socket buffer size: %lld", $3);
1206				YYERROR;
1207			}
1208		}
1209		| IP STRING NUMBER	{
1210			if ($3 < 0) {
1211				yyerror("invalid ttl: %lld", $3);
1212				free($2);
1213				YYERROR;
1214			}
1215			if (strcasecmp("ttl", $2) == 0) {
1216				proto->tcpflags |= TCPFLAG_IPTTL;
1217				proto->tcpipttl = $3;
1218			} else if (strcasecmp("minttl", $2) == 0) {
1219				proto->tcpflags |= TCPFLAG_IPMINTTL;
1220				proto->tcpipminttl = $3;
1221			} else {
1222				yyerror("invalid TCP/IP flag: %s", $2);
1223				free($2);
1224				YYERROR;
1225			}
1226			free($2);
1227		}
1228		;
1229
1230tlsflags_l	: tlsflags comma tlsflags_l
1231		| tlsflags
1232		;
1233
1234tlsflags	: SESSION TICKETS { proto->tickets = 1; }
1235		| NO SESSION TICKETS { proto->tickets = 0; }
1236		| CIPHERS STRING		{
1237			if (strlcpy(proto->tlsciphers, $2,
1238			    sizeof(proto->tlsciphers)) >=
1239			    sizeof(proto->tlsciphers)) {
1240				yyerror("tlsciphers truncated");
1241				free($2);
1242				YYERROR;
1243			}
1244			free($2);
1245		}
1246		| NO EDH			{
1247			(void)strlcpy(proto->tlsdhparams, "none",
1248			    sizeof(proto->tlsdhparams));
1249		}
1250		| EDH			{
1251			(void)strlcpy(proto->tlsdhparams, "auto",
1252			    sizeof(proto->tlsdhparams));
1253		}
1254		| EDH PARAMS STRING		{
1255			struct tls_config	*tls_cfg;
1256			if ((tls_cfg = tls_config_new()) == NULL) {
1257				yyerror("tls_config_new failed");
1258				free($3);
1259				YYERROR;
1260			}
1261			if (tls_config_set_dheparams(tls_cfg, $3) != 0) {
1262				yyerror("tls edh params %s: %s", $3,
1263				    tls_config_error(tls_cfg));
1264				tls_config_free(tls_cfg);
1265				free($3);
1266				YYERROR;
1267			}
1268			tls_config_free(tls_cfg);
1269			if (strlcpy(proto->tlsdhparams, $3,
1270			    sizeof(proto->tlsdhparams)) >=
1271			    sizeof(proto->tlsdhparams)) {
1272				yyerror("tls edh truncated");
1273				free($3);
1274				YYERROR;
1275			}
1276			free($3);
1277		}
1278		| ECDHE STRING			{
1279			struct tls_config	*tls_cfg;
1280			if ((tls_cfg = tls_config_new()) == NULL) {
1281				yyerror("tls_config_new failed");
1282				free($2);
1283				YYERROR;
1284			}
1285			if (tls_config_set_ecdhecurves(tls_cfg, $2) != 0) {
1286				yyerror("tls ecdhe %s: %s", $2,
1287				    tls_config_error(tls_cfg));
1288				tls_config_free(tls_cfg);
1289				free($2);
1290				YYERROR;
1291			}
1292			tls_config_free(tls_cfg);
1293			if (strlcpy(proto->tlsecdhecurves, $2,
1294			    sizeof(proto->tlsecdhecurves)) >=
1295			    sizeof(proto->tlsecdhecurves)) {
1296				yyerror("tls ecdhe curves truncated");
1297				free($2);
1298				YYERROR;
1299			}
1300			free($2);
1301		}
1302		| CA FILENAME STRING		{
1303			if (strlcpy(proto->tlsca, $3,
1304			    sizeof(proto->tlsca)) >=
1305			    sizeof(proto->tlsca)) {
1306				yyerror("tlsca truncated");
1307				free($3);
1308				YYERROR;
1309			}
1310			free($3);
1311		}
1312		| CA KEY STRING PASSWORD STRING	{
1313			if (strlcpy(proto->tlscakey, $3,
1314			    sizeof(proto->tlscakey)) >=
1315			    sizeof(proto->tlscakey)) {
1316				yyerror("tlscakey truncated");
1317				free($3);
1318				free($5);
1319				YYERROR;
1320			}
1321			if ((proto->tlscapass = strdup($5)) == NULL) {
1322				yyerror("tlscapass");
1323				free($3);
1324				free($5);
1325				YYERROR;
1326			}
1327			free($3);
1328			free($5);
1329		}
1330		| CA CERTIFICATE STRING		{
1331			if (strlcpy(proto->tlscacert, $3,
1332			    sizeof(proto->tlscacert)) >=
1333			    sizeof(proto->tlscacert)) {
1334				yyerror("tlscacert truncated");
1335				free($3);
1336				YYERROR;
1337			}
1338			free($3);
1339		}
1340		| KEYPAIR STRING		{
1341			struct keyname	*name;
1342
1343			if (strlen($2) >= PATH_MAX) {
1344				yyerror("keypair name too long");
1345				free($2);
1346				YYERROR;
1347			}
1348			if ((name = calloc(1, sizeof(*name))) == NULL) {
1349				yyerror("calloc");
1350				free($2);
1351				YYERROR;
1352			}
1353			name->name = $2;
1354			TAILQ_INSERT_TAIL(&proto->tlscerts, name, entry);
1355		}
1356		| NO flag			{ proto->tlsflags &= ~($2); }
1357		| flag				{ proto->tlsflags |= $1; }
1358		;
1359
1360flag		: STRING			{
1361			if (strcmp("sslv3", $1) == 0)
1362				$$ = TLSFLAG_SSLV3;
1363			else if (strcmp("tlsv1", $1) == 0)
1364				$$ = TLSFLAG_TLSV1;
1365			else if (strcmp("tlsv1.0", $1) == 0)
1366				$$ = TLSFLAG_TLSV1_0;
1367			else if (strcmp("tlsv1.1", $1) == 0)
1368				$$ = TLSFLAG_TLSV1_1;
1369			else if (strcmp("tlsv1.2", $1) == 0)
1370				$$ = TLSFLAG_TLSV1_2;
1371			else if (strcmp("tlsv1.3", $1) == 0)
1372				$$ = TLSFLAG_TLSV1_3;
1373			else if (strcmp("cipher-server-preference", $1) == 0)
1374				$$ = TLSFLAG_CIPHER_SERVER_PREF;
1375			else if (strcmp("client-renegotiation", $1) == 0)
1376				$$ = TLSFLAG_CLIENT_RENEG;
1377			else {
1378				yyerror("invalid TLS flag: %s", $1);
1379				free($1);
1380				YYERROR;
1381			}
1382			free($1);
1383		}
1384		;
1385
1386filterrule	: action dir quick ruleaf rulesrc ruledst {
1387			if ((rule = calloc(1, sizeof(*rule))) == NULL)
1388				fatal("out of memory");
1389
1390			rule->rule_action = $1;
1391			rule->rule_proto = proto->type;
1392			rule->rule_dir = $2;
1393			rule->rule_flags |= $3;
1394			rule->rule_af = $4;
1395			rule->rule_src.addr = $5.ss;
1396			rule->rule_src.addr_mask = $5.prefixlen;
1397			rule->rule_dst.addr = $6.ss;
1398			rule->rule_dst.addr_mask = $6.prefixlen;
1399
1400			if (RELAY_AF_NEQ(rule->rule_af,
1401			    rule->rule_src.addr.ss_family) ||
1402			    RELAY_AF_NEQ(rule->rule_af,
1403			    rule->rule_dst.addr.ss_family) ||
1404			    RELAY_AF_NEQ(rule->rule_src.addr.ss_family,
1405			    rule->rule_dst.addr.ss_family)) {
1406				yyerror("address family mismatch");
1407				YYERROR;
1408			}
1409
1410			rulefile = NULL;
1411		} ruleopts_l {
1412			if (rule_add(proto, rule, rulefile) == -1) {
1413				if (rulefile == NULL) {
1414					yyerror("failed to load rule");
1415				} else {
1416					yyerror("failed to load rules from %s",
1417					    rulefile);
1418					free(rulefile);
1419				}
1420				rule_free(rule);
1421				free(rule);
1422				YYERROR;
1423			}
1424			if (rulefile)
1425				free(rulefile);
1426			rulefile = NULL;
1427			rule = NULL;
1428			keytype = KEY_TYPE_NONE;
1429		}
1430		;
1431
1432action		: PASS				{ $$ = RULE_ACTION_PASS; }
1433		| BLOCK				{ $$ = RULE_ACTION_BLOCK; }
1434		| MATCH				{ $$ = RULE_ACTION_MATCH; }
1435		;
1436
1437dir		: /* empty */			{
1438			$$ = dir = RELAY_DIR_REQUEST;
1439		}
1440		| REQUEST			{
1441			$$ = dir = RELAY_DIR_REQUEST;
1442		}
1443		| RESPONSE			{
1444			$$ = dir = RELAY_DIR_RESPONSE;
1445		}
1446		;
1447
1448quick		: /* empty */			{ $$ = 0; }
1449		| QUICK				{ $$ = RULE_FLAG_QUICK; }
1450		;
1451
1452ruleaf		: /* empty */			{ $$ = AF_UNSPEC; }
1453		| INET6				{ $$ = AF_INET6; }
1454		| INET				{ $$ = AF_INET; }
1455		;
1456
1457rulesrc		: /* empty */		{
1458			memset(&$$, 0, sizeof($$));
1459		}
1460		| FROM addrprefix		{
1461			$$ = $2;
1462		}
1463		;
1464
1465ruledst		: /* empty */			{
1466			memset(&$$, 0, sizeof($$));
1467		}
1468		| TO addrprefix			{
1469			$$ = $2;
1470		}
1471		;
1472
1473ruleopts_l	: /* empty */
1474		| ruleopts_t
1475		;
1476
1477ruleopts_t	: ruleopts ruleopts_t
1478		| ruleopts
1479		;
1480
1481ruleopts	: METHOD STRING					{
1482			u_int	id;
1483			if ((id = relay_httpmethod_byname($2)) ==
1484			    HTTP_METHOD_NONE) {
1485				yyerror("unknown HTTP method currently not "
1486				    "supported");
1487				free($2);
1488				YYERROR;
1489			}
1490			rule->rule_method = id;
1491			free($2);
1492		}
1493		| COOKIE key_option STRING value		{
1494			keytype = KEY_TYPE_COOKIE;
1495			rule->rule_kv[keytype].kv_key = strdup($3);
1496			rule->rule_kv[keytype].kv_option = $2;
1497			rule->rule_kv[keytype].kv_value = (($4 != NULL) ?
1498			    strdup($4) : strdup("*"));
1499			if (rule->rule_kv[keytype].kv_key == NULL ||
1500			    rule->rule_kv[keytype].kv_value == NULL)
1501				fatal("out of memory");
1502			free($3);
1503			if ($4)
1504				free($4);
1505			rule->rule_kv[keytype].kv_type = keytype;
1506		}
1507		| COOKIE key_option				{
1508			keytype = KEY_TYPE_COOKIE;
1509			rule->rule_kv[keytype].kv_option = $2;
1510			rule->rule_kv[keytype].kv_type = keytype;
1511		}
1512		| HEADER key_option STRING value		{
1513			keytype = KEY_TYPE_HEADER;
1514			memset(&rule->rule_kv[keytype], 0,
1515			    sizeof(rule->rule_kv[keytype]));
1516			rule->rule_kv[keytype].kv_option = $2;
1517			rule->rule_kv[keytype].kv_key = strdup($3);
1518			rule->rule_kv[keytype].kv_value = (($4 != NULL) ?
1519			    strdup($4) : strdup("*"));
1520			if (rule->rule_kv[keytype].kv_key == NULL ||
1521			    rule->rule_kv[keytype].kv_value == NULL)
1522				fatal("out of memory");
1523			free($3);
1524			if ($4)
1525				free($4);
1526			rule->rule_kv[keytype].kv_type = keytype;
1527		}
1528		| HEADER key_option				{
1529			keytype = KEY_TYPE_HEADER;
1530			rule->rule_kv[keytype].kv_option = $2;
1531			rule->rule_kv[keytype].kv_type = keytype;
1532		}
1533		| PATH key_option STRING value			{
1534			keytype = KEY_TYPE_PATH;
1535			rule->rule_kv[keytype].kv_option = $2;
1536			rule->rule_kv[keytype].kv_key = strdup($3);
1537			rule->rule_kv[keytype].kv_value = (($4 != NULL) ?
1538			    strdup($4) : strdup("*"));
1539			if (rule->rule_kv[keytype].kv_key == NULL ||
1540			    rule->rule_kv[keytype].kv_value == NULL)
1541				fatal("out of memory");
1542			free($3);
1543			if ($4)
1544				free($4);
1545			rule->rule_kv[keytype].kv_type = keytype;
1546		}
1547		| PATH key_option				{
1548			keytype = KEY_TYPE_PATH;
1549			rule->rule_kv[keytype].kv_option = $2;
1550			rule->rule_kv[keytype].kv_type = keytype;
1551		}
1552		| PATH STRIP NUMBER				{
1553			char	*strip = NULL;
1554
1555			if ($3 < 0 || $3 > INT_MAX) {
1556				yyerror("invalid strip number");
1557				YYERROR;
1558			}
1559			if (asprintf(&strip, "%lld", $3) <= 0)
1560				fatal("can't parse strip");
1561			keytype = KEY_TYPE_PATH;
1562			rule->rule_kv[keytype].kv_option = KEY_OPTION_STRIP;
1563			rule->rule_kv[keytype].kv_value = strip;
1564			rule->rule_kv[keytype].kv_type = keytype;
1565		}
1566		| QUERYSTR key_option STRING value		{
1567			switch ($2) {
1568			case KEY_OPTION_APPEND:
1569			case KEY_OPTION_SET:
1570			case KEY_OPTION_REMOVE:
1571				yyerror("combining query type and the given "
1572				    "option is not supported");
1573				free($3);
1574				if ($4)
1575					free($4);
1576				YYERROR;
1577				break;
1578			}
1579			keytype = KEY_TYPE_QUERY;
1580			rule->rule_kv[keytype].kv_option = $2;
1581			rule->rule_kv[keytype].kv_key = strdup($3);
1582			rule->rule_kv[keytype].kv_value = (($4 != NULL) ?
1583			    strdup($4) : strdup("*"));
1584			if (rule->rule_kv[keytype].kv_key == NULL ||
1585			    rule->rule_kv[keytype].kv_value == NULL)
1586				fatal("out of memory");
1587			free($3);
1588			if ($4)
1589				free($4);
1590			rule->rule_kv[keytype].kv_type = keytype;
1591		}
1592		| QUERYSTR key_option				{
1593			switch ($2) {
1594			case KEY_OPTION_APPEND:
1595			case KEY_OPTION_SET:
1596			case KEY_OPTION_REMOVE:
1597				yyerror("combining query type and the given "
1598				    "option is not supported");
1599				YYERROR;
1600				break;
1601			}
1602			keytype = KEY_TYPE_QUERY;
1603			rule->rule_kv[keytype].kv_option = $2;
1604			rule->rule_kv[keytype].kv_type = keytype;
1605		}
1606		| URL key_option optdigest value			{
1607			switch ($2) {
1608			case KEY_OPTION_APPEND:
1609			case KEY_OPTION_SET:
1610			case KEY_OPTION_REMOVE:
1611				yyerror("combining url type and the given "
1612				"option is not supported");
1613				free($3.digest);
1614				free($4);
1615				YYERROR;
1616				break;
1617			}
1618			keytype = KEY_TYPE_URL;
1619			rule->rule_kv[keytype].kv_option = $2;
1620			rule->rule_kv[keytype].kv_key = strdup($3.digest);
1621			rule->rule_kv[keytype].kv_digest = $3.type;
1622			rule->rule_kv[keytype].kv_value = (($4 != NULL) ?
1623			    strdup($4) : strdup("*"));
1624			if (rule->rule_kv[keytype].kv_key == NULL ||
1625			    rule->rule_kv[keytype].kv_value == NULL)
1626				fatal("out of memory");
1627			free($3.digest);
1628			if ($4)
1629				free($4);
1630			rule->rule_kv[keytype].kv_type = keytype;
1631		}
1632		| URL key_option					{
1633			switch ($2) {
1634			case KEY_OPTION_APPEND:
1635			case KEY_OPTION_SET:
1636			case KEY_OPTION_REMOVE:
1637				yyerror("combining url type and the given "
1638				    "option is not supported");
1639				YYERROR;
1640				break;
1641			}
1642			keytype = KEY_TYPE_URL;
1643			rule->rule_kv[keytype].kv_option = $2;
1644			rule->rule_kv[keytype].kv_type = keytype;
1645		}
1646		| FORWARD TO table				{
1647			if (table_findbyname(conf, $3) == NULL) {
1648				yyerror("undefined forward table");
1649				free($3);
1650				YYERROR;
1651			}
1652			if (strlcpy(rule->rule_tablename, $3,
1653			    sizeof(rule->rule_tablename)) >=
1654			    sizeof(rule->rule_tablename)) {
1655				yyerror("invalid forward table name");
1656				free($3);
1657				YYERROR;
1658			}
1659			free($3);
1660		}
1661		| TAG STRING					{
1662			tag = tag_name2id($2);
1663			if (rule->rule_tag) {
1664				yyerror("tag already defined");
1665				free($2);
1666				rule_free(rule);
1667				free(rule);
1668				YYERROR;
1669			}
1670			if (tag == 0) {
1671				yyerror("invalid tag");
1672				free($2);
1673				rule_free(rule);
1674				free(rule);
1675				YYERROR;
1676			}
1677			rule->rule_tag = tag;
1678			if (strlcpy(rule->rule_tagname, $2,
1679			    sizeof(rule->rule_tagname)) >=
1680			    sizeof(rule->rule_tagname)) {
1681				yyerror("tag truncated");
1682				free($2);
1683				rule_free(rule);
1684				free(rule);
1685				YYERROR;
1686			}
1687			free($2);
1688		}
1689		| NO TAG					{
1690			if (tag == 0) {
1691				yyerror("no tag defined");
1692				YYERROR;
1693			}
1694			rule->rule_tag = -1;
1695			memset(rule->rule_tagname, 0,
1696			    sizeof(rule->rule_tagname));
1697		}
1698		| TAGGED STRING					{
1699			tagged = tag_name2id($2);
1700			if (rule->rule_tagged) {
1701				yyerror("tagged already defined");
1702				free($2);
1703				rule_free(rule);
1704				free(rule);
1705				YYERROR;
1706			}
1707			if (tagged == 0) {
1708				yyerror("invalid tag");
1709				free($2);
1710				rule_free(rule);
1711				free(rule);
1712				YYERROR;
1713			}
1714			rule->rule_tagged = tagged;
1715			if (strlcpy(rule->rule_taggedname, $2,
1716			    sizeof(rule->rule_taggedname)) >=
1717			    sizeof(rule->rule_taggedname)) {
1718				yyerror("tagged truncated");
1719				free($2);
1720				rule_free(rule);
1721				free(rule);
1722				YYERROR;
1723			}
1724			free($2);
1725		}
1726		| LABEL STRING					{
1727			label = label_name2id($2);
1728			if (rule->rule_label) {
1729				yyerror("label already defined");
1730				free($2);
1731				rule_free(rule);
1732				free(rule);
1733				YYERROR;
1734			}
1735			if (label == 0) {
1736				yyerror("invalid label");
1737				free($2);
1738				rule_free(rule);
1739				free(rule);
1740				YYERROR;
1741			}
1742			rule->rule_label = label;
1743			if (strlcpy(rule->rule_labelname, $2,
1744			    sizeof(rule->rule_labelname)) >=
1745			    sizeof(rule->rule_labelname)) {
1746				yyerror("label truncated");
1747				free($2);
1748				rule_free(rule);
1749				free(rule);
1750				YYERROR;
1751			}
1752			free($2);
1753		}
1754		| NO LABEL					{
1755			if (label == 0) {
1756				yyerror("no label defined");
1757				YYERROR;
1758			}
1759			rule->rule_label = -1;
1760			memset(rule->rule_labelname, 0,
1761			    sizeof(rule->rule_labelname));
1762		}
1763		| FILENAME STRING value				{
1764			if (rulefile != NULL) {
1765				yyerror("only one file per rule supported");
1766				free($2);
1767				free($3);
1768				rule_free(rule);
1769				free(rule);
1770				YYERROR;
1771			}
1772			if ($3) {
1773				if ((rule->rule_kv[keytype].kv_value =
1774				    strdup($3)) == NULL)
1775					fatal("out of memory");
1776				free($3);
1777			} else
1778				rule->rule_kv[keytype].kv_value = NULL;
1779			rulefile = $2;
1780		}
1781		;
1782
1783value		: /* empty */		{ $$ = NULL; }
1784		| VALUE STRING		{ $$ = $2; }
1785		;
1786
1787key_option	: /* empty */		{ $$ = KEY_OPTION_NONE; }
1788		| APPEND		{ $$ = KEY_OPTION_APPEND; }
1789		| SET			{ $$ = KEY_OPTION_SET; }
1790		| REMOVE		{ $$ = KEY_OPTION_REMOVE; }
1791		| HASH			{ $$ = KEY_OPTION_HASH; }
1792		| LOG			{ $$ = KEY_OPTION_LOG; }
1793		;
1794
1795relay		: RELAY STRING	{
1796			struct relay *r;
1797
1798			if (!loadcfg) {
1799				free($2);
1800				YYACCEPT;
1801			}
1802
1803			if ((r = calloc(1, sizeof (*r))) == NULL)
1804				fatal("out of memory");
1805			TAILQ_INIT(&relays);
1806
1807			if (strlcpy(r->rl_conf.name, $2,
1808			    sizeof(r->rl_conf.name)) >=
1809			    sizeof(r->rl_conf.name)) {
1810				yyerror("relay name truncated");
1811				free($2);
1812				free(r);
1813				YYERROR;
1814			}
1815			free($2);
1816			if (relay_id(r) == -1) {
1817				yyerror("too many relays defined");
1818				free(r);
1819				YYERROR;
1820			}
1821			r->rl_conf.timeout.tv_sec = RELAY_TIMEOUT;
1822			r->rl_proto = NULL;
1823			r->rl_conf.proto = EMPTY_ID;
1824			r->rl_conf.dstretry = 0;
1825			r->rl_tls_ca_fd = -1;
1826			r->rl_tls_cacert_fd = -1;
1827			TAILQ_INIT(&r->rl_tables);
1828			if (last_relay_id == INT_MAX) {
1829				yyerror("too many relays defined");
1830				free(r);
1831				YYERROR;
1832			}
1833			dstmode = RELAY_DSTMODE_DEFAULT;
1834			rlay = r;
1835		} '{' optnl relayopts_l '}'	{
1836			struct relay		*r;
1837			struct relay_config	*rlconf = &rlay->rl_conf;
1838			struct keyname		*name;
1839
1840			if (relay_findbyname(conf, rlconf->name) != NULL ||
1841			    relay_findbyaddr(conf, rlconf) != NULL) {
1842				yyerror("relay %s or listener defined twice",
1843				    rlconf->name);
1844				YYERROR;
1845			}
1846
1847			if (rlay->rl_conf.ss.ss_family == AF_UNSPEC) {
1848				yyerror("relay %s has no listener",
1849				    rlay->rl_conf.name);
1850				YYERROR;
1851			}
1852			if ((rlay->rl_conf.flags & (F_NATLOOK|F_DIVERT)) ==
1853			    (F_NATLOOK|F_DIVERT)) {
1854				yyerror("relay %s with conflicting nat lookup "
1855				    "and peer options", rlay->rl_conf.name);
1856				YYERROR;
1857			}
1858			if ((rlay->rl_conf.flags & (F_NATLOOK|F_DIVERT)) == 0 &&
1859			    rlay->rl_conf.dstss.ss_family == AF_UNSPEC &&
1860			    TAILQ_EMPTY(&rlay->rl_tables)) {
1861				yyerror("relay %s has no target, rdr, "
1862				    "or table", rlay->rl_conf.name);
1863				YYERROR;
1864			}
1865			if (rlay->rl_conf.proto == EMPTY_ID) {
1866				rlay->rl_proto = &conf->sc_proto_default;
1867				rlay->rl_conf.proto = conf->sc_proto_default.id;
1868			}
1869
1870			if (TAILQ_EMPTY(&rlay->rl_proto->tlscerts) &&
1871			    relay_load_certfiles(conf, rlay, NULL) == -1) {
1872				yyerror("cannot load certificates for relay %s",
1873				    rlay->rl_conf.name);
1874				YYERROR;
1875			}
1876			TAILQ_FOREACH(name, &rlay->rl_proto->tlscerts, entry) {
1877				if (relay_load_certfiles(conf,
1878				    rlay, name->name) == -1) {
1879					yyerror("cannot load keypair %s"
1880					    " for relay %s", name->name,
1881					    rlay->rl_conf.name);
1882					YYERROR;
1883				}
1884			}
1885
1886			conf->sc_relaycount++;
1887			SPLAY_INIT(&rlay->rl_sessions);
1888			TAILQ_INSERT_TAIL(conf->sc_relays, rlay, rl_entry);
1889
1890			tableport = 0;
1891
1892			while ((r = TAILQ_FIRST(&relays)) != NULL) {
1893				TAILQ_REMOVE(&relays, r, rl_entry);
1894				if (relay_inherit(rlay, r) == NULL) {
1895					YYERROR;
1896				}
1897			}
1898			rlay = NULL;
1899		}
1900		;
1901
1902relayopts_l	: relayopts_l relayoptsl nl
1903		| relayoptsl optnl
1904		;
1905
1906relayoptsl	: LISTEN ON STRING port opttls {
1907			struct addresslist	 al;
1908			struct address		*h;
1909			struct relay		*r;
1910
1911			if (rlay->rl_conf.ss.ss_family != AF_UNSPEC) {
1912				if ((r = calloc(1, sizeof (*r))) == NULL)
1913					fatal("out of memory");
1914				TAILQ_INSERT_TAIL(&relays, r, rl_entry);
1915			} else
1916				r = rlay;
1917			if ($4.op != PF_OP_EQ) {
1918				yyerror("invalid port");
1919				free($3);
1920				YYERROR;
1921			}
1922
1923			TAILQ_INIT(&al);
1924			if (host($3, &al, 1, &$4, NULL, -1) <= 0) {
1925				yyerror("invalid listen ip: %s", $3);
1926				free($3);
1927				YYERROR;
1928			}
1929			free($3);
1930			h = TAILQ_FIRST(&al);
1931			bcopy(&h->ss, &r->rl_conf.ss, sizeof(r->rl_conf.ss));
1932			r->rl_conf.port = h->port.val[0];
1933			if ($5) {
1934				r->rl_conf.flags |= F_TLS;
1935				conf->sc_conf.flags |= F_TLS;
1936			}
1937			tableport = h->port.val[0];
1938			host_free(&al);
1939		}
1940		| forwardmode opttlsclient TO forwardspec dstaf {
1941			rlay->rl_conf.fwdmode = $1;
1942			if ($1 == FWD_ROUTE) {
1943				yyerror("no route for relays");
1944				YYERROR;
1945			}
1946			if ($2) {
1947				rlay->rl_conf.flags |= F_TLSCLIENT;
1948				conf->sc_conf.flags |= F_TLSCLIENT;
1949			}
1950		}
1951		| SESSION TIMEOUT NUMBER		{
1952			if ((rlay->rl_conf.timeout.tv_sec = $3) < 0) {
1953				yyerror("invalid timeout: %lld", $3);
1954				YYERROR;
1955			}
1956			if (rlay->rl_conf.timeout.tv_sec > INT_MAX) {
1957				yyerror("timeout too large: %lld", $3);
1958				YYERROR;
1959			}
1960		}
1961		| PROTO STRING			{
1962			struct protocol *p;
1963
1964			if (rlay->rl_conf.proto != EMPTY_ID) {
1965				yyerror("more than one protocol specified");
1966				YYERROR;
1967			}
1968
1969			TAILQ_FOREACH(p, conf->sc_protos, entry)
1970				if (!strcmp(p->name, $2))
1971					break;
1972			if (p == NULL) {
1973				yyerror("no such protocol: %s", $2);
1974				free($2);
1975				YYERROR;
1976			}
1977			p->flags |= F_USED;
1978			rlay->rl_conf.proto = p->id;
1979			rlay->rl_proto = p;
1980			free($2);
1981		}
1982		| DISABLE		{ rlay->rl_conf.flags |= F_DISABLE; }
1983		| include
1984		;
1985
1986forwardspec	: STRING port retry	{
1987			struct addresslist	 al;
1988			struct address		*h;
1989
1990			if (rlay->rl_conf.dstss.ss_family != AF_UNSPEC) {
1991				yyerror("relay %s target or redirection "
1992				    "already specified", rlay->rl_conf.name);
1993				free($1);
1994				YYERROR;
1995			}
1996			if ($2.op != PF_OP_EQ) {
1997				yyerror("invalid port");
1998				free($1);
1999				YYERROR;
2000			}
2001
2002			TAILQ_INIT(&al);
2003			if (host($1, &al, 1, &$2, NULL, -1) <= 0) {
2004				yyerror("invalid forward ip: %s", $1);
2005				free($1);
2006				YYERROR;
2007			}
2008			free($1);
2009			h = TAILQ_FIRST(&al);
2010			bcopy(&h->ss, &rlay->rl_conf.dstss,
2011			    sizeof(rlay->rl_conf.dstss));
2012			rlay->rl_conf.dstport = h->port.val[0];
2013			rlay->rl_conf.dstretry = $3;
2014			host_free(&al);
2015		}
2016		| NAT LOOKUP retry	{
2017			conf->sc_conf.flags |= F_NEEDPF;
2018			rlay->rl_conf.flags |= F_NATLOOK;
2019			rlay->rl_conf.dstretry = $3;
2020		}
2021		| DESTINATION retry		{
2022			conf->sc_conf.flags |= F_NEEDPF;
2023			rlay->rl_conf.flags |= F_DIVERT;
2024			rlay->rl_conf.dstretry = $2;
2025		}
2026		| tablespec	{
2027			struct relay_table	*rlt;
2028
2029			if ((rlt = calloc(1, sizeof(*rlt))) == NULL) {
2030				yyerror("failed to allocate table reference");
2031				YYERROR;
2032			}
2033
2034			rlt->rlt_table = $1;
2035			rlt->rlt_table->conf.flags |= F_USED;
2036			rlt->rlt_mode = dstmode;
2037			rlt->rlt_flags = F_USED;
2038			if (!TAILQ_EMPTY(&rlay->rl_tables))
2039				rlt->rlt_flags |= F_BACKUP;
2040
2041			if (hashkey != NULL &&
2042			    (rlay->rl_conf.flags & F_HASHKEY) == 0) {
2043				memcpy(&rlay->rl_conf.hashkey,
2044				    hashkey, sizeof(rlay->rl_conf.hashkey));
2045				rlay->rl_conf.flags |= F_HASHKEY;
2046			}
2047			free(hashkey);
2048			hashkey = NULL;
2049
2050			TAILQ_INSERT_TAIL(&rlay->rl_tables, rlt, rlt_entry);
2051		}
2052		;
2053
2054dstmode		: /* empty */		{ $$ = RELAY_DSTMODE_DEFAULT; }
2055		| LOADBALANCE		{ $$ = RELAY_DSTMODE_LOADBALANCE; }
2056		| ROUNDROBIN		{ $$ = RELAY_DSTMODE_ROUNDROBIN; }
2057		| HASH			{ $$ = RELAY_DSTMODE_HASH; }
2058		| LEASTSTATES		{ $$ = RELAY_DSTMODE_LEASTSTATES; }
2059		| SRCHASH		{ $$ = RELAY_DSTMODE_SRCHASH; }
2060		| RANDOM		{ $$ = RELAY_DSTMODE_RANDOM; }
2061		;
2062
2063router		: ROUTER STRING		{
2064			struct router *rt = NULL;
2065
2066			if (!loadcfg) {
2067				free($2);
2068				YYACCEPT;
2069			}
2070
2071			conf->sc_conf.flags |= F_NEEDRT;
2072			TAILQ_FOREACH(rt, conf->sc_rts, rt_entry)
2073				if (!strcmp(rt->rt_conf.name, $2))
2074					break;
2075			if (rt != NULL) {
2076				yyerror("router %s defined twice", $2);
2077				free($2);
2078				YYERROR;
2079			}
2080
2081			if ((rt = calloc(1, sizeof (*rt))) == NULL)
2082				fatal("out of memory");
2083
2084			if (strlcpy(rt->rt_conf.name, $2,
2085			    sizeof(rt->rt_conf.name)) >=
2086			    sizeof(rt->rt_conf.name)) {
2087				yyerror("router name truncated");
2088				free(rt);
2089				YYERROR;
2090			}
2091			free($2);
2092			rt->rt_conf.id = ++last_rt_id;
2093			if (last_rt_id == INT_MAX) {
2094				yyerror("too many routers defined");
2095				free(rt);
2096				YYERROR;
2097			}
2098			TAILQ_INIT(&rt->rt_netroutes);
2099			router = rt;
2100
2101			tableport = -1;
2102		} '{' optnl routeopts_l '}'	{
2103			if (!router->rt_conf.nroutes) {
2104				yyerror("router %s without routes",
2105				    router->rt_conf.name);
2106				free(router);
2107				router = NULL;
2108				YYERROR;
2109			}
2110
2111			conf->sc_routercount++;
2112			TAILQ_INSERT_TAIL(conf->sc_rts, router, rt_entry);
2113			router = NULL;
2114
2115			tableport = 0;
2116		}
2117		;
2118
2119routeopts_l	: routeopts_l routeoptsl nl
2120		| routeoptsl optnl
2121		;
2122
2123routeoptsl	: ROUTE addrprefix {
2124			struct netroute	*nr;
2125
2126			if (router->rt_conf.af == AF_UNSPEC)
2127				router->rt_conf.af = $2.ss.ss_family;
2128			else if (router->rt_conf.af != $2.ss.ss_family) {
2129				yyerror("router %s address family mismatch",
2130				    router->rt_conf.name);
2131				YYERROR;
2132			}
2133
2134			if ((nr = calloc(1, sizeof(*nr))) == NULL)
2135				fatal("out of memory");
2136
2137			nr->nr_conf.id = ++last_nr_id;
2138			if (last_nr_id == INT_MAX) {
2139				yyerror("too many routes defined");
2140				free(nr);
2141				YYERROR;
2142			}
2143			nr->nr_conf.prefixlen = $2.prefixlen;
2144			nr->nr_conf.routerid = router->rt_conf.id;
2145			nr->nr_router = router;
2146			bcopy(&$2.ss, &nr->nr_conf.ss, sizeof($2.ss));
2147
2148			router->rt_conf.nroutes++;
2149			conf->sc_routecount++;
2150			TAILQ_INSERT_TAIL(&router->rt_netroutes, nr, nr_entry);
2151			TAILQ_INSERT_TAIL(conf->sc_routes, nr, nr_route);
2152		}
2153		| FORWARD TO tablespec {
2154			free(hashkey);
2155			hashkey = NULL;
2156
2157			if (router->rt_gwtable) {
2158				yyerror("router %s table already specified",
2159				    router->rt_conf.name);
2160				purge_table(conf, conf->sc_tables, $3);
2161				YYERROR;
2162			}
2163			router->rt_gwtable = $3;
2164			router->rt_gwtable->conf.flags |= F_USED;
2165			router->rt_conf.gwtable = $3->conf.id;
2166			router->rt_conf.gwport = $3->conf.port;
2167		}
2168		| RTABLE NUMBER {
2169			if (router->rt_conf.rtable) {
2170				yyerror("router %s rtable already specified",
2171				    router->rt_conf.name);
2172				YYERROR;
2173			}
2174			if ($2 < 0 || $2 > RT_TABLEID_MAX) {
2175				yyerror("invalid rtable id %lld", $2);
2176				YYERROR;
2177			}
2178			router->rt_conf.rtable = $2;
2179		}
2180		| RTLABEL STRING {
2181			if (strlcpy(router->rt_conf.label, $2,
2182			    sizeof(router->rt_conf.label)) >=
2183			    sizeof(router->rt_conf.label)) {
2184				yyerror("route label truncated");
2185				free($2);
2186				YYERROR;
2187			}
2188			free($2);
2189		}
2190		| DISABLE		{ rlay->rl_conf.flags |= F_DISABLE; }
2191		| include
2192		;
2193
2194dstaf		: /* empty */		{
2195			rlay->rl_conf.dstaf.ss_family = AF_UNSPEC;
2196		}
2197		| INET			{
2198			rlay->rl_conf.dstaf.ss_family = AF_INET;
2199		}
2200		| INET6	STRING		{
2201			struct sockaddr_in6	*sin6;
2202
2203			sin6 = (struct sockaddr_in6 *)&rlay->rl_conf.dstaf;
2204			if (inet_pton(AF_INET6, $2, &sin6->sin6_addr) == -1) {
2205				yyerror("invalid ipv6 address %s", $2);
2206				free($2);
2207				YYERROR;
2208			}
2209			free($2);
2210
2211			sin6->sin6_family = AF_INET6;
2212			sin6->sin6_len = sizeof(*sin6);
2213		}
2214		;
2215
2216interface	: /* empty */		{ $$ = NULL; }
2217		| INTERFACE STRING	{ $$ = $2; }
2218		;
2219
2220host		: address	{
2221			if ((hst = calloc(1, sizeof(*(hst)))) == NULL)
2222				fatal("out of memory");
2223
2224			if (strlcpy(hst->conf.name, $1.name,
2225			    sizeof(hst->conf.name)) >= sizeof(hst->conf.name)) {
2226				yyerror("host name truncated");
2227				free(hst);
2228				YYERROR;
2229			}
2230			bcopy(&$1.ss, &hst->conf.ss, sizeof($1.ss));
2231			hst->conf.id = 0; /* will be set later */
2232			SLIST_INIT(&hst->children);
2233		} opthostflags {
2234			$$ = hst;
2235			hst = NULL;
2236		}
2237		;
2238
2239opthostflags	: /* empty */
2240		| hostflags_l
2241		;
2242
2243hostflags_l	: hostflags hostflags_l
2244		| hostflags
2245		;
2246
2247hostflags	: RETRY NUMBER		{
2248			if (hst->conf.retry) {
2249				yyerror("retry value already set");
2250				YYERROR;
2251			}
2252			if ($2 < 0) {
2253				yyerror("invalid retry value: %lld\n", $2);
2254				YYERROR;
2255			}
2256			hst->conf.retry = $2;
2257		}
2258		| PARENT NUMBER		{
2259			if (hst->conf.parentid) {
2260				yyerror("parent value already set");
2261				YYERROR;
2262			}
2263			if ($2 < 0) {
2264				yyerror("invalid parent value: %lld\n", $2);
2265				YYERROR;
2266			}
2267			hst->conf.parentid = $2;
2268		}
2269		| PRIORITY NUMBER		{
2270			if (hst->conf.priority) {
2271				yyerror("priority already set");
2272				YYERROR;
2273			}
2274			if ($2 < 0 || $2 > RTP_MAX) {
2275				yyerror("invalid priority value: %lld\n", $2);
2276				YYERROR;
2277			}
2278			hst->conf.priority = $2;
2279		}
2280		| IP TTL NUMBER		{
2281			if (hst->conf.ttl) {
2282				yyerror("ttl value already set");
2283				YYERROR;
2284			}
2285			if ($3 < 0) {
2286				yyerror("invalid ttl value: %lld\n", $3);
2287				YYERROR;
2288			}
2289			hst->conf.ttl = $3;
2290		}
2291		;
2292
2293address		: STRING	{
2294			struct address *h;
2295			struct addresslist al;
2296
2297			if (strlcpy($$.name, $1,
2298			    sizeof($$.name)) >= sizeof($$.name)) {
2299				yyerror("host name truncated");
2300				free($1);
2301				YYERROR;
2302			}
2303
2304			TAILQ_INIT(&al);
2305			if (host($1, &al, 1, NULL, NULL, -1) <= 0) {
2306				yyerror("invalid host %s", $1);
2307				free($1);
2308				YYERROR;
2309			}
2310			free($1);
2311			h = TAILQ_FIRST(&al);
2312			memcpy(&$$.ss, &h->ss, sizeof($$.ss));
2313			host_free(&al);
2314		}
2315		;
2316
2317addrprefix	: address '/' NUMBER 		{
2318			$$ = $1;
2319			if (($$.ss.ss_family == AF_INET &&
2320			    ($3 > 32 || $3 < 0)) ||
2321			    ($$.ss.ss_family == AF_INET6 &&
2322			    ($3 > 128 || $3 < 0))) {
2323				yyerror("invalid prefixlen %lld", $3);
2324				YYERROR;
2325			}
2326			$$.prefixlen = $3;
2327		}
2328		| address			{
2329			$$ = $1;
2330			if ($$.ss.ss_family == AF_INET)
2331				$$.prefixlen = 32;
2332			else if ($$.ss.ss_family == AF_INET6)
2333				$$.prefixlen = 128;
2334		}
2335		;
2336
2337retry		: /* empty */		{ $$ = 0; }
2338		| RETRY NUMBER		{
2339			if (($$ = $2) < 0) {
2340				yyerror("invalid retry value: %lld\n", $2);
2341				YYERROR;
2342			}
2343		}
2344		;
2345
2346timeout		: NUMBER
2347		{
2348			if ($1 < 0) {
2349				yyerror("invalid timeout: %lld\n", $1);
2350				YYERROR;
2351			}
2352			$$.tv_sec = $1 / 1000;
2353			$$.tv_usec = ($1 % 1000) * 1000;
2354		}
2355		;
2356
2357comma		: ','
2358		| nl
2359		| /* empty */
2360		;
2361
2362optnl		: '\n' optnl
2363		|
2364		;
2365
2366nl		: '\n' optnl
2367		;
2368%%
2369
2370struct keywords {
2371	const char	*k_name;
2372	int		 k_val;
2373};
2374
2375int
2376yyerror(const char *fmt, ...)
2377{
2378	va_list		 ap;
2379	char		*msg;
2380
2381	file->errors++;
2382	va_start(ap, fmt);
2383	if (vasprintf(&msg, fmt, ap) == -1)
2384		fatalx("yyerror vasprintf");
2385	va_end(ap);
2386	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
2387	free(msg);
2388	return (0);
2389}
2390
2391int
2392kw_cmp(const void *k, const void *e)
2393{
2394	return (strcmp(k, ((const struct keywords *)e)->k_name));
2395}
2396
2397int
2398lookup(char *s)
2399{
2400	/* this has to be sorted always */
2401	static const struct keywords keywords[] = {
2402		{ "agentx",		AGENTX },
2403		{ "append",		APPEND },
2404		{ "backlog",		BACKLOG },
2405		{ "backup",		BACKUP },
2406		{ "binary",		BINARY },
2407		{ "block",		BLOCK },
2408		{ "buffer",		BUFFER },
2409		{ "ca",			CA },
2410		{ "cache",		CACHE },
2411		{ "cert",		CERTIFICATE },
2412		{ "changes",		CHANGES },
2413		{ "check",		CHECK },
2414		{ "checks",		CHECKS },
2415		{ "ciphers",		CIPHERS },
2416		{ "code",		CODE },
2417		{ "connection",		CONNECTION },
2418		{ "context",		CONTEXT },
2419		{ "cookie",		COOKIE },
2420		{ "demote",		DEMOTE },
2421		{ "destination",	DESTINATION },
2422		{ "digest",		DIGEST },
2423		{ "disable",		DISABLE },
2424		{ "ecdhe",		ECDHE },
2425		{ "edh",		EDH },
2426		{ "error",		ERROR },
2427		{ "errors",		ERRORS },
2428		{ "expect",		EXPECT },
2429		{ "external",		EXTERNAL },
2430		{ "file",		FILENAME },
2431		{ "forward",		FORWARD },
2432		{ "from",		FROM },
2433		{ "hash",		HASH },
2434		{ "header",		HEADER },
2435		{ "headerlen",		HEADERLEN },
2436		{ "host",		HOST },
2437		{ "http",		HTTP },
2438		{ "icmp",		ICMP },
2439		{ "include",		INCLUDE },
2440		{ "inet",		INET },
2441		{ "inet6",		INET6 },
2442		{ "interface",		INTERFACE },
2443		{ "interval",		INTERVAL },
2444		{ "ip",			IP },
2445		{ "key",		KEY },
2446		{ "keypair",		KEYPAIR },
2447		{ "label",		LABEL },
2448		{ "least-states",	LEASTSTATES },
2449		{ "listen",		LISTEN },
2450		{ "loadbalance",	LOADBALANCE },
2451		{ "log",		LOG },
2452		{ "lookup",		LOOKUP },
2453		{ "match",		MATCH },
2454		{ "method",		METHOD },
2455		{ "mode",		MODE },
2456		{ "nat",		NAT },
2457		{ "no",			NO },
2458		{ "nodelay",		NODELAY },
2459		{ "nothing",		NOTHING },
2460		{ "on",			ON },
2461		{ "params",		PARAMS },
2462		{ "parent",		PARENT },
2463		{ "pass",		PASS },
2464		{ "password",		PASSWORD },
2465		{ "path",		PATH },
2466		{ "pftag",		PFTAG },
2467		{ "port",		PORT },
2468		{ "prefork",		PREFORK },
2469		{ "priority",		PRIORITY },
2470		{ "protocol",		PROTO },
2471		{ "query",		QUERYSTR },
2472		{ "quick",		QUICK },
2473		{ "random",		RANDOM },
2474		{ "real",		REAL },
2475		{ "redirect",		REDIRECT },
2476		{ "relay",		RELAY },
2477		{ "remove",		REMOVE },
2478		{ "request",		REQUEST },
2479		{ "response",		RESPONSE },
2480		{ "retry",		RETRY },
2481		{ "return",		RETURN },
2482		{ "roundrobin",		ROUNDROBIN },
2483		{ "route",		ROUTE },
2484		{ "router",		ROUTER },
2485		{ "rtable",		RTABLE },
2486		{ "rtlabel",		RTLABEL },
2487		{ "sack",		SACK },
2488		{ "script",		SCRIPT },
2489		{ "send",		SEND },
2490		{ "session",		SESSION },
2491		{ "set",		SET },
2492		{ "socket",		SOCKET },
2493		{ "source-hash",	SRCHASH },
2494		{ "splice",		SPLICE },
2495		{ "ssl",		SSL },
2496		{ "state",		STATE },
2497		{ "sticky-address",	STICKYADDR },
2498		{ "strip",		STRIP },
2499		{ "style",		STYLE },
2500		{ "table",		TABLE },
2501		{ "tag",		TAG },
2502		{ "tagged",		TAGGED },
2503		{ "tcp",		TCP },
2504		{ "tickets",		TICKETS },
2505		{ "timeout",		TIMEOUT },
2506		{ "tls",		TLS },
2507		{ "to",			TO },
2508		{ "transparent",	TRANSPARENT },
2509		{ "ttl",		TTL },
2510		{ "url",		URL },
2511		{ "value",		VALUE },
2512		{ "websockets",		WEBSOCKETS },
2513		{ "with",		WITH }
2514	};
2515	const struct keywords	*p;
2516
2517	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
2518	    sizeof(keywords[0]), kw_cmp);
2519
2520	if (p)
2521		return (p->k_val);
2522	else
2523		return (STRING);
2524}
2525
2526
2527#define START_EXPAND	1
2528#define DONE_EXPAND	2
2529
2530static int	expanding;
2531
2532int
2533igetc(void)
2534{
2535	int	c;
2536
2537	while (1) {
2538		if (file->ungetpos > 0)
2539			c = file->ungetbuf[--file->ungetpos];
2540		else c = getc(file->stream);
2541
2542		if (c == START_EXPAND)
2543			expanding = 1;
2544		else if (c == DONE_EXPAND)
2545			expanding = 0;
2546		else
2547			break;
2548	}
2549	return (c);
2550}
2551
2552int
2553lgetc(int quotec)
2554{
2555	int		c, next;
2556
2557	if (quotec) {
2558		if ((c = igetc()) == EOF) {
2559			yyerror("reached end of file while parsing "
2560			    "quoted string");
2561			if (file == topfile || popfile() == EOF)
2562				return (EOF);
2563			return (quotec);
2564		}
2565		return (c);
2566	}
2567
2568	while ((c = igetc()) == '\\') {
2569		next = igetc();
2570		if (next != '\n') {
2571			c = next;
2572			break;
2573		}
2574		yylval.lineno = file->lineno;
2575		file->lineno++;
2576	}
2577
2578	if (c == EOF) {
2579		/*
2580		 * Fake EOL when hit EOF for the first time. This gets line
2581		 * count right if last line in included file is syntactically
2582		 * invalid and has no newline.
2583		 */
2584		if (file->eof_reached == 0) {
2585			file->eof_reached = 1;
2586			return ('\n');
2587		}
2588		while (c == EOF) {
2589			if (file == topfile || popfile() == EOF)
2590				return (EOF);
2591			c = igetc();
2592		}
2593	}
2594	return (c);
2595}
2596
2597void
2598lungetc(int c)
2599{
2600	if (c == EOF)
2601		return;
2602
2603	if (file->ungetpos >= file->ungetsize) {
2604		void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
2605		if (p == NULL)
2606			err(1, "%s", __func__);
2607		file->ungetbuf = p;
2608		file->ungetsize *= 2;
2609	}
2610	file->ungetbuf[file->ungetpos++] = c;
2611}
2612
2613int
2614findeol(void)
2615{
2616	int	c;
2617
2618	/* skip to either EOF or the first real EOL */
2619	while (1) {
2620		c = lgetc(0);
2621		if (c == '\n') {
2622			file->lineno++;
2623			break;
2624		}
2625		if (c == EOF)
2626			break;
2627	}
2628	return (ERROR);
2629}
2630
2631int
2632yylex(void)
2633{
2634	u_char	 buf[8096];
2635	u_char	*p, *val;
2636	int	 quotec, next, c;
2637	int	 token;
2638
2639top:
2640	p = buf;
2641	while ((c = lgetc(0)) == ' ' || c == '\t')
2642		; /* nothing */
2643
2644	yylval.lineno = file->lineno;
2645	if (c == '#')
2646		while ((c = lgetc(0)) != '\n' && c != EOF)
2647			; /* nothing */
2648	if (c == '$' && !expanding) {
2649		while (1) {
2650			if ((c = lgetc(0)) == EOF)
2651				return (0);
2652
2653			if (p + 1 >= buf + sizeof(buf) - 1) {
2654				yyerror("string too long");
2655				return (findeol());
2656			}
2657			if (isalnum(c) || c == '_') {
2658				*p++ = c;
2659				continue;
2660			}
2661			*p = '\0';
2662			lungetc(c);
2663			break;
2664		}
2665		val = symget(buf);
2666		if (val == NULL) {
2667			yyerror("macro '%s' not defined", buf);
2668			return (findeol());
2669		}
2670		p = val + strlen(val) - 1;
2671		lungetc(DONE_EXPAND);
2672		while (p >= val) {
2673			lungetc(*p);
2674			p--;
2675		}
2676		lungetc(START_EXPAND);
2677		goto top;
2678	}
2679
2680	switch (c) {
2681	case '\'':
2682	case '"':
2683		quotec = c;
2684		while (1) {
2685			if ((c = lgetc(quotec)) == EOF)
2686				return (0);
2687			if (c == '\n') {
2688				file->lineno++;
2689				continue;
2690			} else if (c == '\\') {
2691				if ((next = lgetc(quotec)) == EOF)
2692					return (0);
2693				if (next == quotec || next == ' ' ||
2694				    next == '\t')
2695					c = next;
2696				else if (next == '\n') {
2697					file->lineno++;
2698					continue;
2699				} else
2700					lungetc(next);
2701			} else if (c == quotec) {
2702				*p = '\0';
2703				break;
2704			} else if (c == '\0') {
2705				yyerror("syntax error");
2706				return (findeol());
2707			}
2708			if (p + 1 >= buf + sizeof(buf) - 1) {
2709				yyerror("string too long");
2710				return (findeol());
2711			}
2712			*p++ = c;
2713		}
2714		yylval.v.string = strdup(buf);
2715		if (yylval.v.string == NULL)
2716			err(1, "%s", __func__);
2717		return (STRING);
2718	}
2719
2720#define allowed_to_end_number(x) \
2721	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
2722
2723	if (c == '-' || isdigit(c)) {
2724		do {
2725			*p++ = c;
2726			if ((size_t)(p-buf) >= sizeof(buf)) {
2727				yyerror("string too long");
2728				return (findeol());
2729			}
2730		} while ((c = lgetc(0)) != EOF && isdigit(c));
2731		lungetc(c);
2732		if (p == buf + 1 && buf[0] == '-')
2733			goto nodigits;
2734		if (c == EOF || allowed_to_end_number(c)) {
2735			const char *errstr = NULL;
2736
2737			*p = '\0';
2738			yylval.v.number = strtonum(buf, LLONG_MIN,
2739			    LLONG_MAX, &errstr);
2740			if (errstr) {
2741				yyerror("\"%s\" invalid number: %s",
2742				    buf, errstr);
2743				return (findeol());
2744			}
2745			return (NUMBER);
2746		} else {
2747nodigits:
2748			while (p > buf + 1)
2749				lungetc(*--p);
2750			c = *--p;
2751			if (c == '-')
2752				return (c);
2753		}
2754	}
2755
2756#define allowed_in_string(x) \
2757	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
2758	x != '{' && x != '}' && x != '<' && x != '>' && \
2759	x != '!' && x != '=' && x != '#' && \
2760	x != ',' && x != '/'))
2761
2762	if (isalnum(c) || c == ':' || c == '_') {
2763		do {
2764			*p++ = c;
2765			if ((size_t)(p-buf) >= sizeof(buf)) {
2766				yyerror("string too long");
2767				return (findeol());
2768			}
2769		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
2770		lungetc(c);
2771		*p = '\0';
2772		if ((token = lookup(buf)) == STRING)
2773			if ((yylval.v.string = strdup(buf)) == NULL)
2774				err(1, "%s", __func__);
2775		return (token);
2776	}
2777	if (c == '\n') {
2778		yylval.lineno = file->lineno;
2779		file->lineno++;
2780	}
2781	if (c == EOF)
2782		return (0);
2783	return (c);
2784}
2785
2786int
2787check_file_secrecy(int fd, const char *fname)
2788{
2789	struct stat	st;
2790
2791	if (fstat(fd, &st)) {
2792		log_warn("cannot stat %s", fname);
2793		return (-1);
2794	}
2795	if (st.st_uid != 0 && st.st_uid != getuid()) {
2796		log_warnx("%s: owner not root or current user", fname);
2797		return (-1);
2798	}
2799	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
2800		log_warnx("%s: group writable or world read/writable", fname);
2801		return (-1);
2802	}
2803	return (0);
2804}
2805
2806struct file *
2807pushfile(const char *name, int secret)
2808{
2809	struct file	*nfile;
2810
2811	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
2812		log_warn("%s", __func__);
2813		return (NULL);
2814	}
2815	if ((nfile->name = strdup(name)) == NULL) {
2816		log_warn("%s", __func__);
2817		free(nfile);
2818		return (NULL);
2819	}
2820	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
2821		log_warn("%s: %s", __func__, nfile->name);
2822		free(nfile->name);
2823		free(nfile);
2824		return (NULL);
2825	} else if (secret &&
2826	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
2827		fclose(nfile->stream);
2828		free(nfile->name);
2829		free(nfile);
2830		return (NULL);
2831	}
2832	nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
2833	nfile->ungetsize = 16;
2834	nfile->ungetbuf = malloc(nfile->ungetsize);
2835	if (nfile->ungetbuf == NULL) {
2836		log_warn("%s", __func__);
2837		fclose(nfile->stream);
2838		free(nfile->name);
2839		free(nfile);
2840		return (NULL);
2841	}
2842	TAILQ_INSERT_TAIL(&files, nfile, entry);
2843	return (nfile);
2844}
2845
2846int
2847popfile(void)
2848{
2849	struct file	*prev;
2850
2851	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
2852		prev->errors += file->errors;
2853
2854	TAILQ_REMOVE(&files, file, entry);
2855	fclose(file->stream);
2856	free(file->name);
2857	free(file->ungetbuf);
2858	free(file);
2859	file = prev;
2860	return (file ? 0 : EOF);
2861}
2862
2863int
2864parse_config(const char *filename, struct relayd *x_conf)
2865{
2866	struct sym	*sym, *next;
2867
2868	conf = x_conf;
2869	if (config_init(conf) == -1) {
2870		log_warn("%s: cannot initialize configuration", __func__);
2871		return (-1);
2872	}
2873
2874	errors = 0;
2875
2876	if ((file = pushfile(filename, 0)) == NULL)
2877		return (-1);
2878
2879	topfile = file;
2880	setservent(1);
2881
2882	yyparse();
2883	errors = file->errors;
2884	while (popfile() != EOF)
2885		;
2886
2887	endservent();
2888	endprotoent();
2889
2890	/* Free macros */
2891	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
2892		if (!sym->persist) {
2893			free(sym->nam);
2894			free(sym->val);
2895			TAILQ_REMOVE(&symhead, sym, entry);
2896			free(sym);
2897		}
2898	}
2899
2900	return (errors ? -1 : 0);
2901}
2902
2903int
2904load_config(const char *filename, struct relayd *x_conf)
2905{
2906	struct sym		*sym, *next;
2907	struct table		*nexttb;
2908	struct host		*h, *ph;
2909	struct relay_table	*rlt;
2910
2911	conf = x_conf;
2912	conf->sc_conf.flags = 0;
2913
2914	loadcfg = 1;
2915	errors = 0;
2916	last_host_id = last_table_id = last_rdr_id = last_proto_id =
2917	    last_relay_id = last_rt_id = last_nr_id = 0;
2918
2919	rdr = NULL;
2920	table = NULL;
2921	rlay = NULL;
2922	proto = NULL;
2923	router = NULL;
2924
2925	if ((file = pushfile(filename, 0)) == NULL)
2926		return (-1);
2927
2928	topfile = file;
2929	setservent(1);
2930
2931	yyparse();
2932	errors = file->errors;
2933	while (popfile() != EOF)
2934		;
2935
2936	endservent();
2937	endprotoent();
2938
2939	/* Free macros and check which have not been used. */
2940	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
2941		next = TAILQ_NEXT(sym, entry);
2942		if ((conf->sc_conf.opts & RELAYD_OPT_VERBOSE) && !sym->used)
2943			fprintf(stderr, "warning: macro '%s' not "
2944			    "used\n", sym->nam);
2945		if (!sym->persist) {
2946			free(sym->nam);
2947			free(sym->val);
2948			TAILQ_REMOVE(&symhead, sym, entry);
2949			free(sym);
2950		}
2951	}
2952
2953	if (TAILQ_EMPTY(conf->sc_rdrs) &&
2954	    TAILQ_EMPTY(conf->sc_relays) &&
2955	    TAILQ_EMPTY(conf->sc_rts)) {
2956		log_warnx("no actions, nothing to do");
2957		errors++;
2958	}
2959
2960	/* Cleanup relay list to inherit */
2961	while ((rlay = TAILQ_FIRST(&relays)) != NULL) {
2962		TAILQ_REMOVE(&relays, rlay, rl_entry);
2963		while ((rlt = TAILQ_FIRST(&rlay->rl_tables))) {
2964			TAILQ_REMOVE(&rlay->rl_tables, rlt, rlt_entry);
2965			free(rlt);
2966		}
2967		free(rlay);
2968	}
2969
2970	if (timercmp(&conf->sc_conf.timeout, &conf->sc_conf.interval, >=)) {
2971		log_warnx("global timeout exceeds interval");
2972		errors++;
2973	}
2974
2975	/* Verify that every table is used */
2976	for (table = TAILQ_FIRST(conf->sc_tables); table != NULL;
2977	     table = nexttb) {
2978		nexttb = TAILQ_NEXT(table, entry);
2979		if (table->conf.port == 0) {
2980			TAILQ_REMOVE(conf->sc_tables, table, entry);
2981			while ((h = TAILQ_FIRST(&table->hosts)) != NULL) {
2982				TAILQ_REMOVE(&table->hosts, h, entry);
2983				free(h);
2984			}
2985			if (table->sendbuf != NULL)
2986				free(table->sendbuf);
2987			if (table->sendbinbuf != NULL)
2988				ibuf_free(table->sendbinbuf);
2989			free(table);
2990			continue;
2991		}
2992
2993		TAILQ_FOREACH(h, &table->hosts, entry) {
2994			if (h->conf.parentid) {
2995				ph = host_find(conf, h->conf.parentid);
2996
2997				/* Validate the parent id */
2998				if (h->conf.id == h->conf.parentid ||
2999				    ph == NULL || ph->conf.parentid)
3000					ph = NULL;
3001
3002				if (ph == NULL) {
3003					log_warnx("host parent id %d invalid",
3004					    h->conf.parentid);
3005					errors++;
3006				} else
3007					SLIST_INSERT_HEAD(&ph->children,
3008					    h, child);
3009			}
3010		}
3011
3012		if (!(table->conf.flags & F_USED)) {
3013			log_warnx("unused table: %s", table->conf.name);
3014			errors++;
3015		}
3016		if (timercmp(&table->conf.timeout,
3017		    &conf->sc_conf.interval, >=)) {
3018			log_warnx("table timeout exceeds interval: %s",
3019			    table->conf.name);
3020			errors++;
3021		}
3022	}
3023
3024	/* Verify that every non-default protocol is used */
3025	TAILQ_FOREACH(proto, conf->sc_protos, entry) {
3026		if (!(proto->flags & F_USED)) {
3027			log_warnx("unused protocol: %s", proto->name);
3028		}
3029	}
3030
3031	return (errors ? -1 : 0);
3032}
3033
3034int
3035symset(const char *nam, const char *val, int persist)
3036{
3037	struct sym	*sym;
3038
3039	TAILQ_FOREACH(sym, &symhead, entry) {
3040		if (strcmp(nam, sym->nam) == 0)
3041			break;
3042	}
3043
3044	if (sym != NULL) {
3045		if (sym->persist == 1)
3046			return (0);
3047		else {
3048			free(sym->nam);
3049			free(sym->val);
3050			TAILQ_REMOVE(&symhead, sym, entry);
3051			free(sym);
3052		}
3053	}
3054	if ((sym = calloc(1, sizeof(*sym))) == NULL)
3055		return (-1);
3056
3057	sym->nam = strdup(nam);
3058	if (sym->nam == NULL) {
3059		free(sym);
3060		return (-1);
3061	}
3062	sym->val = strdup(val);
3063	if (sym->val == NULL) {
3064		free(sym->nam);
3065		free(sym);
3066		return (-1);
3067	}
3068	sym->used = 0;
3069	sym->persist = persist;
3070	TAILQ_INSERT_TAIL(&symhead, sym, entry);
3071	return (0);
3072}
3073
3074int
3075cmdline_symset(char *s)
3076{
3077	char	*sym, *val;
3078	int	ret;
3079
3080	if ((val = strrchr(s, '=')) == NULL)
3081		return (-1);
3082	sym = strndup(s, val - s);
3083	if (sym == NULL)
3084		errx(1, "%s: strndup", __func__);
3085	ret = symset(sym, val + 1, 1);
3086	free(sym);
3087
3088	return (ret);
3089}
3090
3091char *
3092symget(const char *nam)
3093{
3094	struct sym	*sym;
3095
3096	TAILQ_FOREACH(sym, &symhead, entry) {
3097		if (strcmp(nam, sym->nam) == 0) {
3098			sym->used = 1;
3099			return (sym->val);
3100		}
3101	}
3102	return (NULL);
3103}
3104
3105struct address *
3106host_ip(const char *s)
3107{
3108	struct addrinfo	 hints, *res;
3109	struct address	*h = NULL;
3110
3111	memset(&hints, 0, sizeof(hints));
3112	hints.ai_family = AF_UNSPEC;
3113	hints.ai_socktype = SOCK_DGRAM; /*dummy*/
3114	hints.ai_flags = AI_NUMERICHOST;
3115	if (getaddrinfo(s, "0", &hints, &res) == 0) {
3116		if (res->ai_family == AF_INET ||
3117		    res->ai_family == AF_INET6) {
3118			if ((h = calloc(1, sizeof(*h))) == NULL)
3119				fatal(NULL);
3120			memcpy(&h->ss, res->ai_addr, res->ai_addrlen);
3121		}
3122		freeaddrinfo(res);
3123	}
3124
3125	return (h);
3126}
3127
3128int
3129host_dns(const char *s, struct addresslist *al, int max,
3130    struct portrange *port, const char *ifname, int ipproto)
3131{
3132	struct addrinfo		 hints, *res0, *res;
3133	int			 error, cnt = 0;
3134	struct address		*h;
3135
3136	if ((cnt = host_if(s, al, max, port, ifname, ipproto)) != 0)
3137		return (cnt);
3138
3139	bzero(&hints, sizeof(hints));
3140	hints.ai_family = AF_UNSPEC;
3141	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
3142	hints.ai_flags = AI_ADDRCONFIG;
3143	error = getaddrinfo(s, NULL, &hints, &res0);
3144	if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
3145		return (0);
3146	if (error) {
3147		log_warnx("%s: could not parse \"%s\": %s", __func__, s,
3148		    gai_strerror(error));
3149		return (-1);
3150	}
3151
3152	for (res = res0; res && cnt < max; res = res->ai_next) {
3153		if (res->ai_family != AF_INET &&
3154		    res->ai_family != AF_INET6)
3155			continue;
3156		if ((h = calloc(1, sizeof(*h))) == NULL)
3157			fatal(__func__);
3158
3159		if (port != NULL)
3160			bcopy(port, &h->port, sizeof(h->port));
3161		if (ifname != NULL) {
3162			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
3163			    sizeof(h->ifname))
3164				log_warnx("%s: interface name truncated",
3165				    __func__);
3166			freeaddrinfo(res0);
3167			free(h);
3168			return (-1);
3169		}
3170		if (ipproto != -1)
3171			h->ipproto = ipproto;
3172
3173		memcpy(&h->ss, res->ai_addr, res->ai_addrlen);
3174
3175		TAILQ_INSERT_HEAD(al, h, entry);
3176		cnt++;
3177	}
3178	if (cnt == max && res) {
3179		log_warnx("%s: %s resolves to more than %d hosts", __func__,
3180		    s, max);
3181	}
3182	freeaddrinfo(res0);
3183	return (cnt);
3184}
3185
3186int
3187host_if(const char *s, struct addresslist *al, int max,
3188    struct portrange *port, const char *ifname, int ipproto)
3189{
3190	struct ifaddrs		*ifap, *p;
3191	struct sockaddr_in	*sain;
3192	struct sockaddr_in6	*sin6;
3193	struct address		*h;
3194	int			 cnt = 0, af;
3195
3196	if (getifaddrs(&ifap) == -1)
3197		fatal("getifaddrs");
3198
3199	/* First search for IPv4 addresses */
3200	af = AF_INET;
3201
3202 nextaf:
3203	for (p = ifap; p != NULL && cnt < max; p = p->ifa_next) {
3204		if (p->ifa_addr == NULL ||
3205		    p->ifa_addr->sa_family != af ||
3206		    (strcmp(s, p->ifa_name) != 0 &&
3207		    !is_if_in_group(p->ifa_name, s)))
3208			continue;
3209		if ((h = calloc(1, sizeof(*h))) == NULL)
3210			fatal("calloc");
3211
3212		if (port != NULL)
3213			bcopy(port, &h->port, sizeof(h->port));
3214		if (ifname != NULL) {
3215			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
3216			    sizeof(h->ifname))
3217				log_warnx("%s: interface name truncated",
3218				    __func__);
3219			freeifaddrs(ifap);
3220			return (-1);
3221		}
3222		if (ipproto != -1)
3223			h->ipproto = ipproto;
3224		h->ss.ss_family = af;
3225
3226		if (af == AF_INET) {
3227			sain = (struct sockaddr_in *)&h->ss;
3228			sain->sin_len = sizeof(struct sockaddr_in);
3229			sain->sin_addr.s_addr = ((struct sockaddr_in *)
3230			    p->ifa_addr)->sin_addr.s_addr;
3231		} else {
3232			sin6 = (struct sockaddr_in6 *)&h->ss;
3233			sin6->sin6_len = sizeof(struct sockaddr_in6);
3234			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
3235			    p->ifa_addr)->sin6_addr, sizeof(struct in6_addr));
3236			sin6->sin6_scope_id = ((struct sockaddr_in6 *)
3237			    p->ifa_addr)->sin6_scope_id;
3238		}
3239
3240		TAILQ_INSERT_HEAD(al, h, entry);
3241		cnt++;
3242	}
3243	if (af == AF_INET) {
3244		/* Next search for IPv6 addresses */
3245		af = AF_INET6;
3246		goto nextaf;
3247	}
3248
3249	if (cnt > max) {
3250		log_warnx("%s: %s resolves to more than %d hosts", __func__,
3251		    s, max);
3252	}
3253	freeifaddrs(ifap);
3254	return (cnt);
3255}
3256
3257int
3258host(const char *s, struct addresslist *al, int max,
3259    struct portrange *port, const char *ifname, int ipproto)
3260{
3261	struct address	*h;
3262
3263	if ((h = host_ip(s)) == NULL)
3264		return (host_dns(s, al, max, port, ifname, ipproto));
3265
3266	if (port != NULL)
3267		bcopy(port, &h->port, sizeof(h->port));
3268	if (ifname != NULL) {
3269		if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
3270		    sizeof(h->ifname)) {
3271			log_warnx("%s: interface name truncated",
3272			    __func__);
3273			free(h);
3274			return (-1);
3275		}
3276	}
3277	if (ipproto != -1)
3278		h->ipproto = ipproto;
3279
3280	TAILQ_INSERT_HEAD(al, h, entry);
3281	return (1);
3282}
3283
3284void
3285host_free(struct addresslist *al)
3286{
3287	struct address	 *h;
3288
3289	while ((h = TAILQ_FIRST(al)) != NULL) {
3290		TAILQ_REMOVE(al, h, entry);
3291		free(h);
3292	}
3293}
3294
3295struct table *
3296table_inherit(struct table *tb)
3297{
3298	char		pname[TABLE_NAME_SIZE + 6];
3299	struct host	*h, *dsth;
3300	struct table	*dsttb, *oldtb;
3301
3302	/* Get the table or table template */
3303	if ((dsttb = table_findbyname(conf, tb->conf.name)) == NULL) {
3304		yyerror("unknown table %s", tb->conf.name);
3305		goto fail;
3306	}
3307	if (dsttb->conf.port != 0)
3308		fatal("invalid table");	/* should not happen */
3309
3310	if (tb->conf.port == 0) {
3311		yyerror("invalid port");
3312		goto fail;
3313	}
3314
3315	/* Check if a matching table already exists */
3316	if (snprintf(pname, sizeof(pname), "%s:%u",
3317	    tb->conf.name, ntohs(tb->conf.port)) >= (int)sizeof(pname)) {
3318		yyerror("invalid table name");
3319		goto fail;
3320	}
3321	if (strlcpy(tb->conf.name, pname, sizeof(tb->conf.name)) >=
3322	    sizeof(tb->conf.name)) {
3323		yyerror("invalid table mame");
3324		goto fail;
3325	}
3326	if ((oldtb = table_findbyconf(conf, tb)) != NULL) {
3327		purge_table(conf, NULL, tb);
3328		return (oldtb);
3329	}
3330
3331	/* Create a new table */
3332	tb->conf.id = ++last_table_id;
3333	if (last_table_id == INT_MAX) {
3334		yyerror("too many tables defined");
3335		goto fail;
3336	}
3337	tb->conf.flags |= dsttb->conf.flags;
3338
3339	/* Inherit global table options */
3340	if (tb->conf.timeout.tv_sec == 0 && tb->conf.timeout.tv_usec == 0)
3341		bcopy(&dsttb->conf.timeout, &tb->conf.timeout,
3342		    sizeof(struct timeval));
3343
3344	/* Copy the associated hosts */
3345	TAILQ_INIT(&tb->hosts);
3346	TAILQ_FOREACH(dsth, &dsttb->hosts, entry) {
3347		if ((h = (struct host *)
3348		    calloc(1, sizeof (*h))) == NULL)
3349			fatal("out of memory");
3350		bcopy(dsth, h, sizeof(*h));
3351		h->conf.id = ++last_host_id;
3352		if (last_host_id == INT_MAX) {
3353			yyerror("too many hosts defined");
3354			free(h);
3355			goto fail;
3356		}
3357		h->conf.tableid = tb->conf.id;
3358		h->tablename = tb->conf.name;
3359		SLIST_INIT(&h->children);
3360		TAILQ_INSERT_TAIL(&tb->hosts, h, entry);
3361		TAILQ_INSERT_TAIL(&conf->sc_hosts, h, globalentry);
3362	}
3363
3364	conf->sc_tablecount++;
3365	TAILQ_INSERT_TAIL(conf->sc_tables, tb, entry);
3366
3367	return (tb);
3368
3369 fail:
3370	purge_table(conf, NULL, tb);
3371	return (NULL);
3372}
3373
3374int
3375relay_id(struct relay *rl)
3376{
3377	rl->rl_conf.id = ++last_relay_id;
3378
3379	if (last_relay_id == INT_MAX)
3380		return (-1);
3381
3382	return (0);
3383}
3384
3385struct relay *
3386relay_inherit(struct relay *ra, struct relay *rb)
3387{
3388	struct relay_config	 rc;
3389	struct relay_table	*rta, *rtb;
3390
3391	bcopy(&rb->rl_conf, &rc, sizeof(rc));
3392	bcopy(ra, rb, sizeof(*rb));
3393
3394	bcopy(&rc.ss, &rb->rl_conf.ss, sizeof(rb->rl_conf.ss));
3395	rb->rl_conf.port = rc.port;
3396	rb->rl_conf.flags =
3397	    (ra->rl_conf.flags & ~F_TLS) | (rc.flags & F_TLS);
3398	if (!(rb->rl_conf.flags & F_TLS)) {
3399		rb->rl_tls_cacert_fd = -1;
3400		rb->rl_tls_ca_fd = -1;
3401	}
3402	TAILQ_INIT(&rb->rl_tables);
3403
3404	if (relay_id(rb) == -1) {
3405		yyerror("too many relays defined");
3406		goto err;
3407	}
3408
3409	if (snprintf(rb->rl_conf.name, sizeof(rb->rl_conf.name), "%s%u:%u",
3410	    ra->rl_conf.name, rb->rl_conf.id, ntohs(rc.port)) >=
3411	    (int)sizeof(rb->rl_conf.name)) {
3412		yyerror("invalid relay name");
3413		goto err;
3414	}
3415
3416	if (relay_findbyname(conf, rb->rl_conf.name) != NULL ||
3417	    relay_findbyaddr(conf, &rb->rl_conf) != NULL) {
3418		yyerror("relay %s or listener defined twice",
3419		    rb->rl_conf.name);
3420		goto err;
3421	}
3422
3423	if (relay_load_certfiles(conf, rb, NULL) == -1) {
3424		yyerror("cannot load certificates for relay %s",
3425		    rb->rl_conf.name);
3426		goto err;
3427	}
3428
3429	TAILQ_FOREACH(rta, &ra->rl_tables, rlt_entry) {
3430		if ((rtb = calloc(1, sizeof(*rtb))) == NULL) {
3431			yyerror("cannot allocate relay table");
3432			goto err;
3433		}
3434		rtb->rlt_table = rta->rlt_table;
3435		rtb->rlt_mode = rta->rlt_mode;
3436		rtb->rlt_flags = rta->rlt_flags;
3437
3438		TAILQ_INSERT_TAIL(&rb->rl_tables, rtb, rlt_entry);
3439	}
3440
3441	conf->sc_relaycount++;
3442	SPLAY_INIT(&rlay->rl_sessions);
3443	TAILQ_INSERT_TAIL(conf->sc_relays, rb, rl_entry);
3444
3445	return (rb);
3446
3447 err:
3448	while ((rtb = TAILQ_FIRST(&rb->rl_tables))) {
3449		TAILQ_REMOVE(&rb->rl_tables, rtb, rlt_entry);
3450		free(rtb);
3451	}
3452	free(rb);
3453	return (NULL);
3454}
3455
3456int
3457getservice(char *n)
3458{
3459	struct servent	*s;
3460	const char	*errstr;
3461	long long	 llval;
3462
3463	llval = strtonum(n, 0, UINT16_MAX, &errstr);
3464	if (errstr) {
3465		s = getservbyname(n, "tcp");
3466		if (s == NULL)
3467			s = getservbyname(n, "udp");
3468		if (s == NULL) {
3469			yyerror("unknown port %s", n);
3470			return (-1);
3471		}
3472		return (s->s_port);
3473	}
3474
3475	return (htons((u_short)llval));
3476}
3477
3478int
3479is_if_in_group(const char *ifname, const char *groupname)
3480{
3481	unsigned int		 len;
3482	struct ifgroupreq	 ifgr;
3483	struct ifg_req		*ifg;
3484	int			 s;
3485	int			 ret = 0;
3486
3487	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
3488		err(1, "socket");
3489
3490	memset(&ifgr, 0, sizeof(ifgr));
3491	if (strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ) >= IFNAMSIZ)
3492		err(1, "IFNAMSIZ");
3493	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
3494		if (errno == EINVAL || errno == ENOTTY)
3495			goto end;
3496		err(1, "SIOCGIFGROUP");
3497	}
3498
3499	len = ifgr.ifgr_len;
3500	ifgr.ifgr_groups = calloc(len / sizeof(struct ifg_req),
3501	    sizeof(struct ifg_req));
3502	if (ifgr.ifgr_groups == NULL)
3503		err(1, "getifgroups");
3504	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
3505		err(1, "SIOCGIFGROUP");
3506
3507	ifg = ifgr.ifgr_groups;
3508	for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
3509		len -= sizeof(struct ifg_req);
3510		if (strcmp(ifg->ifgrq_group, groupname) == 0) {
3511			ret = 1;
3512			break;
3513		}
3514	}
3515	free(ifgr.ifgr_groups);
3516
3517end:
3518	close(s);
3519	return (ret);
3520}
3521