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