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