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