parse.y revision 1.142
1/*	$OpenBSD: parse.y,v 1.142 2009/08/27 09:26:53 reyk Exp $	*/
2
3/*
4 * Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
5 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
6 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
7 * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
8 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
9 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
10 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
11 * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
12 *
13 * Permission to use, copy, modify, and distribute this software for any
14 * purpose with or without fee is hereby granted, provided that the above
15 * copyright notice and this permission notice appear in all copies.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
18 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
20 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
23 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 */
25
26%{
27#include <sys/types.h>
28#include <sys/socket.h>
29#include <sys/stat.h>
30#include <sys/queue.h>
31
32#include <net/if.h>
33#include <net/pfvar.h>
34#include <netinet/in.h>
35#include <arpa/inet.h>
36#include <arpa/nameser.h>
37
38#include <ctype.h>
39#include <unistd.h>
40#include <err.h>
41#include <errno.h>
42#include <event.h>
43#include <limits.h>
44#include <stdint.h>
45#include <stdarg.h>
46#include <stdio.h>
47#include <netdb.h>
48#include <string.h>
49#include <ifaddrs.h>
50
51#include <openssl/ssl.h>
52
53#include "relayd.h"
54
55TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
56static struct file {
57	TAILQ_ENTRY(file)	 entry;
58	FILE			*stream;
59	char			*name;
60	int			 lineno;
61	int			 errors;
62} *file, *topfile;
63struct file	*pushfile(const char *, int);
64int		 popfile(void);
65int		 check_file_secrecy(int, const char *);
66int		 yyparse(void);
67int		 yylex(void);
68int		 yyerror(const char *, ...);
69int		 kw_cmp(const void *, const void *);
70int		 lookup(char *);
71int		 lgetc(int);
72int		 lungetc(int);
73int		 findeol(void);
74
75TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
76struct sym {
77	TAILQ_ENTRY(sym)	 entry;
78	int			 used;
79	int			 persist;
80	char			*nam;
81	char			*val;
82};
83int		 symset(const char *, const char *, int);
84char		*symget(const char *);
85
86struct relayd		*conf = NULL;
87static int		 errors = 0;
88objid_t			 last_rdr_id = 0;
89objid_t			 last_table_id = 0;
90objid_t			 last_host_id = 0;
91objid_t			 last_relay_id = 0;
92objid_t			 last_proto_id = 0;
93objid_t			 last_rt_id = 0;
94objid_t			 last_nr_id = 0;
95
96static struct rdr	*rdr = NULL;
97static struct table	*table = NULL;
98static struct relay	*rlay = NULL;
99static struct host	*hst = NULL;
100struct relaylist	 relays;
101static struct protocol	*proto = NULL;
102static struct protonode	 node;
103static struct router	*router = NULL;
104static u_int16_t	 label = 0;
105static in_port_t	 tableport = 0;
106static int		 nodedirection;
107
108struct address	*host_v4(const char *);
109struct address	*host_v6(const char *);
110int		 host_dns(const char *, struct addresslist *,
111		    int, struct portrange *, const char *, int);
112int		 host_if(const char *, struct addresslist *,
113		    int, struct portrange *, const char *, int);
114int		 host(const char *, struct addresslist *,
115		    int, struct portrange *, const char *, int);
116
117struct table	*table_inherit(struct table *);
118struct relay	*relay_inherit(struct relay *, struct relay *);
119int		 getservice(char *);
120
121typedef struct {
122	union {
123		int64_t			 number;
124		char			*string;
125		struct host		*host;
126		struct timeval		 tv;
127		struct table		*table;
128		struct portrange	 port;
129		struct {
130			struct sockaddr_storage	 ss;
131			char			 name[MAXHOSTNAMELEN];
132		}			 addr;
133		struct {
134			enum digest_type type;
135			char		*digest;
136		}			 digest;
137	} v;
138	int lineno;
139} YYSTYPE;
140
141%}
142
143%token	ALL APPEND BACKLOG BACKUP BUFFER CA CACHE CHANGE CHECK
144%token	CIPHERS CODE COOKIE DEMOTE DIGEST DISABLE ERROR EXPECT
145%token	EXTERNAL FILENAME FILTER FORWARD FROM HASH HEADER HOST ICMP
146%token	INCLUDE INET INET6 INTERFACE INTERVAL IP LABEL LISTEN
147%token	LOADBALANCE LOG LOOKUP MARK MARKED MODE NAT NO
148%token	NODELAY NOTHING ON PARENT PATH PORT PREFORK PROTO
149%token	QUERYSTR REAL REDIRECT RELAY REMOVE REQUEST RESPONSE RETRY
150%token	RETURN ROUNDROBIN ROUTE SACK SCRIPT SEND SESSION SOCKET
151%token	SSL STICKYADDR STYLE TABLE TAG TCP TIMEOUT TO ROUTER RTLABEL
152%token	TRANSPARENT TRAP UPDATES URL VIRTUAL WITH TTL RTABLE
153%token	<v.string>	STRING
154%token  <v.number>	NUMBER
155%type	<v.string>	hostname interface table
156%type	<v.number>	http_type loglevel mark
157%type	<v.number>	direction dstmode flag forwardmode retry
158%type	<v.number>	optssl optsslclient sslcache
159%type	<v.number>	redirect_proto relay_proto
160%type	<v.port>	port
161%type	<v.host>	host
162%type	<v.addr>	address
163%type	<v.tv>		timeout
164%type	<v.digest>	digest
165%type	<v.table>	tablespec
166
167%%
168
169grammar		: /* empty */
170		| grammar include '\n'
171		| grammar '\n'
172		| grammar varset '\n'
173		| grammar main '\n'
174		| grammar rdr '\n'
175		| grammar tabledef '\n'
176		| grammar relay '\n'
177		| grammar proto '\n'
178		| grammar router '\n'
179		| grammar error '\n'		{ file->errors++; }
180		;
181
182include		: INCLUDE STRING		{
183			struct file	*nfile;
184
185			if ((nfile = pushfile($2, 0)) == NULL) {
186				yyerror("failed to include file %s", $2);
187				free($2);
188				YYERROR;
189			}
190			free($2);
191
192			file = nfile;
193			lungetc('\n');
194		}
195
196optssl		: /*empty*/	{ $$ = 0; }
197		| SSL		{ $$ = 1; }
198		;
199
200optsslclient	: /*empty*/	{ $$ = 0; }
201		| WITH SSL	{ $$ = 1; }
202		;
203
204http_type	: STRING	{
205			if (strcmp("https", $1) == 0) {
206				$$ = 1;
207			} else if (strcmp("http", $1) == 0) {
208				$$ = 0;
209			} else {
210				yyerror("invalid check type: %s", $1);
211				free($1);
212				YYERROR;
213			}
214			free($1);
215		}
216		;
217
218hostname	: /* empty */		{
219			$$ = strdup("");
220			if ($$ == NULL)
221				fatal("calloc");
222		}
223		| HOST STRING	{
224			if (asprintf(&$$, "Host: %s\r\nConnection: close\r\n",
225			    $2) == -1)
226				fatal("asprintf");
227		}
228		;
229
230relay_proto	: /* empty */			{ $$ = RELAY_PROTO_TCP; }
231		| TCP				{ $$ = RELAY_PROTO_TCP; }
232		| STRING			{
233			if (strcmp("http", $1) == 0) {
234				$$ = RELAY_PROTO_HTTP;
235			} else if (strcmp("dns", $1) == 0) {
236				$$ = RELAY_PROTO_DNS;
237			} else {
238				yyerror("invalid protocol type: %s", $1);
239				free($1);
240				YYERROR;
241			}
242			free($1);
243		}
244		;
245
246redirect_proto	: /* empty */			{ $$ = IPPROTO_TCP; }
247		| TCP				{ $$ = IPPROTO_TCP; }
248		| STRING			{
249			struct protoent	*p;
250
251			if ((p = getprotobyname($1)) == NULL) {
252				yyerror("invalid protocol: %s", $1);
253				free($1);
254				YYERROR;
255			}
256			free($1);
257
258			$$ = p->p_proto;
259		}
260		;
261
262eflags_l	: eflags comma eflags_l
263		| eflags
264		;
265
266opteflags	: /* nothing */
267		| eflags
268		;
269
270eflags		: STYLE STRING
271		{
272			if ((proto->style = strdup($2)) == NULL)
273				fatal("out of memory");
274			free($2);
275		}
276		;
277
278port		: PORT STRING {
279			char		*a, *b;
280			int		 p[2];
281
282			p[0] = p[1] = 0;
283
284			a = $2;
285			b = strchr($2, ':');
286			if (b == NULL)
287				$$.op = PF_OP_EQ;
288			else {
289				*b++ = '\0';
290				if ((p[1] = getservice(b)) == -1) {
291					free($2);
292					YYERROR;
293				}
294				$$.op = PF_OP_RRG;
295			}
296			if ((p[0] = getservice(a)) == -1) {
297				free($2);
298				YYERROR;
299			}
300			$$.val[0] = p[0];
301			$$.val[1] = p[1];
302			free($2);
303		}
304		| PORT NUMBER {
305			if ($2 <= 0 || $2 >= (int)USHRT_MAX) {
306				yyerror("invalid port: %d", $2);
307				YYERROR;
308			}
309			$$.val[0] = htons($2);
310			$$.op = PF_OP_EQ;
311		}
312		;
313
314varset		: STRING '=' STRING	{
315			if (symset($1, $3, 0) == -1)
316				fatal("cannot store variable");
317			free($1);
318			free($3);
319		}
320		;
321
322sendbuf		: NOTHING		{
323			table->sendbuf = NULL;
324			table->sendbuf_len = 0;
325		}
326		| STRING		{
327			table->sendbuf = strdup($1);
328			if (table->sendbuf == NULL)
329				fatal("out of memory");
330			table->sendbuf_len = strlen(table->sendbuf);
331			free($1);
332		}
333		;
334
335main		: INTERVAL NUMBER	{
336			if ((conf->sc_interval.tv_sec = $2) < 0) {
337				yyerror("invalid interval: %d", $2);
338				YYERROR;
339			}
340		}
341		| LOG loglevel		{ conf->sc_opts |= $2; }
342		| TIMEOUT timeout	{
343			bcopy(&$2, &conf->sc_timeout, sizeof(struct timeval));
344		}
345		| PREFORK NUMBER	{
346			if ($2 <= 0 || $2 > RELAY_MAXPROC) {
347				yyerror("invalid number of preforked "
348				    "relays: %d", $2);
349				YYERROR;
350			}
351			conf->sc_prefork_relay = $2;
352		}
353		| DEMOTE STRING		{
354			conf->sc_flags |= F_DEMOTE;
355			if (strlcpy(conf->sc_demote_group, $2,
356			    sizeof(conf->sc_demote_group))
357			    >= sizeof(conf->sc_demote_group)) {
358				yyerror("yyparse: demote group name too long");
359				free($2);
360				YYERROR;
361			}
362			free($2);
363			if (carp_demote_init(conf->sc_demote_group, 1) == -1) {
364				yyerror("yyparse: error initializing group %s",
365				    conf->sc_demote_group);
366				YYERROR;
367			}
368		}
369		| SEND TRAP		{ conf->sc_flags |= F_TRAP; }
370		;
371
372loglevel	: UPDATES		{ $$ = RELAYD_OPT_LOGUPDATE; }
373		| ALL			{ $$ = RELAYD_OPT_LOGALL; }
374		;
375
376rdr		: REDIRECT STRING	{
377			struct rdr *srv;
378
379			conf->sc_flags |= F_NEEDPF;
380			TAILQ_FOREACH(srv, conf->sc_rdrs, entry)
381				if (!strcmp(srv->conf.name, $2))
382					break;
383			if (srv != NULL) {
384				yyerror("redirection %s defined twice", $2);
385				free($2);
386				YYERROR;
387			}
388			if ((srv = calloc(1, sizeof (*srv))) == NULL)
389				fatal("out of memory");
390
391			if (strlcpy(srv->conf.name, $2,
392			    sizeof(srv->conf.name)) >=
393			    sizeof(srv->conf.name)) {
394				yyerror("redirection name truncated");
395				free(srv);
396				YYERROR;
397			}
398			free($2);
399			srv->conf.id = ++last_rdr_id;
400			srv->conf.timeout.tv_sec = RELAY_TIMEOUT;
401			if (last_rdr_id == INT_MAX) {
402				yyerror("too many redirections defined");
403				free(srv);
404				YYERROR;
405			}
406			rdr = srv;
407		} '{' optnl rdropts_l '}'	{
408			if (rdr->table == NULL) {
409				yyerror("redirection %s has no table",
410				    rdr->conf.name);
411				YYERROR;
412			}
413			if (TAILQ_EMPTY(&rdr->virts)) {
414				yyerror("redirection %s has no virtual ip",
415				    rdr->conf.name);
416				YYERROR;
417			}
418			conf->sc_rdrcount++;
419			if (rdr->backup == NULL) {
420				rdr->conf.backup_id =
421				    conf->sc_empty_table.conf.id;
422				rdr->backup = &conf->sc_empty_table;
423			} else if (rdr->backup->conf.port !=
424			    rdr->table->conf.port) {
425				yyerror("redirection %s uses two different "
426				    "ports for its table and backup table",
427				    rdr->conf.name);
428				YYERROR;
429			}
430			if (!(rdr->conf.flags & F_DISABLE))
431				rdr->conf.flags |= F_ADD;
432			TAILQ_INSERT_TAIL(conf->sc_rdrs, rdr, entry);
433			tableport = 0;
434			rdr = NULL;
435		}
436		;
437
438rdropts_l	: rdropts_l rdroptsl nl
439		| rdroptsl optnl
440		;
441
442rdroptsl	: forwardmode TO tablespec interface	{
443			switch ($1) {
444			case FWD_NORMAL:
445				if ($4 == NULL)
446					break;
447				yyerror("superfluous interface");
448				YYERROR;
449			case FWD_ROUTE:
450				if ($4 != NULL)
451					break;
452				yyerror("missing interface to route to");
453				YYERROR;
454			case FWD_TRANS:
455				yyerror("no transparent forward here");
456				YYERROR;
457			}
458			if ($4 != NULL) {
459				strlcpy($3->conf.ifname, $4,
460				    sizeof($3->conf.ifname));
461				free($4);
462			}
463
464			if ($3->conf.check == CHECK_NOCHECK) {
465				yyerror("table %s has no check", $3->conf.name);
466				purge_table(conf->sc_tables, $3);
467				YYERROR;
468			}
469			if (rdr->backup) {
470				yyerror("only one backup table is allowed");
471				purge_table(conf->sc_tables, $3);
472				YYERROR;
473			}
474			if (rdr->table) {
475				rdr->backup = $3;
476				rdr->conf.backup_id = $3->conf.id;
477			} else {
478				rdr->table = $3;
479				rdr->conf.table_id = $3->conf.id;
480			}
481			$3->conf.fwdmode = $1;
482			$3->conf.rdrid = rdr->conf.id;
483			$3->conf.flags |= F_USED;
484		}
485		| LISTEN ON STRING redirect_proto port interface {
486			if (host($3, &rdr->virts,
487			    SRV_MAX_VIRTS, &$5, $6, $4) <= 0) {
488				yyerror("invalid virtual ip: %s", $3);
489				free($3);
490				free($6);
491				YYERROR;
492			}
493			free($3);
494			free($6);
495			if (rdr->conf.port == 0)
496				rdr->conf.port = $5.val[0];
497			tableport = rdr->conf.port;
498		}
499		| DISABLE		{ rdr->conf.flags |= F_DISABLE; }
500		| STICKYADDR		{ rdr->conf.flags |= F_STICKY; }
501		| TAG STRING {
502			conf->sc_flags |= F_NEEDPF;
503			if (strlcpy(rdr->conf.tag, $2,
504			    sizeof(rdr->conf.tag)) >=
505			    sizeof(rdr->conf.tag)) {
506				yyerror("redirection tag name truncated");
507				free($2);
508				YYERROR;
509			}
510			free($2);
511		}
512		| SESSION TIMEOUT NUMBER		{
513			if ((rdr->conf.timeout.tv_sec = $3) < 0) {
514				yyerror("invalid timeout: %d", $3);
515				YYERROR;
516			}
517		}
518		| include
519		;
520
521forwardmode	: FORWARD		{ $$ = FWD_NORMAL; }
522		| ROUTE			{ $$ = FWD_ROUTE; }
523		| TRANSPARENT FORWARD	{ $$ = FWD_TRANS; }
524		;
525
526table		: '<' STRING '>'	{
527			if (strlen($2) >= TABLE_NAME_SIZE) {
528				yyerror("invalid table name");
529				free($2);
530				YYERROR;
531			}
532			$$ = $2;
533		}
534		;
535
536tabledef	: TABLE table		{
537			struct table *tb;
538
539			TAILQ_FOREACH(tb, conf->sc_tables, entry)
540				if (!strcmp(tb->conf.name, $2))
541					break;
542			if (tb != NULL) {
543				yyerror("table %s defined twice", $2);
544				free($2);
545				YYERROR;
546			}
547
548			if ((tb = calloc(1, sizeof (*tb))) == NULL)
549				fatal("out of memory");
550
551			(void)strlcpy(tb->conf.name, $2, sizeof(tb->conf.name));
552			free($2);
553
554			tb->conf.id = 0; /* will be set later */
555			bcopy(&conf->sc_timeout, &tb->conf.timeout,
556			    sizeof(struct timeval));
557			TAILQ_INIT(&tb->hosts);
558			table = tb;
559		} tabledefopts_l 	{
560			if (TAILQ_EMPTY(&table->hosts)) {
561				yyerror("table %s has no hosts",
562				    table->conf.name);
563				YYERROR;
564			}
565			conf->sc_tablecount++;
566			TAILQ_INSERT_TAIL(conf->sc_tables, table, entry);
567		}
568		;
569
570tabledefopts_l	: tabledefopts_l tabledefopts
571		| tabledefopts
572		;
573
574tabledefopts	: DISABLE		{ table->conf.flags |= F_DISABLE; }
575		| '{' optnl tablelist_l '}'
576		;
577
578tablelist_l	: tablelist comma tablelist_l
579		| tablelist optnl
580		;
581
582tablelist	: host			{
583			$1->conf.tableid = table->conf.id;
584			$1->tablename = table->conf.name;
585			TAILQ_INSERT_TAIL(&table->hosts, $1, entry);
586		}
587		| include
588		;
589
590tablespec	: table 		{
591			struct table	*tb;
592			if ((tb = calloc(1, sizeof (*tb))) == NULL)
593				fatal("out of memory");
594			(void)strlcpy(tb->conf.name, $1, sizeof(tb->conf.name));
595			free($1);
596			table = tb;
597		} tableopts_l		{
598			struct table	*tb;
599			if (table->conf.port == 0)
600				table->conf.port = tableport;
601			else
602				table->conf.flags |= F_PORT;
603			if ((tb = table_inherit(table)) == NULL)
604				YYERROR;
605			$$ = tb;
606		}
607		;
608
609tableopts_l	: tableopts tableopts_l
610		| tableopts
611		;
612
613tableopts	: CHECK tablecheck
614		| port			{
615			if ($1.op != PF_OP_EQ) {
616				yyerror("invalid port");
617				YYERROR;
618			}
619			table->conf.port = $1.val[0];
620		}
621		| TIMEOUT timeout	{
622			bcopy(&$2, &table->conf.timeout,
623			    sizeof(struct timeval));
624		}
625		| DEMOTE STRING		{
626			table->conf.flags |= F_DEMOTE;
627			if (strlcpy(table->conf.demote_group, $2,
628			    sizeof(table->conf.demote_group))
629			    >= sizeof(table->conf.demote_group)) {
630				yyerror("yyparse: demote group name too long");
631				free($2);
632				YYERROR;
633			}
634			free($2);
635			if (carp_demote_init(table->conf.demote_group, 1)
636			    == -1) {
637				yyerror("yyparse: error initializing group "
638				    "'%s'", table->conf.demote_group);
639				YYERROR;
640			}
641		}
642		| INTERVAL NUMBER	{
643			if ($2 < conf->sc_interval.tv_sec ||
644			    $2 % conf->sc_interval.tv_sec) {
645				yyerror("table interval must be "
646				    "divisible by global interval");
647				YYERROR;
648			}
649			table->conf.skip_cnt = ($2 / conf->sc_interval.tv_sec) - 1;
650		}
651		| MODE dstmode		{
652			switch ($2) {
653			case RELAY_DSTMODE_LOADBALANCE:
654			case RELAY_DSTMODE_HASH:
655				if (rdr != NULL) {
656					yyerror("mode not supported "
657					    "for redirections");
658					YYERROR;
659				}
660				/* FALLTHROUGH */
661			case RELAY_DSTMODE_ROUNDROBIN:
662				if (rlay != NULL)
663					rlay->rl_conf.dstmode = $2;
664				break;
665			}
666		}
667		;
668
669tablecheck	: ICMP			{ table->conf.check = CHECK_ICMP; }
670		| TCP			{ table->conf.check = CHECK_TCP; }
671		| SSL			{
672			table->conf.check = CHECK_TCP;
673			conf->sc_flags |= F_SSL;
674			table->conf.flags |= F_SSL;
675		}
676		| http_type STRING hostname CODE NUMBER {
677			if ($1) {
678				conf->sc_flags |= F_SSL;
679				table->conf.flags |= F_SSL;
680			}
681			table->conf.check = CHECK_HTTP_CODE;
682			if ((table->conf.retcode = $5) <= 0) {
683				yyerror("invalid HTTP code: %d", $5);
684				free($2);
685				free($3);
686				YYERROR;
687			}
688			if (asprintf(&table->sendbuf,
689			    "HEAD %s HTTP/1.%c\r\n%s\r\n",
690			    $2, strlen($3) ? '1' : '0', $3) == -1)
691				fatal("asprintf");
692			free($2);
693			free($3);
694			if (table->sendbuf == NULL)
695				fatal("out of memory");
696			table->sendbuf_len = strlen(table->sendbuf);
697		}
698		| http_type STRING hostname digest {
699			if ($1) {
700				conf->sc_flags |= F_SSL;
701				table->conf.flags |= F_SSL;
702			}
703			table->conf.check = CHECK_HTTP_DIGEST;
704			if (asprintf(&table->sendbuf,
705			    "GET %s HTTP/1.%c\r\n%s\r\n",
706			    $2, strlen($3) ? '1' : '0', $3) == -1)
707				fatal("asprintf");
708			free($2);
709			free($3);
710			if (table->sendbuf == NULL)
711				fatal("out of memory");
712			table->sendbuf_len = strlen(table->sendbuf);
713			(void)strlcpy(table->conf.digest, $4.digest,
714			    sizeof(table->conf.digest));
715			table->conf.digest_type = $4.type;
716			free($4.digest);
717		}
718		| SEND sendbuf EXPECT STRING optssl {
719			table->conf.check = CHECK_SEND_EXPECT;
720			if ($5) {
721				conf->sc_flags |= F_SSL;
722				table->conf.flags |= F_SSL;
723			}
724			if (strlcpy(table->conf.exbuf, $4,
725			    sizeof(table->conf.exbuf))
726			    >= sizeof(table->conf.exbuf)) {
727				yyerror("yyparse: expect buffer truncated");
728				free($4);
729				YYERROR;
730			}
731			translate_string(table->conf.exbuf);
732			free($4);
733		}
734		| SCRIPT STRING {
735			table->conf.check = CHECK_SCRIPT;
736			if (strlcpy(table->conf.path, $2,
737			    sizeof(table->conf.path)) >=
738			    sizeof(table->conf.path)) {
739				yyerror("script path truncated");
740				free($2);
741				YYERROR;
742			}
743			free($2);
744		}
745		;
746
747digest		: DIGEST STRING
748		{
749			switch (strlen($2)) {
750			case 40:
751				$$.type = DIGEST_SHA1;
752				break;
753			case 32:
754				$$.type = DIGEST_MD5;
755				break;
756			default:
757				yyerror("invalid http digest");
758				free($2);
759				YYERROR;
760			}
761			$$.digest = $2;
762		}
763		;
764
765proto		: relay_proto PROTO STRING	{
766			struct protocol *p;
767
768			if (strcmp($3, "default") == 0) {
769				p = &conf->sc_proto_default;
770			} else {
771				TAILQ_FOREACH(p, conf->sc_protos, entry)
772					if (!strcmp(p->name, $3))
773						break;
774			}
775			if (p != NULL) {
776				yyerror("protocol %s defined twice", $3);
777				free($3);
778				YYERROR;
779			}
780			if ((p = calloc(1, sizeof (*p))) == NULL)
781				fatal("out of memory");
782
783			if (strlcpy(p->name, $3, sizeof(p->name)) >=
784			    sizeof(p->name)) {
785				yyerror("protocol name truncated");
786				free(p);
787				YYERROR;
788			}
789			free($3);
790			p->id = ++last_proto_id;
791			p->type = $1;
792			p->cache = RELAY_CACHESIZE;
793			p->tcpflags = TCPFLAG_DEFAULT;
794			p->sslflags = SSLFLAG_DEFAULT;
795			p->tcpbacklog = RELAY_BACKLOG;
796			(void)strlcpy(p->sslciphers, SSLCIPHERS_DEFAULT,
797			    sizeof(p->sslciphers));
798			if (last_proto_id == INT_MAX) {
799				yyerror("too many protocols defined");
800				free(p);
801				YYERROR;
802			}
803			RB_INIT(&p->request_tree);
804			RB_INIT(&p->response_tree);
805			proto = p;
806		} protopts_n			{
807			conf->sc_protocount++;
808
809			if ((proto->sslflags & SSLFLAG_VERSION) == 0) {
810				yyerror("invalid SSL protocol");
811				YYERROR;
812			}
813
814			TAILQ_INSERT_TAIL(conf->sc_protos, proto, entry);
815		}
816		;
817
818protopts_n	: /* empty */
819		| '{' '}'
820		| '{' optnl protopts_l '}'
821		;
822
823protopts_l	: protopts_l protoptsl nl
824		| protoptsl optnl
825		;
826
827protoptsl	: SSL sslflags
828		| SSL '{' sslflags_l '}'
829		| TCP tcpflags
830		| TCP '{' tcpflags_l '}'
831		| RETURN ERROR opteflags	{ proto->flags |= F_RETURN; }
832		| RETURN ERROR '{' eflags_l '}'	{ proto->flags |= F_RETURN; }
833		| LABEL STRING			{
834			label = pn_name2id($2);
835			free($2);
836			if (label == 0) {
837				yyerror("invalid protocol action label");
838				YYERROR;
839			}
840		}
841		| NO LABEL			{
842			label = 0;
843		}
844		| direction			{
845			node.label = label;
846			nodedirection = $1;
847		} protonode {
848			if (nodedirection != -1 &&
849			    protonode_add(nodedirection, proto, &node) == -1) {
850				yyerror("failed to add protocol node");
851				YYERROR;
852			}
853			bzero(&node, sizeof(node));
854		}
855		| include
856		;
857
858direction	: /* empty */		{ $$ = RELAY_DIR_REQUEST; }
859		| REQUEST		{ $$ = RELAY_DIR_REQUEST; }
860		| RESPONSE		{ $$ = RELAY_DIR_RESPONSE; }
861		;
862
863tcpflags_l	: tcpflags comma tcpflags_l
864		| tcpflags
865		;
866
867tcpflags	: SACK			{ proto->tcpflags |= TCPFLAG_SACK; }
868		| NO SACK		{ proto->tcpflags |= TCPFLAG_NSACK; }
869		| NODELAY		{ proto->tcpflags |= TCPFLAG_NODELAY; }
870		| NO NODELAY		{ proto->tcpflags |= TCPFLAG_NNODELAY; }
871		| BACKLOG NUMBER	{
872			if ($2 < 0 || $2 > RELAY_MAX_SESSIONS) {
873				yyerror("invalid backlog: %d", $2);
874				YYERROR;
875			}
876			proto->tcpbacklog = $2;
877		}
878		| SOCKET BUFFER NUMBER	{
879			proto->tcpflags |= TCPFLAG_BUFSIZ;
880			if ((proto->tcpbufsiz = $3) < 0) {
881				yyerror("invalid socket buffer size: %d", $3);
882				YYERROR;
883			}
884		}
885		| IP STRING NUMBER	{
886			if ($3 < 0) {
887				yyerror("invalid ttl: %d", $3);
888				free($2);
889				YYERROR;
890			}
891			if (strcasecmp("ttl", $2) == 0) {
892				proto->tcpflags |= TCPFLAG_IPTTL;
893				proto->tcpipttl = $3;
894			} else if (strcasecmp("minttl", $2) == 0) {
895				proto->tcpflags |= TCPFLAG_IPMINTTL;
896				proto->tcpipminttl = $3;
897			} else {
898				yyerror("invalid TCP/IP flag: %s", $2);
899				free($2);
900				YYERROR;
901			}
902			free($2);
903		}
904		;
905
906sslflags_l	: sslflags comma sslflags_l
907		| sslflags
908		;
909
910sslflags	: SESSION CACHE sslcache	{ proto->cache = $3; }
911		| CIPHERS STRING		{
912			if (strlcpy(proto->sslciphers, $2,
913			    sizeof(proto->sslciphers)) >=
914			    sizeof(proto->sslciphers)) {
915				yyerror("sslciphers truncated");
916				free($2);
917				YYERROR;
918			}
919			free($2);
920		}
921		| CA FILENAME STRING		{
922			if (proto->sslca != NULL) {
923				yyerror("sslca already specified");
924				free($3);
925				YYERROR;
926			}
927			proto->sslca = $3;
928		}
929		| NO flag			{ proto->sslflags &= ~($2); }
930		| flag				{ proto->sslflags |= $1; }
931		;
932
933flag		: STRING			{
934			if (strcmp("sslv2", $1) == 0)
935				$$ = SSLFLAG_SSLV2;
936			else if (strcmp("sslv3", $1) == 0)
937				$$ = SSLFLAG_SSLV3;
938			else if (strcmp("tlsv1", $1) == 0)
939				$$ = SSLFLAG_TLSV1;
940			else {
941				yyerror("invalid SSL flag: %s", $1);
942				free($1);
943				YYERROR;
944			}
945			free($1);
946		}
947		;
948
949protonode	: nodetype APPEND STRING TO STRING nodeopts		{
950			node.action = NODE_ACTION_APPEND;
951			node.key = strdup($5);
952			node.value = strdup($3);
953			if (node.key == NULL || node.value == NULL)
954				fatal("out of memory");
955			if (strchr(node.value, '$') != NULL)
956				node.flags |= PNFLAG_MACRO;
957			free($5);
958			free($3);
959		}
960		| nodetype CHANGE STRING TO STRING nodeopts		{
961			node.action = NODE_ACTION_CHANGE;
962			node.key = strdup($3);
963			node.value = strdup($5);
964			if (node.key == NULL || node.value == NULL)
965				fatal("out of memory");
966			if (strchr(node.value, '$') != NULL)
967				node.flags |= PNFLAG_MACRO;
968			free($5);
969			free($3);
970		}
971		| nodetype REMOVE STRING nodeopts			{
972			node.action = NODE_ACTION_REMOVE;
973			node.key = strdup($3);
974			node.value = NULL;
975			if (node.key == NULL)
976				fatal("out of memory");
977			free($3);
978		}
979		| nodetype REMOVE					{
980			node.action = NODE_ACTION_REMOVE;
981			node.key = NULL;
982			node.value = NULL;
983		} nodefile
984		| nodetype EXPECT STRING FROM STRING nodeopts		{
985			node.action = NODE_ACTION_EXPECT;
986			node.key = strdup($5);
987			node.value = strdup($3);
988			if (node.key == NULL || node.value == NULL)
989				fatal("out of memory");
990			free($5);
991			free($3);
992			proto->lateconnect++;
993		}
994		| nodetype EXPECT STRING nodeopts			{
995			node.action = NODE_ACTION_EXPECT;
996			node.key = strdup($3);
997			node.value = strdup("*");
998			if (node.key == NULL || node.value == NULL)
999				fatal("out of memory");
1000			free($3);
1001			proto->lateconnect++;
1002		}
1003		| nodetype EXPECT					{
1004			node.action = NODE_ACTION_EXPECT;
1005			node.key = NULL;
1006			node.value = "*";
1007			proto->lateconnect++;
1008		} nodefile
1009		| nodetype EXPECT digest nodeopts			{
1010			if (node.type != NODE_TYPE_URL) {
1011				yyerror("digest not supported for this type");
1012				free($3.digest);
1013				YYERROR;
1014			}
1015			node.action = NODE_ACTION_EXPECT;
1016			node.key = strdup($3.digest);
1017			node.flags |= PNFLAG_LOOKUP_DIGEST($3.type);
1018			node.value = strdup("*");
1019			if (node.key == NULL || node.value == NULL)
1020				fatal("out of memory");
1021			free($3.digest);
1022			proto->lateconnect++;
1023		}
1024		| nodetype FILTER STRING FROM STRING nodeopts		{
1025			node.action = NODE_ACTION_FILTER;
1026			node.key = strdup($5);
1027			node.value = strdup($3);
1028			if (node.key == NULL || node.value == NULL)
1029				fatal("out of memory");
1030			free($5);
1031			free($3);
1032			proto->lateconnect++;
1033		}
1034		| nodetype FILTER STRING nodeopts			{
1035			node.action = NODE_ACTION_FILTER;
1036			node.key = strdup($3);
1037			node.value = strdup("*");
1038			if (node.key == NULL || node.value == NULL)
1039				fatal("out of memory");
1040			free($3);
1041			proto->lateconnect++;
1042		}
1043		| nodetype FILTER					{
1044			node.action = NODE_ACTION_FILTER;
1045			node.key = NULL;
1046			node.value = "*";
1047			proto->lateconnect++;
1048		} nodefile
1049		| nodetype FILTER digest nodeopts			{
1050			if (node.type != NODE_TYPE_URL) {
1051				yyerror("digest not supported for this type");
1052				free($3.digest);
1053				YYERROR;
1054			}
1055			node.action = NODE_ACTION_FILTER;
1056			node.key = strdup($3.digest);
1057			node.flags |= PNFLAG_LOOKUP_DIGEST($3.type);
1058			node.value = strdup("*");
1059			if (node.key == NULL || node.value == NULL)
1060				fatal("out of memory");
1061			free($3.digest);
1062			proto->lateconnect++;
1063		}
1064		| nodetype HASH STRING nodeopts				{
1065			node.action = NODE_ACTION_HASH;
1066			node.key = strdup($3);
1067			node.value = NULL;
1068			if (node.key == NULL)
1069				fatal("out of memory");
1070			free($3);
1071			proto->lateconnect++;
1072		}
1073		| nodetype LOG STRING nodeopts				{
1074			node.action = NODE_ACTION_LOG;
1075			node.key = strdup($3);
1076			node.value = NULL;
1077			node.flags |= PNFLAG_LOG;
1078			if (node.key == NULL)
1079				fatal("out of memory");
1080			free($3);
1081		}
1082		| nodetype LOG						{
1083			node.action = NODE_ACTION_LOG;
1084			node.key = NULL;
1085			node.value = NULL;
1086			node.flags |= PNFLAG_LOG;
1087		} nodefile
1088		| nodetype MARK STRING FROM STRING WITH mark log	{
1089			node.action = NODE_ACTION_MARK;
1090			node.key = strdup($5);
1091			node.value = strdup($3);
1092			node.mark = $7;
1093			if (node.key == NULL || node.value == NULL)
1094				fatal("out of memory");
1095			free($3);
1096			free($5);
1097		}
1098		| nodetype MARK STRING WITH mark nodeopts		{
1099			node.action = NODE_ACTION_MARK;
1100			node.key = strdup($3);
1101			node.value = strdup("*");
1102			node.mark = $5;	/* overwrite */
1103			if (node.key == NULL || node.value == NULL)
1104				fatal("out of memory");
1105			free($3);
1106		}
1107		;
1108
1109nodefile	: FILENAME STRING nodeopts			{
1110			if (protonode_load(nodedirection,
1111			    proto, &node, $2) == -1) {
1112				yyerror("failed to load from file: %s", $2);
1113				free($2);
1114				YYERROR;
1115			}
1116			free($2);
1117			nodedirection = -1;	/* don't add template node */
1118		}
1119		;
1120
1121nodeopts	: marked log
1122		;
1123
1124marked		: /* empty */
1125		| MARKED mark			{ node.mark = $2; }
1126		;
1127
1128log		: /* empty */
1129		| LOG				{ node.flags |= PNFLAG_LOG; }
1130		;
1131
1132mark		: NUMBER					{
1133			if ($1 <= 0 || $1 >= (int)USHRT_MAX) {
1134				yyerror("invalid mark: %d", $1);
1135				YYERROR;
1136			}
1137			$$ = $1;
1138		}
1139		;
1140
1141nodetype	: HEADER			{
1142			node.type = NODE_TYPE_HEADER;
1143		}
1144		| QUERYSTR			{ node.type = NODE_TYPE_QUERY; }
1145		| COOKIE			{
1146			node.type = NODE_TYPE_COOKIE;
1147		}
1148		| PATH				{
1149			proto->flags |= F_LOOKUP_PATH;
1150			node.type = NODE_TYPE_PATH;
1151		}
1152		| URL				{ node.type = NODE_TYPE_URL; }
1153		;
1154
1155sslcache	: NUMBER			{
1156			if ($1 < 0) {
1157				yyerror("invalid sslcache value: %d", $1);
1158				YYERROR;
1159			}
1160			$$ = $1;
1161		}
1162		| DISABLE			{ $$ = -2; }
1163		;
1164
1165relay		: RELAY STRING	{
1166			struct relay *r;
1167
1168			TAILQ_FOREACH(r, conf->sc_relays, rl_entry)
1169				if (!strcmp(r->rl_conf.name, $2))
1170					break;
1171			if (r != NULL) {
1172				yyerror("relay %s defined twice", $2);
1173				free($2);
1174				YYERROR;
1175			}
1176			TAILQ_INIT(&relays);
1177
1178			if ((r = calloc(1, sizeof (*r))) == NULL)
1179				fatal("out of memory");
1180
1181			if (strlcpy(r->rl_conf.name, $2, sizeof(r->rl_conf.name)) >=
1182			    sizeof(r->rl_conf.name)) {
1183				yyerror("relay name truncated");
1184				free(r);
1185				YYERROR;
1186			}
1187			free($2);
1188			r->rl_conf.id = ++last_relay_id;
1189			r->rl_conf.timeout.tv_sec = RELAY_TIMEOUT;
1190			r->rl_proto = NULL;
1191			r->rl_conf.proto = EMPTY_ID;
1192			r->rl_conf.dsttable = EMPTY_ID;
1193			r->rl_conf.dstmode = RELAY_DSTMODE_DEFAULT;
1194			r->rl_conf.dstretry = 0;
1195			if (last_relay_id == INT_MAX) {
1196				yyerror("too many relays defined");
1197				free(r);
1198				YYERROR;
1199			}
1200			rlay = r;
1201		} '{' optnl relayopts_l '}'	{
1202			struct relay	*r;
1203
1204			if (rlay->rl_conf.ss.ss_family == AF_UNSPEC) {
1205				yyerror("relay %s has no listener",
1206				    rlay->rl_conf.name);
1207				YYERROR;
1208			}
1209			if ((rlay->rl_conf.flags & F_NATLOOK) == 0 &&
1210			    rlay->rl_conf.dstss.ss_family == AF_UNSPEC &&
1211			    rlay->rl_conf.dsttable == EMPTY_ID) {
1212				yyerror("relay %s has no target, rdr, "
1213				    "or table", rlay->rl_conf.name);
1214				YYERROR;
1215			}
1216			if (rlay->rl_conf.proto == EMPTY_ID) {
1217				rlay->rl_proto = &conf->sc_proto_default;
1218				rlay->rl_conf.proto = conf->sc_proto_default.id;
1219			}
1220			if (relay_load_certfiles(rlay) == -1) {
1221				yyerror("cannot load certificates for relay %s",
1222				    rlay->rl_conf.name);
1223				YYERROR;
1224			}
1225			conf->sc_relaycount++;
1226			SPLAY_INIT(&rlay->rl_sessions);
1227			TAILQ_INSERT_TAIL(conf->sc_relays, rlay, rl_entry);
1228			tableport = 0;
1229
1230			while ((r = TAILQ_FIRST(&relays)) != NULL) {
1231				TAILQ_REMOVE(&relays, r, rl_entry);
1232				if (relay_inherit(rlay, r) == NULL) {
1233					YYERROR;
1234				}
1235			}
1236			rlay = NULL;
1237		}
1238		;
1239
1240relayopts_l	: relayopts_l relayoptsl nl
1241		| relayoptsl optnl
1242		;
1243
1244relayoptsl	: LISTEN ON STRING port optssl {
1245			struct addresslist	 al;
1246			struct address		*h;
1247			struct relay		*r;
1248
1249			if (rlay->rl_conf.ss.ss_family != AF_UNSPEC) {
1250				if ((r = calloc(1, sizeof (*r))) == NULL)
1251					fatal("out of memory");
1252				TAILQ_INSERT_TAIL(&relays, r, rl_entry);
1253			} else
1254				r = rlay;
1255			if ($4.op != PF_OP_EQ) {
1256				yyerror("invalid port");
1257				free($3);
1258				YYERROR;
1259			}
1260
1261			TAILQ_INIT(&al);
1262			if (host($3, &al, 1, &$4, NULL, -1) <= 0) {
1263				yyerror("invalid listen ip: %s", $3);
1264				free($3);
1265				YYERROR;
1266			}
1267			free($3);
1268			h = TAILQ_FIRST(&al);
1269			bcopy(&h->ss, &r->rl_conf.ss, sizeof(r->rl_conf.ss));
1270			r->rl_conf.port = h->port.val[0];
1271			if ($5) {
1272				r->rl_conf.flags |= F_SSL;
1273				conf->sc_flags |= F_SSL;
1274			}
1275			tableport = h->port.val[0];
1276		}
1277		| forwardmode optsslclient TO forwardspec interface dstaf {
1278			rlay->rl_conf.fwdmode = $1;
1279			switch ($1) {
1280			case FWD_NORMAL:
1281				if ($5 == NULL)
1282					break;
1283				yyerror("superfluous interface");
1284				YYERROR;
1285			case FWD_ROUTE:
1286				yyerror("no route for redirections");
1287				YYERROR;
1288			case FWD_TRANS:
1289				if ($5 != NULL)
1290					break;
1291				yyerror("missing interface");
1292				YYERROR;
1293			}
1294			if ($5 != NULL) {
1295				strlcpy(rlay->rl_conf.ifname, $5,
1296				    sizeof(rlay->rl_conf.ifname));
1297				free($5);
1298			}
1299			if ($2) {
1300				rlay->rl_conf.flags |= F_SSLCLIENT;
1301				conf->sc_flags |= F_SSLCLIENT;
1302			}
1303		}
1304		| SESSION TIMEOUT NUMBER		{
1305			if ((rlay->rl_conf.timeout.tv_sec = $3) < 0) {
1306				yyerror("invalid timeout: %d", $3);
1307				YYERROR;
1308			}
1309		}
1310		| PROTO STRING			{
1311			struct protocol *p;
1312
1313			TAILQ_FOREACH(p, conf->sc_protos, entry)
1314				if (!strcmp(p->name, $2))
1315					break;
1316			if (p == NULL) {
1317				yyerror("no such protocol: %s", $2);
1318				free($2);
1319				YYERROR;
1320			}
1321			p->flags |= F_USED;
1322			rlay->rl_conf.proto = p->id;
1323			rlay->rl_proto = p;
1324			free($2);
1325		}
1326		| DISABLE		{ rlay->rl_conf.flags |= F_DISABLE; }
1327		| include
1328		;
1329
1330forwardspec	: STRING port retry	{
1331			struct addresslist	 al;
1332			struct address		*h;
1333
1334			if (rlay->rl_conf.dstss.ss_family != AF_UNSPEC) {
1335				yyerror("relay %s target or redirection already "
1336				    "specified", rlay->rl_conf.name);
1337				free($1);
1338				YYERROR;
1339			}
1340			if ($2.op != PF_OP_EQ) {
1341				yyerror("invalid port");
1342				free($1);
1343				YYERROR;
1344			}
1345
1346			TAILQ_INIT(&al);
1347			if (host($1, &al, 1, &$2, NULL, -1) <= 0) {
1348				yyerror("invalid listen ip: %s", $1);
1349				free($1);
1350				YYERROR;
1351			}
1352			free($1);
1353			h = TAILQ_FIRST(&al);
1354			bcopy(&h->ss, &rlay->rl_conf.dstss,
1355			    sizeof(rlay->rl_conf.dstss));
1356			rlay->rl_conf.dstport = h->port.val[0];
1357			rlay->rl_conf.dstretry = $3;
1358		}
1359		| NAT LOOKUP retry	{
1360			conf->sc_flags |= F_NEEDPF;
1361			rlay->rl_conf.flags |= F_NATLOOK;
1362			rlay->rl_conf.dstretry = $3;
1363		}
1364		| tablespec	{
1365			if (rlay->rl_dsttable) {
1366				yyerror("table already specified");
1367				purge_table(conf->sc_tables, $1);
1368				YYERROR;
1369			}
1370
1371			rlay->rl_dsttable = $1;
1372			rlay->rl_dsttable->conf.flags |= F_USED;
1373			rlay->rl_conf.dsttable = $1->conf.id;
1374			rlay->rl_conf.dstport = $1->conf.port;
1375		}
1376		;
1377
1378dstmode		: /* empty */		{ $$ = RELAY_DSTMODE_DEFAULT; }
1379		| LOADBALANCE		{ $$ = RELAY_DSTMODE_LOADBALANCE; }
1380		| ROUNDROBIN		{ $$ = RELAY_DSTMODE_ROUNDROBIN; }
1381		| HASH			{ $$ = RELAY_DSTMODE_HASH; }
1382		;
1383
1384router		: ROUTER STRING		{
1385			struct router *rt = NULL;
1386
1387			conf->sc_flags |= F_NEEDRT;
1388			TAILQ_FOREACH(rt, conf->sc_rts, rt_entry)
1389				if (!strcmp(rt->rt_conf.name, $2))
1390					break;
1391			if (rt != NULL) {
1392				yyerror("router %s defined twice", $2);
1393				free($2);
1394				YYERROR;
1395			}
1396
1397			if ((rt = calloc(1, sizeof (*rt))) == NULL)
1398				fatal("out of memory");
1399
1400			if (strlcpy(rt->rt_conf.name, $2,
1401			    sizeof(rt->rt_conf.name)) >=
1402			    sizeof(rt->rt_conf.name)) {
1403				yyerror("router name truncated");
1404				free(rt);
1405				YYERROR;
1406			}
1407			free($2);
1408			rt->rt_conf.id = ++last_rt_id;
1409			if (last_rt_id == INT_MAX) {
1410				yyerror("too many routers defined");
1411				free(rt);
1412				YYERROR;
1413			}
1414			TAILQ_INIT(&rt->rt_netroutes);
1415			router = rt;
1416
1417			tableport = -1;
1418		} '{' optnl routeopts_l '}'	{
1419			if (!router->rt_conf.nroutes) {
1420				yyerror("router %s without routes",
1421				    router->rt_conf.name);
1422				free(router);
1423				router = NULL;
1424				YYERROR;
1425			}
1426
1427			conf->sc_routercount++;
1428			TAILQ_INSERT_TAIL(conf->sc_rts, router, rt_entry);
1429			router = NULL;
1430
1431			tableport = 0;
1432		}
1433		;
1434
1435routeopts_l	: routeopts_l routeoptsl nl
1436		| routeoptsl optnl
1437		;
1438
1439routeoptsl	: ROUTE address '/' NUMBER {
1440			struct netroute	*nr;
1441
1442			if (router->rt_af == AF_UNSPEC)
1443				router->rt_af = $2.ss.ss_family;
1444			else if (router->rt_af != $2.ss.ss_family) {
1445				yyerror("router %s address family mismatch",
1446				    router->rt_conf.name);
1447				YYERROR;
1448			}
1449
1450			if ((router->rt_af == AF_INET && ($4 > 32 || $4 < 0)) ||
1451			    (router->rt_af == AF_INET6 && ($4 > 128 || $4 < 0))) {
1452				yyerror("invalid prefixlen %d", $4);
1453				YYERROR;
1454			}
1455
1456			if ((nr = calloc(1, sizeof(*nr))) == NULL)
1457				fatal("out of memory");
1458
1459			nr->nr_conf.id = ++last_nr_id;
1460			if (last_nr_id == INT_MAX) {
1461				yyerror("too many routes defined");
1462				free(nr);
1463				YYERROR;
1464			}
1465			nr->nr_conf.prefixlen = $4;
1466			nr->nr_conf.routerid = router->rt_conf.id;
1467			nr->nr_router = router;
1468			bcopy(&$2.ss, &nr->nr_conf.ss, sizeof($2.ss));
1469
1470			router->rt_conf.nroutes++;
1471			conf->sc_routecount++;
1472			TAILQ_INSERT_TAIL(&router->rt_netroutes, nr, nr_entry);
1473			TAILQ_INSERT_TAIL(conf->sc_routes, nr, nr_route);
1474		}
1475		| FORWARD TO tablespec {
1476			if (router->rt_gwtable) {
1477				yyerror("router %s table already specified",
1478				    router->rt_conf.name);
1479				purge_table(conf->sc_tables, $3);
1480				YYERROR;
1481			}
1482			router->rt_gwtable = $3;
1483			router->rt_gwtable->conf.flags |= F_USED;
1484			router->rt_conf.gwtable = $3->conf.id;
1485			router->rt_conf.gwport = $3->conf.port;
1486		}
1487		| RTABLE NUMBER {
1488			if (router->rt_conf.rtable) {
1489				yyerror("router %s rtable already specified",
1490				    router->rt_conf.name);
1491				YYERROR;
1492			}
1493			if ($2 < 0 || $2 > RT_TABLEID_MAX) {
1494				yyerror("invalid rtable id %d", $2);
1495				YYERROR;
1496			}
1497			router->rt_conf.rtable = $2;
1498		}
1499		| RTLABEL STRING {
1500			if (strlcpy(router->rt_conf.label, $2,
1501			    sizeof(router->rt_conf.label)) >=
1502			    sizeof(router->rt_conf.label)) {
1503				yyerror("route label truncated");
1504				free($2);
1505				YYERROR;
1506			}
1507			free($2);
1508		}
1509		| DISABLE		{ rlay->rl_conf.flags |= F_DISABLE; }
1510		| include
1511		;
1512
1513dstaf		: /* empty */		{
1514			rlay->rl_conf.dstaf.ss_family = AF_UNSPEC;
1515		}
1516		| INET			{
1517			rlay->rl_conf.dstaf.ss_family = AF_INET;
1518		}
1519		| INET6	STRING		{
1520			struct sockaddr_in6	*sin6;
1521
1522			sin6 = (struct sockaddr_in6 *)&rlay->rl_conf.dstaf;
1523			if (inet_pton(AF_INET6, $2, &sin6->sin6_addr) == -1) {
1524				yyerror("invalid ipv6 address %s", $2);
1525				free($2);
1526				YYERROR;
1527			}
1528			free($2);
1529
1530			sin6->sin6_family = AF_INET6;
1531			sin6->sin6_len = sizeof(*sin6);
1532		}
1533		;
1534
1535interface	: /*empty*/		{ $$ = NULL; }
1536		| INTERFACE STRING	{ $$ = $2; }
1537		;
1538
1539host		: address	{
1540			if ((hst = calloc(1, sizeof(*(hst)))) == NULL)
1541				fatal("out of memory");
1542
1543			if (strlcpy(hst->conf.name, $1.name,
1544			    sizeof(hst->conf.name)) >= sizeof(hst->conf.name)) {
1545				yyerror("host name truncated");
1546				free(hst);
1547				YYERROR;
1548			}
1549			bcopy(&$1.ss, &hst->conf.ss, sizeof($1.ss));
1550			hst->conf.id = 0; /* will be set later */
1551			SLIST_INIT(&hst->children);
1552		} opthostflags {
1553			$$ = hst;
1554			hst = NULL;
1555		}
1556		;
1557
1558opthostflags	: /* empty */
1559		| hostflags_l
1560		;
1561
1562hostflags_l	: hostflags hostflags_l
1563		| hostflags
1564		;
1565
1566hostflags	: RETRY NUMBER		{
1567			if (hst->conf.retry) {
1568				yyerror("retry value already set");
1569				YYERROR;
1570			}
1571			if ($2 < 0) {
1572				yyerror("invalid retry value: %d\n", $2);
1573				YYERROR;
1574			}
1575			hst->conf.retry = $2;
1576		}
1577		| PARENT NUMBER		{
1578			if (hst->conf.parentid) {
1579				yyerror("parent value already set");
1580				YYERROR;
1581			}
1582			if ($2 < 0) {
1583				yyerror("invalid parent value: %d\n", $2);
1584				YYERROR;
1585			}
1586			hst->conf.parentid = $2;
1587		}
1588		| IP TTL NUMBER		{
1589			if (hst->conf.ttl) {
1590				yyerror("ttl value already set");
1591				YYERROR;
1592			}
1593			if ($3 < 0) {
1594				yyerror("invalid ttl value: %d\n", $3);
1595				YYERROR;
1596			}
1597			hst->conf.ttl = $3;
1598		}
1599		;
1600
1601address		: STRING	{
1602			struct address *a;
1603			struct addresslist al;
1604
1605			if (strlcpy($$.name, $1,
1606			    sizeof($$.name)) >= sizeof($$.name)) {
1607				yyerror("host name truncated");
1608				free($1);
1609				YYERROR;
1610			}
1611
1612			TAILQ_INIT(&al);
1613			if (host($1, &al, 1, NULL, NULL, -1) <= 0) {
1614				yyerror("invalid host %s", $1);
1615				free($1);
1616				YYERROR;
1617			}
1618			free($1);
1619			a = TAILQ_FIRST(&al);
1620			memcpy(&$$.ss, &a->ss, sizeof($$.ss));
1621			free(a);
1622		}
1623		;
1624
1625retry		: /* empty */		{ $$ = 0; }
1626		| RETRY NUMBER		{
1627			if (($$ = $2) < 0) {
1628				yyerror("invalid retry value: %d\n", $2);
1629				YYERROR;
1630			}
1631		}
1632		;
1633
1634timeout		: NUMBER
1635		{
1636			if ($1 < 0) {
1637				yyerror("invalid timeout: %d\n", $1);
1638				YYERROR;
1639			}
1640			$$.tv_sec = $1 / 1000;
1641			$$.tv_usec = ($1 % 1000) * 1000;
1642		}
1643		;
1644
1645comma		: ','
1646		| nl
1647		| /* empty */
1648		;
1649
1650optnl		: '\n' optnl
1651		|
1652		;
1653
1654nl		: '\n' optnl
1655		;
1656
1657%%
1658
1659struct keywords {
1660	const char	*k_name;
1661	int		 k_val;
1662};
1663
1664int
1665yyerror(const char *fmt, ...)
1666{
1667	va_list		 ap;
1668
1669	file->errors++;
1670	va_start(ap, fmt);
1671	fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
1672	vfprintf(stderr, fmt, ap);
1673	fprintf(stderr, "\n");
1674	va_end(ap);
1675	return (0);
1676}
1677
1678int
1679kw_cmp(const void *k, const void *e)
1680{
1681	return (strcmp(k, ((const struct keywords *)e)->k_name));
1682}
1683
1684int
1685lookup(char *s)
1686{
1687	/* this has to be sorted always */
1688	static const struct keywords keywords[] = {
1689		{ "all",		ALL },
1690		{ "append",		APPEND },
1691		{ "backlog",		BACKLOG },
1692		{ "backup",		BACKUP },
1693		{ "buffer",		BUFFER },
1694		{ "ca",			CA },
1695		{ "cache",		CACHE },
1696		{ "change",		CHANGE },
1697		{ "check",		CHECK },
1698		{ "ciphers",		CIPHERS },
1699		{ "code",		CODE },
1700		{ "cookie",		COOKIE },
1701		{ "demote",		DEMOTE },
1702		{ "digest",		DIGEST },
1703		{ "disable",		DISABLE },
1704		{ "error",		ERROR },
1705		{ "expect",		EXPECT },
1706		{ "external",		EXTERNAL },
1707		{ "file",		FILENAME },
1708		{ "filter",		FILTER },
1709		{ "forward",		FORWARD },
1710		{ "from",		FROM },
1711		{ "hash",		HASH },
1712		{ "header",		HEADER },
1713		{ "host",		HOST },
1714		{ "icmp",		ICMP },
1715		{ "include",		INCLUDE },
1716		{ "inet",		INET },
1717		{ "inet6",		INET6 },
1718		{ "interface",		INTERFACE },
1719		{ "interval",		INTERVAL },
1720		{ "ip",			IP },
1721		{ "label",		LABEL },
1722		{ "listen",		LISTEN },
1723		{ "loadbalance",	LOADBALANCE },
1724		{ "log",		LOG },
1725		{ "lookup",		LOOKUP },
1726		{ "mark",		MARK },
1727		{ "marked",		MARKED },
1728		{ "mode",		MODE },
1729		{ "nat",		NAT },
1730		{ "no",			NO },
1731		{ "nodelay",		NODELAY },
1732		{ "nothing",		NOTHING },
1733		{ "on",			ON },
1734		{ "parent",		PARENT },
1735		{ "path",		PATH },
1736		{ "port",		PORT },
1737		{ "prefork",		PREFORK },
1738		{ "protocol",		PROTO },
1739		{ "query",		QUERYSTR },
1740		{ "real",		REAL },
1741		{ "redirect",		REDIRECT },
1742		{ "relay",		RELAY },
1743		{ "remove",		REMOVE },
1744		{ "request",		REQUEST },
1745		{ "response",		RESPONSE },
1746		{ "retry",		RETRY },
1747		{ "return",		RETURN },
1748		{ "roundrobin",		ROUNDROBIN },
1749		{ "route",		ROUTE },
1750		{ "router",		ROUTER },
1751		{ "rtable",		RTABLE },
1752		{ "rtlabel",		RTLABEL },
1753		{ "sack",		SACK },
1754		{ "script",		SCRIPT },
1755		{ "send",		SEND },
1756		{ "session",		SESSION },
1757		{ "socket",		SOCKET },
1758		{ "ssl",		SSL },
1759		{ "sticky-address",	STICKYADDR },
1760		{ "style",		STYLE },
1761		{ "table",		TABLE },
1762		{ "tag",		TAG },
1763		{ "tcp",		TCP },
1764		{ "timeout",		TIMEOUT },
1765		{ "to",			TO },
1766		{ "transparent",	TRANSPARENT },
1767		{ "trap",		TRAP },
1768		{ "ttl",		TTL },
1769		{ "updates",		UPDATES },
1770		{ "url",		URL },
1771		{ "virtual",		VIRTUAL },
1772		{ "with",		WITH }
1773	};
1774	const struct keywords	*p;
1775
1776	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
1777	    sizeof(keywords[0]), kw_cmp);
1778
1779	if (p)
1780		return (p->k_val);
1781	else
1782		return (STRING);
1783}
1784
1785#define MAXPUSHBACK	128
1786
1787char	*parsebuf;
1788int	 parseindex;
1789char	 pushback_buffer[MAXPUSHBACK];
1790int	 pushback_index = 0;
1791
1792int
1793lgetc(int quotec)
1794{
1795	int		c, next;
1796
1797	if (parsebuf) {
1798		/* Read character from the parsebuffer instead of input. */
1799		if (parseindex >= 0) {
1800			c = parsebuf[parseindex++];
1801			if (c != '\0')
1802				return (c);
1803			parsebuf = NULL;
1804		} else
1805			parseindex++;
1806	}
1807
1808	if (pushback_index)
1809		return (pushback_buffer[--pushback_index]);
1810
1811	if (quotec) {
1812		if ((c = getc(file->stream)) == EOF) {
1813			yyerror("reached end of file while parsing "
1814			    "quoted string");
1815			if (file == topfile || popfile() == EOF)
1816				return (EOF);
1817			return (quotec);
1818		}
1819		return (c);
1820	}
1821
1822	while ((c = getc(file->stream)) == '\\') {
1823		next = getc(file->stream);
1824		if (next != '\n') {
1825			c = next;
1826			break;
1827		}
1828		yylval.lineno = file->lineno;
1829		file->lineno++;
1830	}
1831
1832	while (c == EOF) {
1833		if (file == topfile || popfile() == EOF)
1834			return (EOF);
1835		c = getc(file->stream);
1836	}
1837	return (c);
1838}
1839
1840int
1841lungetc(int c)
1842{
1843	if (c == EOF)
1844		return (EOF);
1845	if (parsebuf) {
1846		parseindex--;
1847		if (parseindex >= 0)
1848			return (c);
1849	}
1850	if (pushback_index < MAXPUSHBACK-1)
1851		return (pushback_buffer[pushback_index++] = c);
1852	else
1853		return (EOF);
1854}
1855
1856int
1857findeol(void)
1858{
1859	int	c;
1860
1861	parsebuf = NULL;
1862
1863	/* skip to either EOF or the first real EOL */
1864	while (1) {
1865		if (pushback_index)
1866			c = pushback_buffer[--pushback_index];
1867		else
1868			c = lgetc(0);
1869		if (c == '\n') {
1870			file->lineno++;
1871			break;
1872		}
1873		if (c == EOF)
1874			break;
1875	}
1876	return (ERROR);
1877}
1878
1879int
1880yylex(void)
1881{
1882	char	 buf[8096];
1883	char	*p, *val;
1884	int	 quotec, next, c;
1885	int	 token;
1886
1887top:
1888	p = buf;
1889	while ((c = lgetc(0)) == ' ' || c == '\t')
1890		; /* nothing */
1891
1892	yylval.lineno = file->lineno;
1893	if (c == '#')
1894		while ((c = lgetc(0)) != '\n' && c != EOF)
1895			; /* nothing */
1896	if (c == '$' && parsebuf == NULL) {
1897		while (1) {
1898			if ((c = lgetc(0)) == EOF)
1899				return (0);
1900
1901			if (p + 1 >= buf + sizeof(buf) - 1) {
1902				yyerror("string too long");
1903				return (findeol());
1904			}
1905			if (isalnum(c) || c == '_') {
1906				*p++ = (char)c;
1907				continue;
1908			}
1909			*p = '\0';
1910			lungetc(c);
1911			break;
1912		}
1913		val = symget(buf);
1914		if (val == NULL) {
1915			yyerror("macro '%s' not defined", buf);
1916			return (findeol());
1917		}
1918		parsebuf = val;
1919		parseindex = 0;
1920		goto top;
1921	}
1922
1923	switch (c) {
1924	case '\'':
1925	case '"':
1926		quotec = c;
1927		while (1) {
1928			if ((c = lgetc(quotec)) == EOF)
1929				return (0);
1930			if (c == '\n') {
1931				file->lineno++;
1932				continue;
1933			} else if (c == '\\') {
1934				if ((next = lgetc(quotec)) == EOF)
1935					return (0);
1936				if (next == quotec || c == ' ' || c == '\t')
1937					c = next;
1938				else if (next == '\n')
1939					continue;
1940				else
1941					lungetc(next);
1942			} else if (c == quotec) {
1943				*p = '\0';
1944				break;
1945			}
1946			if (p + 1 >= buf + sizeof(buf) - 1) {
1947				yyerror("string too long");
1948				return (findeol());
1949			}
1950			*p++ = (char)c;
1951		}
1952		yylval.v.string = strdup(buf);
1953		if (yylval.v.string == NULL)
1954			err(1, "yylex: strdup");
1955		return (STRING);
1956	}
1957
1958#define allowed_to_end_number(x) \
1959	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
1960
1961	if (c == '-' || isdigit(c)) {
1962		do {
1963			*p++ = c;
1964			if ((unsigned)(p-buf) >= sizeof(buf)) {
1965				yyerror("string too long");
1966				return (findeol());
1967			}
1968		} while ((c = lgetc(0)) != EOF && isdigit(c));
1969		lungetc(c);
1970		if (p == buf + 1 && buf[0] == '-')
1971			goto nodigits;
1972		if (c == EOF || allowed_to_end_number(c)) {
1973			const char *errstr = NULL;
1974
1975			*p = '\0';
1976			yylval.v.number = strtonum(buf, LLONG_MIN,
1977			    LLONG_MAX, &errstr);
1978			if (errstr) {
1979				yyerror("\"%s\" invalid number: %s",
1980				    buf, errstr);
1981				return (findeol());
1982			}
1983			return (NUMBER);
1984		} else {
1985nodigits:
1986			while (p > buf + 1)
1987				lungetc(*--p);
1988			c = *--p;
1989			if (c == '-')
1990				return (c);
1991		}
1992	}
1993
1994#define allowed_in_string(x) \
1995	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
1996	x != '{' && x != '}' && x != '<' && x != '>' && \
1997	x != '!' && x != '=' && x != '#' && \
1998	x != ',' && x != '/'))
1999
2000	if (isalnum(c) || c == ':' || c == '_') {
2001		do {
2002			*p++ = c;
2003			if ((unsigned)(p-buf) >= sizeof(buf)) {
2004				yyerror("string too long");
2005				return (findeol());
2006			}
2007		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
2008		lungetc(c);
2009		*p = '\0';
2010		if ((token = lookup(buf)) == STRING)
2011			if ((yylval.v.string = strdup(buf)) == NULL)
2012				err(1, "yylex: strdup");
2013		return (token);
2014	}
2015	if (c == '\n') {
2016		yylval.lineno = file->lineno;
2017		file->lineno++;
2018	}
2019	if (c == EOF)
2020		return (0);
2021	return (c);
2022}
2023
2024int
2025check_file_secrecy(int fd, const char *fname)
2026{
2027	struct stat	st;
2028
2029	if (fstat(fd, &st)) {
2030		log_warn("cannot stat %s", fname);
2031		return (-1);
2032	}
2033	if (st.st_uid != 0 && st.st_uid != getuid()) {
2034		log_warnx("%s: owner not root or current user", fname);
2035		return (-1);
2036	}
2037	if (st.st_mode & (S_IRWXG | S_IRWXO)) {
2038		log_warnx("%s: group/world readable/writeable", fname);
2039		return (-1);
2040	}
2041	return (0);
2042}
2043
2044struct file *
2045pushfile(const char *name, int secret)
2046{
2047	struct file	*nfile;
2048
2049	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
2050		log_warn("malloc");
2051		return (NULL);
2052	}
2053	if ((nfile->name = strdup(name)) == NULL) {
2054		log_warn("malloc");
2055		free(nfile);
2056		return (NULL);
2057	}
2058	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
2059		log_warn("%s", nfile->name);
2060		free(nfile->name);
2061		free(nfile);
2062		return (NULL);
2063	} else if (secret &&
2064	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
2065		fclose(nfile->stream);
2066		free(nfile->name);
2067		free(nfile);
2068		return (NULL);
2069	}
2070	nfile->lineno = 1;
2071	TAILQ_INSERT_TAIL(&files, nfile, entry);
2072	return (nfile);
2073}
2074
2075int
2076popfile(void)
2077{
2078	struct file	*prev;
2079
2080	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
2081		prev->errors += file->errors;
2082
2083	TAILQ_REMOVE(&files, file, entry);
2084	fclose(file->stream);
2085	free(file->name);
2086	free(file);
2087	file = prev;
2088	return (file ? 0 : EOF);
2089}
2090
2091struct relayd *
2092parse_config(const char *filename, int opts)
2093{
2094	struct sym	*sym, *next;
2095	struct table	*nexttb;
2096	struct host	*h, *ph;
2097
2098	if ((conf = calloc(1, sizeof(*conf))) == NULL ||
2099	    (conf->sc_tables = calloc(1, sizeof(*conf->sc_tables))) == NULL ||
2100	    (conf->sc_relays = calloc(1, sizeof(*conf->sc_relays))) == NULL ||
2101	    (conf->sc_protos = calloc(1, sizeof(*conf->sc_protos))) == NULL ||
2102	    (conf->sc_routes = calloc(1, sizeof(*conf->sc_routes))) == NULL ||
2103	    (conf->sc_rts = calloc(1, sizeof(*conf->sc_rts))) == NULL ||
2104	    (conf->sc_rdrs = calloc(1, sizeof(*conf->sc_rdrs))) == NULL) {
2105		if (conf != NULL) {
2106			if (conf->sc_tables != NULL)
2107				free(conf->sc_tables);
2108			if (conf->sc_relays != NULL)
2109				free(conf->sc_relays);
2110			if (conf->sc_protos != NULL)
2111				free(conf->sc_protos);
2112			if (conf->sc_rdrs != NULL)
2113				free(conf->sc_rdrs);
2114			if (conf->sc_rts != NULL)
2115				free(conf->sc_rts);
2116			free(conf);
2117		}
2118		log_warn("cannot allocate memory");
2119		return (NULL);
2120	}
2121
2122	errors = 0;
2123	last_host_id = last_table_id = last_rdr_id = last_proto_id =
2124	    last_relay_id = last_rt_id = last_nr_id = 0;
2125
2126	rdr = NULL;
2127	table = NULL;
2128	rlay = NULL;
2129	proto = NULL;
2130	router = NULL;
2131
2132	TAILQ_INIT(conf->sc_rdrs);
2133	TAILQ_INIT(conf->sc_tables);
2134	TAILQ_INIT(conf->sc_protos);
2135	TAILQ_INIT(conf->sc_relays);
2136	TAILQ_INIT(conf->sc_rts);
2137	TAILQ_INIT(conf->sc_routes);
2138
2139	memset(&conf->sc_empty_table, 0, sizeof(conf->sc_empty_table));
2140	conf->sc_empty_table.conf.id = EMPTY_TABLE;
2141	conf->sc_empty_table.conf.flags |= F_DISABLE;
2142	(void)strlcpy(conf->sc_empty_table.conf.name, "empty",
2143	    sizeof(conf->sc_empty_table.conf.name));
2144
2145	bzero(&conf->sc_proto_default, sizeof(conf->sc_proto_default));
2146	conf->sc_proto_default.flags = F_USED;
2147	conf->sc_proto_default.cache = RELAY_CACHESIZE;
2148	conf->sc_proto_default.type = RELAY_PROTO_TCP;
2149	(void)strlcpy(conf->sc_proto_default.name, "default",
2150	    sizeof(conf->sc_proto_default.name));
2151	RB_INIT(&conf->sc_proto_default.request_tree);
2152	RB_INIT(&conf->sc_proto_default.response_tree);
2153
2154	conf->sc_timeout.tv_sec = CHECK_TIMEOUT / 1000;
2155	conf->sc_timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000;
2156	conf->sc_interval.tv_sec = CHECK_INTERVAL;
2157	conf->sc_interval.tv_usec = 0;
2158	conf->sc_prefork_relay = RELAY_NUMPROC;
2159	conf->sc_statinterval.tv_sec = RELAY_STATINTERVAL;
2160	conf->sc_opts = opts;
2161	conf->sc_confpath = filename;
2162
2163	if ((file = pushfile(filename, 0)) == NULL) {
2164		free(conf);
2165		return (NULL);
2166	}
2167	topfile = file;
2168	setservent(1);
2169
2170	yyparse();
2171	errors = file->errors;
2172	popfile();
2173
2174	endservent();
2175	endprotoent();
2176
2177	/* Free macros and check which have not been used. */
2178	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
2179		next = TAILQ_NEXT(sym, entry);
2180		if ((conf->sc_opts & RELAYD_OPT_VERBOSE) && !sym->used)
2181			fprintf(stderr, "warning: macro '%s' not "
2182			    "used\n", sym->nam);
2183		if (!sym->persist) {
2184			free(sym->nam);
2185			free(sym->val);
2186			TAILQ_REMOVE(&symhead, sym, entry);
2187			free(sym);
2188		}
2189	}
2190
2191	if (TAILQ_EMPTY(conf->sc_rdrs) &&
2192	    TAILQ_EMPTY(conf->sc_relays) &&
2193	    TAILQ_EMPTY(conf->sc_rts)) {
2194		log_warnx("no actions, nothing to do");
2195		errors++;
2196	}
2197
2198	if (TAILQ_EMPTY(conf->sc_relays))
2199		conf->sc_prefork_relay = 0;
2200
2201	/* Cleanup relay list to inherit */
2202	while ((rlay = TAILQ_FIRST(&relays)) != NULL) {
2203		TAILQ_REMOVE(&relays, rlay, rl_entry);
2204		free(rlay);
2205	}
2206
2207	if (timercmp(&conf->sc_timeout, &conf->sc_interval, >=)) {
2208		log_warnx("global timeout exceeds interval");
2209		errors++;
2210	}
2211
2212	/* Verify that every table is used */
2213	for (table = TAILQ_FIRST(conf->sc_tables); table != NULL;
2214	     table = nexttb) {
2215		nexttb = TAILQ_NEXT(table, entry);
2216		if (table->conf.port == 0) {
2217			TAILQ_REMOVE(conf->sc_tables, table, entry);
2218			while ((h = TAILQ_FIRST(&table->hosts)) != NULL) {
2219				TAILQ_REMOVE(&table->hosts, h, entry);
2220				free(h);
2221			}
2222			if (table->sendbuf != NULL)
2223				free(table->sendbuf);
2224			free(table);
2225			continue;
2226		}
2227
2228		TAILQ_FOREACH(h, &table->hosts, entry) {
2229			if (h->conf.parentid) {
2230				ph = host_find(conf, h->conf.parentid);
2231
2232				/* Validate the parent id */
2233				if (h->conf.id == h->conf.parentid ||
2234				    ph == NULL || ph->conf.parentid)
2235					ph = NULL;
2236
2237				if (ph == NULL) {
2238					log_warnx("host parent id %d invalid",
2239					    h->conf.parentid);
2240					errors++;
2241				} else
2242					SLIST_INSERT_HEAD(&ph->children,
2243					    h, child);
2244			}
2245		}
2246
2247		if (!(table->conf.flags & F_USED)) {
2248			log_warnx("unused table: %s", table->conf.name);
2249			errors++;
2250		}
2251		if (timercmp(&table->conf.timeout, &conf->sc_interval, >=)) {
2252			log_warnx("table timeout exceeds interval: %s",
2253			    table->conf.name);
2254			errors++;
2255		}
2256	}
2257
2258	/* Verify that every non-default protocol is used */
2259	TAILQ_FOREACH(proto, conf->sc_protos, entry) {
2260		if (!(proto->flags & F_USED)) {
2261			log_warnx("unused protocol: %s", proto->name);
2262		}
2263	}
2264
2265	if (errors) {
2266		free(conf);
2267		return (NULL);
2268	}
2269
2270	return (conf);
2271}
2272
2273int
2274symset(const char *nam, const char *val, int persist)
2275{
2276	struct sym	*sym;
2277
2278	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
2279	    sym = TAILQ_NEXT(sym, entry))
2280		;	/* nothing */
2281
2282	if (sym != NULL) {
2283		if (sym->persist == 1)
2284			return (0);
2285		else {
2286			free(sym->nam);
2287			free(sym->val);
2288			TAILQ_REMOVE(&symhead, sym, entry);
2289			free(sym);
2290		}
2291	}
2292	if ((sym = calloc(1, sizeof(*sym))) == NULL)
2293		return (-1);
2294
2295	sym->nam = strdup(nam);
2296	if (sym->nam == NULL) {
2297		free(sym);
2298		return (-1);
2299	}
2300	sym->val = strdup(val);
2301	if (sym->val == NULL) {
2302		free(sym->nam);
2303		free(sym);
2304		return (-1);
2305	}
2306	sym->used = 0;
2307	sym->persist = persist;
2308	TAILQ_INSERT_TAIL(&symhead, sym, entry);
2309	return (0);
2310}
2311
2312int
2313cmdline_symset(char *s)
2314{
2315	char	*sym, *val;
2316	int	ret;
2317	size_t	len;
2318
2319	if ((val = strrchr(s, '=')) == NULL)
2320		return (-1);
2321
2322	len = strlen(s) - strlen(val) + 1;
2323	if ((sym = malloc(len)) == NULL)
2324		errx(1, "cmdline_symset: malloc");
2325
2326	(void)strlcpy(sym, s, len);
2327
2328	ret = symset(sym, val + 1, 1);
2329	free(sym);
2330
2331	return (ret);
2332}
2333
2334char *
2335symget(const char *nam)
2336{
2337	struct sym	*sym;
2338
2339	TAILQ_FOREACH(sym, &symhead, entry)
2340		if (strcmp(nam, sym->nam) == 0) {
2341			sym->used = 1;
2342			return (sym->val);
2343		}
2344	return (NULL);
2345}
2346
2347struct address *
2348host_v4(const char *s)
2349{
2350	struct in_addr		 ina;
2351	struct sockaddr_in	*sain;
2352	struct address		*h;
2353
2354	bzero(&ina, sizeof(ina));
2355	if (inet_pton(AF_INET, s, &ina) != 1)
2356		return (NULL);
2357
2358	if ((h = calloc(1, sizeof(*h))) == NULL)
2359		fatal(NULL);
2360	sain = (struct sockaddr_in *)&h->ss;
2361	sain->sin_len = sizeof(struct sockaddr_in);
2362	sain->sin_family = AF_INET;
2363	sain->sin_addr.s_addr = ina.s_addr;
2364
2365	return (h);
2366}
2367
2368struct address *
2369host_v6(const char *s)
2370{
2371	struct addrinfo		 hints, *res;
2372	struct sockaddr_in6	*sa_in6;
2373	struct address		*h = NULL;
2374
2375	bzero(&hints, sizeof(hints));
2376	hints.ai_family = AF_INET6;
2377	hints.ai_socktype = SOCK_DGRAM; /* dummy */
2378	hints.ai_flags = AI_NUMERICHOST;
2379	if (getaddrinfo(s, "0", &hints, &res) == 0) {
2380		if ((h = calloc(1, sizeof(*h))) == NULL)
2381			fatal(NULL);
2382		sa_in6 = (struct sockaddr_in6 *)&h->ss;
2383		sa_in6->sin6_len = sizeof(struct sockaddr_in6);
2384		sa_in6->sin6_family = AF_INET6;
2385		memcpy(&sa_in6->sin6_addr,
2386		    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
2387		    sizeof(sa_in6->sin6_addr));
2388		sa_in6->sin6_scope_id =
2389		    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
2390
2391		freeaddrinfo(res);
2392	}
2393
2394	return (h);
2395}
2396
2397int
2398host_dns(const char *s, struct addresslist *al, int max,
2399    struct portrange *port, const char *ifname, int ipproto)
2400{
2401	struct addrinfo		 hints, *res0, *res;
2402	int			 error, cnt = 0;
2403	struct sockaddr_in	*sain;
2404	struct sockaddr_in6	*sin6;
2405	struct address		*h;
2406
2407	if ((cnt = host_if(s, al, max, port, ifname, ipproto)) != 0)
2408		return (cnt);
2409
2410	bzero(&hints, sizeof(hints));
2411	hints.ai_family = PF_UNSPEC;
2412	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
2413	error = getaddrinfo(s, NULL, &hints, &res0);
2414	if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
2415		return (0);
2416	if (error) {
2417		log_warnx("host_dns: could not parse \"%s\": %s", s,
2418		    gai_strerror(error));
2419		return (-1);
2420	}
2421
2422	for (res = res0; res && cnt < max; res = res->ai_next) {
2423		if (res->ai_family != AF_INET &&
2424		    res->ai_family != AF_INET6)
2425			continue;
2426		if ((h = calloc(1, sizeof(*h))) == NULL)
2427			fatal(NULL);
2428
2429		if (port != NULL)
2430			bcopy(port, &h->port, sizeof(h->port));
2431		if (ifname != NULL) {
2432			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
2433			    sizeof(h->ifname))
2434				log_warnx("host_dns: interface name truncated");
2435			freeaddrinfo(res0);
2436			return (-1);
2437		}
2438		if (ipproto != -1)
2439			h->ipproto = ipproto;
2440		h->ss.ss_family = res->ai_family;
2441
2442		if (res->ai_family == AF_INET) {
2443			sain = (struct sockaddr_in *)&h->ss;
2444			sain->sin_len = sizeof(struct sockaddr_in);
2445			sain->sin_addr.s_addr = ((struct sockaddr_in *)
2446			    res->ai_addr)->sin_addr.s_addr;
2447		} else {
2448			sin6 = (struct sockaddr_in6 *)&h->ss;
2449			sin6->sin6_len = sizeof(struct sockaddr_in6);
2450			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
2451			    res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
2452		}
2453
2454		TAILQ_INSERT_HEAD(al, h, entry);
2455		cnt++;
2456	}
2457	if (cnt == max && res) {
2458		log_warnx("host_dns: %s resolves to more than %d hosts",
2459		    s, max);
2460	}
2461	freeaddrinfo(res0);
2462	return (cnt);
2463}
2464
2465int
2466host_if(const char *s, struct addresslist *al, int max,
2467    struct portrange *port, const char *ifname, int ipproto)
2468{
2469	struct ifaddrs		*ifap, *p;
2470	struct sockaddr_in	*sain;
2471	struct sockaddr_in6	*sin6;
2472	struct address		*h;
2473	int			 cnt = 0, af;
2474
2475	if (if_nametoindex(s) == 0)
2476		return (0);
2477
2478	if (getifaddrs(&ifap) == -1)
2479		fatal("getifaddrs");
2480
2481	/* First search for IPv4 addresses */
2482	af = AF_INET;
2483
2484 nextaf:
2485	for (p = ifap; p != NULL && cnt < max; p = p->ifa_next) {
2486		if (p->ifa_addr->sa_family != af ||
2487		    strcmp(s, p->ifa_name) != 0)
2488			continue;
2489		if ((h = calloc(1, sizeof(*h))) == NULL)
2490			fatal("calloc");
2491
2492		if (port != NULL)
2493			bcopy(port, &h->port, sizeof(h->port));
2494		if (ifname != NULL) {
2495			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
2496			    sizeof(h->ifname))
2497				log_warnx("host_if: interface name truncated");
2498			freeifaddrs(ifap);
2499			return (-1);
2500		}
2501		if (ipproto != -1)
2502			h->ipproto = ipproto;
2503		h->ss.ss_family = af;
2504
2505		if (af == AF_INET) {
2506			sain = (struct sockaddr_in *)&h->ss;
2507			sain->sin_len = sizeof(struct sockaddr_in);
2508			sain->sin_addr.s_addr = ((struct sockaddr_in *)
2509			    p->ifa_addr)->sin_addr.s_addr;
2510		} else {
2511			sin6 = (struct sockaddr_in6 *)&h->ss;
2512			sin6->sin6_len = sizeof(struct sockaddr_in6);
2513			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
2514			    p->ifa_addr)->sin6_addr, sizeof(struct in6_addr));
2515			sin6->sin6_scope_id = ((struct sockaddr_in6 *)
2516			    p->ifa_addr)->sin6_scope_id;
2517		}
2518
2519		TAILQ_INSERT_HEAD(al, h, entry);
2520		cnt++;
2521	}
2522	if (af == AF_INET) {
2523		/* Next search for IPv6 addresses */
2524		af = AF_INET6;
2525		goto nextaf;
2526	}
2527
2528	if (cnt > max) {
2529		log_warnx("host_if: %s resolves to more than %d hosts",
2530		    s, max);
2531	}
2532	freeifaddrs(ifap);
2533	return (cnt);
2534}
2535
2536int
2537host(const char *s, struct addresslist *al, int max,
2538    struct portrange *port, const char *ifname, int ipproto)
2539{
2540	struct address *h;
2541
2542	h = host_v4(s);
2543
2544	/* IPv6 address? */
2545	if (h == NULL)
2546		h = host_v6(s);
2547
2548	if (h != NULL) {
2549		if (port != NULL)
2550			bcopy(port, &h->port, sizeof(h->port));
2551		if (ifname != NULL) {
2552			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
2553			    sizeof(h->ifname)) {
2554				log_warnx("host: interface name truncated");
2555				return (-1);
2556			}
2557		}
2558		if (ipproto != -1)
2559			h->ipproto = ipproto;
2560
2561		TAILQ_INSERT_HEAD(al, h, entry);
2562		return (1);
2563	}
2564
2565	return (host_dns(s, al, max, port, ifname, ipproto));
2566}
2567
2568struct table *
2569table_inherit(struct table *tb)
2570{
2571	char		pname[TABLE_NAME_SIZE + 6];
2572	struct host	*h, *dsth;
2573	struct table	*dsttb, *oldtb;
2574
2575	/* Get the table or table template */
2576	if ((dsttb = table_findbyname(conf, tb->conf.name)) == NULL) {
2577		yyerror("unknown table %s", tb->conf.name);
2578		purge_table(NULL, tb);
2579		return (NULL);
2580	}
2581	if (dsttb->conf.port != 0)
2582		fatal("invalid table");	/* should not happen */
2583
2584	if (tb->conf.port == 0) {
2585		yyerror("invalid port");
2586		purge_table(NULL, tb);
2587		return (NULL);
2588	}
2589
2590	/* Check if a matching table already exists */
2591	if (snprintf(pname, sizeof(pname), "%s:%u",
2592	    tb->conf.name, ntohs(tb->conf.port)) >= (int)sizeof(pname)) {
2593		yyerror("invalid table name");
2594		return (NULL);
2595	}
2596	(void)strlcpy(tb->conf.name, pname, sizeof(tb->conf.name));
2597	if ((oldtb = table_findbyconf(conf, tb)) != NULL)
2598		return (oldtb);
2599
2600	/* Create a new table */
2601	tb->conf.id = ++last_table_id;
2602	if (last_table_id == INT_MAX) {
2603		yyerror("too many tables defined");
2604		purge_table(NULL, tb);
2605		return (NULL);
2606	}
2607	tb->conf.flags |= dsttb->conf.flags;
2608
2609	/* Inherit global table options */
2610	bcopy(&dsttb->conf.timeout, &tb->conf.timeout, sizeof(struct timeval));
2611	tb->conf.skip_cnt = dsttb->conf.skip_cnt;
2612	strlcpy(tb->conf.demote_group, dsttb->conf.demote_group,
2613	    sizeof(tb->conf.demote_group));
2614
2615	/* Copy the associated hosts */
2616	TAILQ_INIT(&tb->hosts);
2617	TAILQ_FOREACH(dsth, &dsttb->hosts, entry) {
2618		if ((h = (struct host *)
2619		    calloc(1, sizeof (*h))) == NULL)
2620			fatal("out of memory");
2621		bcopy(dsth, h, sizeof(*h));
2622		h->conf.id = ++last_host_id;
2623		if (last_host_id == INT_MAX) {
2624			yyerror("too many hosts defined");
2625			purge_table(NULL, tb);
2626			return (NULL);
2627		}
2628		h->conf.tableid = tb->conf.id;
2629		h->tablename = tb->conf.name;
2630		SLIST_INIT(&h->children);
2631		TAILQ_INSERT_TAIL(&tb->hosts, h, entry);
2632	}
2633
2634	conf->sc_tablecount++;
2635	TAILQ_INSERT_TAIL(conf->sc_tables, tb, entry);
2636
2637	return (tb);
2638}
2639
2640struct relay *
2641relay_inherit(struct relay *ra, struct relay *rb)
2642{
2643	struct relay_config	 rc;
2644
2645	bcopy(&rb->rl_conf, &rc, sizeof(rc));
2646	bcopy(ra, rb, sizeof(*rb));
2647
2648	bcopy(&rc.ss, &rb->rl_conf.ss, sizeof(rb->rl_conf.ss));
2649	rb->rl_conf.port = rc.port;
2650	rb->rl_conf.flags =
2651	    (ra->rl_conf.flags & ~F_SSL) | (rc.flags & F_SSL);
2652
2653	rb->rl_conf.id = ++last_relay_id;
2654	if (last_relay_id == INT_MAX) {
2655		yyerror("too many relays defined");
2656		goto err;
2657	}
2658
2659	if (snprintf(rb->rl_conf.name, sizeof(rb->rl_conf.name), "%s%u:%u",
2660	    ra->rl_conf.name, rb->rl_conf.id, ntohs(rc.port)) >=
2661	    (int)sizeof(rb->rl_conf.name)) {
2662		yyerror("invalid relay name");
2663		goto err;
2664	}
2665
2666	if (relay_findbyname(conf, rb->rl_conf.name) != NULL ||
2667	    relay_findbyaddr(conf, &rb->rl_conf) != NULL) {
2668		yyerror("relay %s defined twice", rb->rl_conf.name);
2669		goto err;
2670	}
2671	if (relay_load_certfiles(rb) == -1) {
2672		yyerror("cannot load certificates for relay %s",
2673		    rb->rl_conf.name);
2674		goto err;
2675	}
2676
2677	conf->sc_relaycount++;
2678	SPLAY_INIT(&rlay->rl_sessions);
2679	TAILQ_INSERT_TAIL(conf->sc_relays, rb, rl_entry);
2680
2681	return (rb);
2682
2683 err:
2684	free(rb);
2685	return (NULL);
2686}
2687
2688int
2689getservice(char *n)
2690{
2691	struct servent	*s;
2692	const char	*errstr;
2693	long long	 llval;
2694
2695	llval = strtonum(n, 0, UINT16_MAX, &errstr);
2696	if (errstr) {
2697		s = getservbyname(n, "tcp");
2698		if (s == NULL)
2699			s = getservbyname(n, "udp");
2700		if (s == NULL) {
2701			yyerror("unknown port %s", n);
2702			return (-1);
2703		}
2704		return (s->s_port);
2705	}
2706
2707	return (htons((u_short)llval));
2708}
2709