parse.y revision 1.82
1/*	$OpenBSD: parse.y,v 1.82 2007/11/19 14:48:19 reyk Exp $	*/
2
3/*
4 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
5 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
6 * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
7 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
8 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
9 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
10 * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
11 *
12 * Permission to use, copy, modify, and distribute this software for any
13 * purpose with or without fee is hereby granted, provided that the above
14 * copyright notice and this permission notice appear in all copies.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
17 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
19 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
22 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 */
24
25%{
26#include <sys/types.h>
27#include <sys/socket.h>
28#include <sys/stat.h>
29#include <sys/queue.h>
30#include <netinet/in.h>
31#include <net/if.h>
32#include <arpa/inet.h>
33#include <arpa/nameser.h>
34
35#include <ctype.h>
36#include <unistd.h>
37#include <err.h>
38#include <errno.h>
39#include <event.h>
40#include <limits.h>
41#include <stdint.h>
42#include <stdarg.h>
43#include <stdio.h>
44#include <netdb.h>
45#include <string.h>
46
47#include <openssl/ssl.h>
48
49#include "hoststated.h"
50
51TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
52static struct file {
53	TAILQ_ENTRY(file)	 entry;
54	FILE			*stream;
55	char			*name;
56	int			 lineno;
57	int			 errors;
58} *file;
59struct file	*pushfile(const char *, int);
60int		 popfile(void);
61int		 check_file_secrecy(int, const char *);
62int		 yyparse(void);
63int		 yylex(void);
64int		 yyerror(const char *, ...);
65int		 kw_cmp(const void *, const void *);
66int		 lookup(char *);
67int		 lgetc(int);
68int		 lungetc(int);
69int		 findeol(void);
70
71TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
72struct sym {
73	TAILQ_ENTRY(sym)	 entry;
74	int			 used;
75	int			 persist;
76	char			*nam;
77	char			*val;
78};
79int		 symset(const char *, const char *, int);
80char		*symget(const char *);
81
82struct hoststated	*conf = NULL;
83static int		 errors = 0;
84objid_t			 last_service_id = 0;
85objid_t			 last_table_id = 0;
86objid_t			 last_host_id = 0;
87objid_t			 last_relay_id = 0;
88objid_t			 last_proto_id = 0;
89
90static struct service	*service = NULL;
91static struct table	*table = NULL;
92static struct relay	*rlay = NULL;
93static struct protocol	*proto = NULL;
94static struct protonode	 node;
95
96struct address	*host_v4(const char *);
97struct address	*host_v6(const char *);
98int		 host_dns(const char *, struct addresslist *,
99		    int, in_port_t, const char *);
100int		 host(const char *, struct addresslist *,
101		    int, in_port_t, const char *);
102
103struct table	*table_inherit(const char *, in_port_t);
104
105typedef struct {
106	union {
107		int64_t		 number;
108		char		*string;
109		struct host	*host;
110		struct timeval	 tv;
111	} v;
112	int lineno;
113} YYSTYPE;
114
115%}
116
117%token	SERVICE TABLE BACKUP HOST REAL INCLUDE
118%token  CHECK TCP ICMP EXTERNAL REQUEST RESPONSE
119%token  TIMEOUT CODE DIGEST PORT TAG INTERFACE
120%token	VIRTUAL INTERVAL DISABLE STICKYADDR BACKLOG PATH SCRIPT
121%token	SEND EXPECT NOTHING SSL LOADBALANCE ROUNDROBIN CIPHERS COOKIE
122%token	RELAY LISTEN ON FORWARD TO NAT LOOKUP PREFORK NO MARK MARKED
123%token	PROTO SESSION CACHE APPEND CHANGE REMOVE FROM FILTER HASH HEADER
124%token	LOG UPDATES ALL DEMOTE NODELAY SACK SOCKET BUFFER URL RETRY IP
125%token	ERROR
126%token	<v.string>	STRING
127%token  <v.number>	NUMBER
128%type	<v.string>	interface hostname
129%type	<v.number>	port http_type loglevel sslcache optssl dstport
130%type	<v.number>	proto_type dstmode docheck retry log flag direction
131%type	<v.host>	host
132%type	<v.tv>		timeout
133
134%%
135
136grammar		: /* empty */
137		| grammar include '\n'
138		| grammar '\n'
139		| grammar varset '\n'
140		| grammar main '\n'
141		| grammar service '\n'
142		| grammar table '\n'
143		| grammar relay '\n'
144		| grammar proto '\n'
145		| grammar error '\n'		{ file->errors++; }
146		;
147
148include		: INCLUDE STRING		{
149			struct file	*nfile;
150
151			if ((nfile = pushfile($2, 0)) == NULL) {
152				yyerror("failed to include file %s", $2);
153				free($2);
154				YYERROR;
155			}
156			free($2);
157
158			file = nfile;
159			lungetc('\n');
160		}
161
162optssl		: /*empty*/	{ $$ = 0; }
163		| SSL		{ $$ = 1; }
164		;
165
166http_type	: STRING	{
167			if (strcmp("https", $1) == 0) {
168				$$ = 1;
169			} else if (strcmp("http", $1) == 0) {
170				$$ = 0;
171			} else {
172				yyerror("invalid check type: %s", $1);
173				free($1);
174				YYERROR;
175			}
176			free($1);
177		}
178		;
179
180hostname	: /* empty */		{
181			$$ = strdup("");
182			if ($$ == NULL)
183				fatal("calloc");
184		}
185		| HOST STRING	{
186			if (asprintf(&$$, "Host: %s\r\n", $2) == -1)
187				fatal("asprintf");
188		}
189		;
190
191proto_type	: TCP				{ $$ = RELAY_PROTO_TCP; }
192		| STRING			{
193			if (strcmp("http", $1) == 0) {
194				$$ = RELAY_PROTO_HTTP;
195			} else if (strcmp("dns", $1) == 0) {
196				$$ = RELAY_PROTO_DNS;
197			} else {
198				yyerror("invalid protocol type: %s", $1);
199				free($1);
200				YYERROR;
201			}
202			free($1);
203		}
204		;
205
206port		: PORT STRING {
207			struct servent	*servent;
208
209			servent = getservbyname($2, "tcp");
210			if (servent == NULL) {
211				yyerror("port %s is invalid", $2);
212				free($2);
213				YYERROR;
214			}
215			$$ = servent->s_port;
216			free($2);
217		}
218		| PORT NUMBER {
219			if ($2 <= 0 || $2 >= (int)USHRT_MAX) {
220				yyerror("invalid port: %d", $2);
221				YYERROR;
222			}
223			$$ = htons($2);
224		}
225		;
226
227varset		: STRING '=' STRING	{
228			if (symset($1, $3, 0) == -1)
229				fatal("cannot store variable");
230			free($1);
231			free($3);
232		}
233		;
234
235sendbuf		: NOTHING		{
236			table->sendbuf = NULL;
237			table->sendbuf_len = 0;
238		}
239		| STRING		{
240			table->sendbuf = strdup($1);
241			if (table->sendbuf == NULL)
242				fatal("out of memory");
243			table->sendbuf_len = strlen(table->sendbuf);
244			free($1);
245		}
246		;
247
248main		: INTERVAL NUMBER	{
249			if ((conf->interval.tv_sec = $2) < 0) {
250				yyerror("invalid interval: %d", $2);
251				YYERROR;
252			}
253		}
254		| LOG loglevel		{ conf->opts |= $2; }
255		| TIMEOUT timeout	{
256			bcopy(&$2, &conf->timeout, sizeof(struct timeval));
257		}
258		| PREFORK NUMBER	{
259			if ($2 <= 0 || $2 > RELAY_MAXPROC) {
260				yyerror("invalid number of preforked "
261				    "relays: %d", $2);
262				YYERROR;
263			}
264			conf->prefork_relay = $2;
265		}
266		| DEMOTE STRING		{
267			conf->flags |= F_DEMOTE;
268			if (strlcpy(conf->demote_group, $2,
269			    sizeof(conf->demote_group))
270			    >= sizeof(conf->demote_group)) {
271				yyerror("yyparse: demote group name too long");
272				free($2);
273				YYERROR;
274			}
275			free($2);
276			if (carp_demote_init(conf->demote_group, 1) == -1) {
277				yyerror("yyparse: error initializing group %s",
278				    conf->demote_group);
279				YYERROR;
280			}
281		}
282		;
283
284loglevel	: UPDATES		{ $$ = HOSTSTATED_OPT_LOGUPDATE; }
285		| ALL			{ $$ = HOSTSTATED_OPT_LOGALL; }
286		;
287
288service		: SERVICE STRING	{
289			struct service *srv;
290
291			TAILQ_FOREACH(srv, conf->services, entry)
292				if (!strcmp(srv->conf.name, $2))
293					break;
294			if (srv != NULL) {
295				yyerror("service %s defined twice", $2);
296				free($2);
297				YYERROR;
298			}
299			if ((srv = calloc(1, sizeof (*srv))) == NULL)
300				fatal("out of memory");
301
302			if (strlcpy(srv->conf.name, $2,
303			    sizeof(srv->conf.name)) >=
304			    sizeof(srv->conf.name)) {
305				yyerror("service name truncated");
306				YYERROR;
307			}
308			free($2);
309			srv->conf.id = last_service_id++;
310			if (last_service_id == INT_MAX) {
311				yyerror("too many services defined");
312				YYERROR;
313			}
314			service = srv;
315		} '{' optnl serviceopts_l '}'	{
316			if (service->table == NULL) {
317				yyerror("service %s has no table",
318				    service->conf.name);
319				YYERROR;
320			}
321			if (TAILQ_EMPTY(&service->virts)) {
322				yyerror("service %s has no virtual ip",
323				    service->conf.name);
324				YYERROR;
325			}
326			conf->servicecount++;
327			if (service->backup == NULL) {
328				service->conf.backup_id =
329				    conf->empty_table.conf.id;
330				service->backup = &conf->empty_table;
331			} else if (service->backup->conf.port !=
332			    service->table->conf.port) {
333				yyerror("service %s uses two different ports "
334				    "for its table and backup table",
335				    service->conf.name);
336				YYERROR;
337			}
338
339			if (!(service->conf.flags & F_DISABLE))
340				service->conf.flags |= F_ADD;
341			TAILQ_INSERT_HEAD(conf->services, service, entry);
342		}
343		;
344
345serviceopts_l	: serviceopts_l serviceoptsl nl
346		| serviceoptsl optnl
347		;
348
349serviceoptsl	: TABLE STRING dstport	{
350			struct table	*tb;
351			in_port_t	 port;
352
353			port = $3;
354			if (port == 0)
355				port = service->conf.port;
356			if ((tb = table_inherit($2, port)) == NULL) {
357				free($2);
358				YYERROR;
359			}
360			free($2);
361
362			service->table = tb;
363			service->conf.table_id = tb->conf.id;
364			service->table->conf.serviceid = service->conf.id;
365			service->table->conf.flags |= F_USED;
366		}
367		| BACKUP TABLE STRING dstport	{
368			struct table	*tb;
369			in_port_t	 port;
370
371			if (service->backup) {
372				yyerror("backup already specified");
373				free($3);
374				YYERROR;
375			}
376
377			port = $4;
378			if (port == 0)
379				port = service->conf.port;
380			if ((tb = table_inherit($3, port)) == NULL) {
381				free($3);
382				YYERROR;
383			}
384			free($3);
385
386			service->backup = tb;
387			service->conf.backup_id = tb->conf.id;
388			service->backup->conf.serviceid = service->conf.id;
389			service->backup->conf.flags |= (F_USED|F_BACKUP);
390		}
391		| VIRTUAL HOST STRING port interface {
392			if (host($3, &service->virts,
393				 SRV_MAX_VIRTS, $4, $5) <= 0) {
394				yyerror("invalid virtual ip: %s", $3);
395				free($3);
396				free($5);
397				YYERROR;
398			}
399			free($3);
400			free($5);
401			if (service->conf.port == 0)
402				service->conf.port = $4;
403		}
404		| DISABLE		{ service->conf.flags |= F_DISABLE; }
405		| STICKYADDR		{ service->conf.flags |= F_STICKY; }
406		| TAG STRING {
407			if (strlcpy(service->conf.tag, $2,
408			    sizeof(service->conf.tag)) >=
409			    sizeof(service->conf.tag)) {
410				yyerror("service tag name truncated");
411				free($2);
412				YYERROR;
413			}
414			free($2);
415		}
416		;
417
418table		: TABLE STRING	{
419			struct table *tb;
420
421			TAILQ_FOREACH(tb, conf->tables, entry)
422				if (!strcmp(tb->conf.name, $2))
423					break;
424			if (tb != NULL) {
425				yyerror("table %s defined twice", $2);
426				free($2);
427				YYERROR;
428			}
429
430			if ((tb = calloc(1, sizeof (*tb))) == NULL)
431				fatal("out of memory");
432
433			if (strlcpy(tb->conf.name, $2, sizeof(tb->conf.name)) >=
434			    sizeof(tb->conf.name)) {
435				yyerror("table name truncated");
436				YYERROR;
437			}
438			tb->conf.id = last_table_id++;
439			bcopy(&conf->timeout, &tb->conf.timeout,
440			    sizeof(struct timeval));
441			if (last_table_id == INT_MAX) {
442				yyerror("too many tables defined");
443				YYERROR;
444			}
445			free($2);
446			table = tb;
447		} '{' optnl tableopts_l '}'	{
448			if (TAILQ_EMPTY(&table->hosts)) {
449				yyerror("table %s has no hosts",
450				    table->conf.name);
451				YYERROR;
452			}
453			if (table->conf.check == CHECK_NOCHECK) {
454				yyerror("table %s has no check",
455				    table->conf.name);
456				YYERROR;
457			}
458			conf->tablecount++;
459			TAILQ_INSERT_HEAD(conf->tables, table, entry);
460		}
461		;
462
463tableopts_l	: tableopts_l tableoptsl nl
464		| tableoptsl optnl
465		;
466
467tableoptsl	: host			{
468			$1->conf.tableid = table->conf.id;
469			$1->tablename = table->conf.name;
470			TAILQ_INSERT_HEAD(&table->hosts, $1, entry);
471		}
472		| TIMEOUT timeout	{
473			bcopy(&$2, &table->conf.timeout,
474			    sizeof(struct timeval));
475		}
476		| CHECK ICMP		{
477			table->conf.check = CHECK_ICMP;
478		}
479		| CHECK TCP		{
480			table->conf.check = CHECK_TCP;
481		}
482		| CHECK SSL		{
483			table->conf.check = CHECK_TCP;
484			conf->flags |= F_SSL;
485			table->conf.flags |= F_SSL;
486		}
487		| CHECK http_type STRING hostname CODE NUMBER {
488			if ($2) {
489				conf->flags |= F_SSL;
490				table->conf.flags |= F_SSL;
491			}
492			table->conf.check = CHECK_HTTP_CODE;
493			if ((table->conf.retcode = $6) <= 0) {
494				yyerror("invalid HTTP code: %d", $6);
495				free($3);
496				free($4);
497				YYERROR;
498			}
499			if (asprintf(&table->sendbuf,
500			    "HEAD %s HTTP/1.0\r\n%s\r\n", $3, $4) == -1)
501				fatal("asprintf");
502			free($3);
503			free($4);
504			if (table->sendbuf == NULL)
505				fatal("out of memory");
506			table->sendbuf_len = strlen(table->sendbuf);
507		}
508		| CHECK http_type STRING hostname DIGEST STRING {
509			if ($2) {
510				conf->flags |= F_SSL;
511				table->conf.flags |= F_SSL;
512			}
513			table->conf.check = CHECK_HTTP_DIGEST;
514			if (asprintf(&table->sendbuf,
515			    "GET %s HTTP/1.0\r\n%s\r\n", $3, $4) == -1)
516				fatal("asprintf");
517			free($3);
518			free($4);
519			if (table->sendbuf == NULL)
520				fatal("out of memory");
521			table->sendbuf_len = strlen(table->sendbuf);
522			if (strlcpy(table->conf.digest, $6,
523			    sizeof(table->conf.digest)) >=
524			    sizeof(table->conf.digest)) {
525				yyerror("http digest truncated");
526				free($6);
527				YYERROR;
528			}
529			free($6);
530		}
531		| CHECK SEND sendbuf EXPECT STRING optssl {
532			table->conf.check = CHECK_SEND_EXPECT;
533			if ($6) {
534				conf->flags |= F_SSL;
535				table->conf.flags |= F_SSL;
536			}
537			if (strlcpy(table->conf.exbuf, $5,
538			    sizeof(table->conf.exbuf))
539			    >= sizeof(table->conf.exbuf)) {
540				yyerror("yyparse: expect buffer truncated");
541				free($5);
542				YYERROR;
543			}
544			translate_string(table->conf.exbuf);
545			free($5);
546		}
547		| CHECK SCRIPT STRING {
548			table->conf.check = CHECK_SCRIPT;
549			if (strlcpy(table->conf.path, $3,
550			    sizeof(table->conf.path)) >=
551			    sizeof(table->conf.path)) {
552				yyerror("script path truncated");
553				free($3);
554				YYERROR;
555			}
556			free($3);
557		}
558		| REAL port {
559			table->conf.port = $2;
560		}
561		| DEMOTE STRING	{
562			table->conf.flags |= F_DEMOTE;
563			if (strlcpy(table->conf.demote_group, $2,
564			    sizeof(table->conf.demote_group))
565			    >= sizeof(table->conf.demote_group)) {
566				yyerror("yyparse: demote group name too long");
567				free($2);
568				YYERROR;
569			}
570			free($2);
571			if (carp_demote_init(table->conf.demote_group, 1)
572			    == -1) {
573				yyerror("yyparse: error initializing group "
574				    "'%s'", table->conf.demote_group);
575				YYERROR;
576			}
577		}
578		| DISABLE			{
579			table->conf.flags |= F_DISABLE;
580		}
581		;
582
583proto		: PROTO STRING	{
584			struct protocol *p;
585
586			if (strcmp($2, "default") == 0) {
587				p = &conf->proto_default;
588			} else {
589				TAILQ_FOREACH(p, conf->protos, entry)
590					if (!strcmp(p->name, $2))
591						break;
592			}
593			if (p != NULL) {
594				yyerror("protocol %s defined twice", $2);
595				free($2);
596				YYERROR;
597			}
598			if ((p = calloc(1, sizeof (*p))) == NULL)
599				fatal("out of memory");
600
601			if (strlcpy(p->name, $2, sizeof(p->name)) >=
602			    sizeof(p->name)) {
603				yyerror("protocol name truncated");
604				YYERROR;
605			}
606			free($2);
607			p->id = last_proto_id++;
608			p->cache = RELAY_CACHESIZE;
609			p->type = RELAY_PROTO_TCP;
610			p->tcpflags = TCPFLAG_DEFAULT;
611			p->sslflags = SSLFLAG_DEFAULT;
612			p->tcpbacklog = RELAY_BACKLOG;
613			(void)strlcpy(p->sslciphers, SSLCIPHERS_DEFAULT,
614			    sizeof(p->sslciphers));
615			if (last_proto_id == INT_MAX) {
616				yyerror("too many protocols defined");
617				YYERROR;
618			}
619			RB_INIT(&p->request_tree);
620			RB_INIT(&p->response_tree);
621			proto = p;
622		} '{' optnl protopts_l '}'	{
623			conf->protocount++;
624
625			if ((proto->sslflags & SSLFLAG_VERSION) == 0) {
626				yyerror("invalid SSL protocol");
627				YYERROR;
628			}
629
630			TAILQ_INSERT_HEAD(conf->protos, proto, entry);
631		}
632		;
633
634protopts_l	: protopts_l protoptsl nl
635		| protoptsl optnl
636		;
637
638protoptsl	: SSL sslflags
639		| SSL '{' sslflags_l '}'
640		| TCP tcpflags
641		| TCP '{' tcpflags_l '}'
642		| PROTO proto_type		{ proto->type = $2; }
643		| direction protonode log	{
644			struct protonode 	*pn, *proot, pk;
645			struct proto_tree	*tree;
646
647			if ($1 == RELAY_DIR_RESPONSE)
648				tree = &proto->response_tree;
649			else
650				tree = &proto->request_tree;
651			if ((pn = calloc(1, sizeof (*pn))) == NULL)
652				fatal("out of memory");
653
654			bcopy(&node, pn, sizeof(*pn));
655			pn->key = node.key;
656			pn->value = node.value;
657			pn->type = node.type;
658			SIMPLEQ_INIT(&pn->head);
659			if ($1 == RELAY_DIR_RESPONSE)
660				pn->id = proto->response_nodes++;
661			else
662				pn->id = proto->request_nodes++;
663			if ($3)
664				pn->flags |= PNFLAG_LOG;
665			if (pn->id == INT_MAX) {
666				yyerror("too many protocol nodes defined");
667				YYERROR;
668			}
669			if ((proot =
670			    RB_INSERT(proto_tree, tree, pn)) != NULL) {
671				/*
672				 * A protocol node with the same key already
673				 * exists, append it to a queue behind the
674				 * existing node.
675				 */
676				if (SIMPLEQ_EMPTY(&proot->head))
677					SIMPLEQ_NEXT(proot, entry) = pn;
678				SIMPLEQ_INSERT_TAIL(&proot->head, pn, entry);
679			}
680
681			if (node.type == NODE_TYPE_COOKIE)
682				pk.key = "Cookie";
683			else
684				pk.key = "GET";
685			if (node.type != NODE_TYPE_HEADER) {
686				pk.type = NODE_TYPE_HEADER;
687				pn = RB_FIND(proto_tree, tree, &pk);
688				if (pn == NULL) {
689					if ((pn = (struct protonode *)
690					    calloc(1, sizeof(*pn))) == NULL)
691						fatal("out of memory");
692					pn->key = strdup(pk.key);
693					if (pn->key == NULL)
694						fatal("out of memory");
695					pn->value = NULL;
696					pn->action = NODE_ACTION_NONE;
697					pn->type = pk.type;
698					if ($1 == RELAY_DIR_RESPONSE)
699						pn->id =
700						    proto->response_nodes++;
701					else
702						pn->id = proto->request_nodes++;
703					if (pn->id == INT_MAX) {
704						yyerror("too many protocol "
705						    "nodes defined");
706						YYERROR;
707					}
708					RB_INSERT(proto_tree, tree, pn);
709				}
710				switch (node.type) {
711				case NODE_TYPE_URL:
712					pn->flags |= PNFLAG_LOOKUP_URL;
713					break;
714				case NODE_TYPE_COOKIE:
715					pn->flags |= PNFLAG_LOOKUP_COOKIE;
716					break;
717				default:
718					break;
719				}
720			}
721
722			bzero(&node, sizeof(node));
723		}
724		;
725
726direction	: /* empty */		{ $$ = RELAY_DIR_REQUEST; }
727		| REQUEST		{ $$ = RELAY_DIR_REQUEST; }
728		| RESPONSE		{ $$ = RELAY_DIR_RESPONSE; }
729		;
730
731tcpflags_l	: tcpflags comma tcpflags_l
732		| tcpflags
733		;
734
735tcpflags	: SACK 			{ proto->tcpflags |= TCPFLAG_SACK; }
736		| NO SACK		{ proto->tcpflags |= TCPFLAG_NSACK; }
737		| NODELAY		{ proto->tcpflags |= TCPFLAG_NODELAY; }
738		| NO NODELAY		{ proto->tcpflags |= TCPFLAG_NNODELAY; }
739		| BACKLOG NUMBER	{
740			if ($2 < 0 || $2 > RELAY_MAX_SESSIONS) {
741				yyerror("invalid backlog: %d", $2);
742				YYERROR;
743			}
744			proto->tcpbacklog = $2;
745		}
746		| SOCKET BUFFER NUMBER	{
747			proto->tcpflags |= TCPFLAG_BUFSIZ;
748			if ((proto->tcpbufsiz = $3) < 0) {
749				yyerror("invalid socket buffer size: %d", $3);
750				YYERROR;
751			}
752		}
753		| IP STRING NUMBER	{
754			if ($3 < 0) {
755				yyerror("invalid ttl: %d", $3);
756				free($2);
757				YYERROR;
758			}
759			if (strcasecmp("ttl", $2) == 0) {
760				proto->tcpflags |= TCPFLAG_IPTTL;
761				proto->tcpipttl = $3;
762			} else if (strcasecmp("minttl", $2) == 0) {
763				proto->tcpflags |= TCPFLAG_IPMINTTL;
764				proto->tcpipminttl = $3;
765			} else {
766				yyerror("invalid TCP/IP flag: %s", $2);
767				free($2);
768				YYERROR;
769			}
770			free($2);
771		}
772		;
773
774sslflags_l	: sslflags comma sslflags_l
775		| sslflags
776		;
777
778sslflags	: SESSION CACHE sslcache	{ proto->cache = $3; }
779		| CIPHERS STRING		{
780			if (strlcpy(proto->sslciphers, $2,
781			    sizeof(proto->sslciphers)) >=
782			    sizeof(proto->sslciphers)) {
783				yyerror("sslciphers truncated");
784				free($2);
785				YYERROR;
786			}
787			free($2);
788		}
789		| NO flag			{ proto->sslflags &= ~($2); }
790		| flag				{ proto->sslflags |= $1; }
791		;
792
793flag		: STRING			{
794			if (strcmp("sslv2", $1) == 0)
795				$$ = SSLFLAG_SSLV2;
796			else if (strcmp("sslv3", $1) == 0)
797				$$ = SSLFLAG_SSLV3;
798			else if (strcmp("tlsv1", $1) == 0)
799				$$ = SSLFLAG_TLSV1;
800			else {
801				yyerror("invalid SSL flag: %s", $1);
802				free($1);
803				YYERROR;
804			}
805			free($1);
806		}
807		;
808
809protonode	: nodetype APPEND STRING TO STRING marked	{
810			node.action = NODE_ACTION_APPEND;
811			node.key = strdup($5);
812			node.value = strdup($3);
813			if (node.key == NULL || node.value == NULL)
814				fatal("out of memory");
815			if (strchr(node.value, '$') != NULL)
816				node.flags |= PNFLAG_MACRO;
817			free($5);
818			free($3);
819		}
820		| nodetype CHANGE STRING TO STRING marked {
821			node.action = NODE_ACTION_CHANGE;
822			node.key = strdup($3);
823			node.value = strdup($5);
824			if (node.key == NULL || node.value == NULL)
825				fatal("out of memory");
826			if (strchr(node.value, '$') != NULL)
827				node.flags |= PNFLAG_MACRO;
828			free($5);
829			free($3);
830		}
831		| nodetype REMOVE STRING marked	{
832			node.action = NODE_ACTION_REMOVE;
833			node.key = strdup($3);
834			node.value = NULL;
835			if (node.key == NULL)
836				fatal("out of memory");
837			free($3);
838		}
839		| nodetype EXPECT STRING FROM STRING mark	{
840			node.action = NODE_ACTION_EXPECT;
841			node.key = strdup($5);
842			node.value = strdup($3);;
843			if (node.key == NULL || node.value == NULL)
844				fatal("out of memory");
845			free($5);
846			free($3);
847			proto->lateconnect++;
848		}
849		| nodetype FILTER STRING FROM STRING mark	{
850			node.action = NODE_ACTION_FILTER;
851			node.key = strdup($5);
852			node.value = strdup($3);;
853			if (node.key == NULL || node.value == NULL)
854				fatal("out of memory");
855			free($5);
856			free($3);
857			proto->lateconnect++;
858		}
859		| nodetype HASH STRING marked			{
860			node.action = NODE_ACTION_HASH;
861			node.key = strdup($3);
862			node.value = NULL;
863			if (node.key == NULL)
864				fatal("out of memory");
865			free($3);
866			proto->lateconnect++;
867		}
868		| nodetype LOG STRING marked			{
869			node.action = NODE_ACTION_LOG;
870			node.key = strdup($3);
871			node.value = NULL;
872			node.flags |= PNFLAG_LOG;
873			if (node.key == NULL)
874				fatal("out of memory");
875			free($3);
876		}
877		;
878
879mark		: /* empty */
880		| MARK				{ node.flags |= PNFLAG_MARK; }
881		;
882
883marked		: /* empty */
884		| MARKED			{ node.flags |= PNFLAG_MARK; }
885		;
886
887nodetype	: HEADER			{
888			node.type = NODE_TYPE_HEADER;
889		}
890		| URL				{ node.type = NODE_TYPE_URL; }
891		| COOKIE			{
892			node.type = NODE_TYPE_COOKIE;
893		}
894		| PATH				{
895				proto->flags |= F_LOOKUP_PATH;
896				node.type = NODE_TYPE_PATH;
897		}
898		;
899
900sslcache	: NUMBER			{
901			if ($1 < 0) {
902				yyerror("invalid sslcache value: %d", $1);
903				YYERROR;
904			}
905			$$ = $1;
906		}
907		| DISABLE			{ $$ = -2; }
908		;
909
910relay		: RELAY STRING	{
911			struct relay *r;
912
913			TAILQ_FOREACH(r, conf->relays, entry)
914				if (!strcmp(r->conf.name, $2))
915					break;
916			if (r != NULL) {
917				yyerror("relay %s defined twice", $2);
918				free($2);
919				YYERROR;
920			}
921			if ((r = calloc(1, sizeof (*r))) == NULL)
922				fatal("out of memory");
923
924			if (strlcpy(r->conf.name, $2, sizeof(r->conf.name)) >=
925			    sizeof(r->conf.name)) {
926				yyerror("relay name truncated");
927				YYERROR;
928			}
929			free($2);
930			r->conf.id = last_relay_id++;
931			r->conf.timeout.tv_sec = RELAY_TIMEOUT;
932			r->proto = NULL;
933			r->conf.proto = EMPTY_ID;
934			r->conf.dsttable = EMPTY_ID;
935			r->conf.dstretry = 0;
936			if (last_relay_id == INT_MAX) {
937				yyerror("too many relays defined");
938				YYERROR;
939			}
940			rlay = r;
941		} '{' optnl relayopts_l '}'	{
942			if (rlay->conf.ss.ss_family == AF_UNSPEC) {
943				yyerror("relay %s has no listener",
944				    rlay->conf.name);
945				YYERROR;
946			}
947			if ((rlay->conf.flags & F_NATLOOK) == 0 &&
948			    rlay->conf.dstss.ss_family == AF_UNSPEC &&
949			    rlay->conf.dsttable == EMPTY_ID) {
950				yyerror("relay %s has no target, service, "
951				    "or table", rlay->conf.name);
952				YYERROR;
953			}
954			if (rlay->conf.proto == EMPTY_ID) {
955				rlay->proto = &conf->proto_default;
956				rlay->conf.proto = conf->proto_default.id;
957			}
958			if (relay_load_certfiles(rlay) == -1) {
959				yyerror("cannot load certificates for relay %s",
960				    rlay->conf.name);
961				YYERROR;
962			}
963			conf->relaycount++;
964			SPLAY_INIT(&rlay->sessions);
965			TAILQ_INSERT_HEAD(conf->relays, rlay, entry);
966		}
967		;
968
969relayopts_l	: relayopts_l relayoptsl nl
970		| relayoptsl optnl
971		;
972
973relayoptsl	: LISTEN ON STRING port optssl {
974			struct addresslist 	 al;
975			struct address		*h;
976
977			if (rlay->conf.ss.ss_family != AF_UNSPEC) {
978				yyerror("relay %s listener already specified",
979				    rlay->conf.name);
980				YYERROR;
981			}
982
983			TAILQ_INIT(&al);
984			if (host($3, &al, 1, $4, NULL) <= 0) {
985				yyerror("invalid listen ip: %s", $3);
986				free($3);
987				YYERROR;
988			}
989			free($3);
990			h = TAILQ_FIRST(&al);
991			bcopy(&h->ss, &rlay->conf.ss, sizeof(rlay->conf.ss));
992			rlay->conf.port = h->port;
993			if ($5) {
994				rlay->conf.flags |= F_SSL;
995				conf->flags |= F_SSL;
996			}
997		}
998		| FORWARD TO STRING port retry {
999			struct addresslist 	 al;
1000			struct address		*h;
1001
1002			if (rlay->conf.dstss.ss_family != AF_UNSPEC) {
1003				yyerror("relay %s target or service already "
1004				    "specified", rlay->conf.name);
1005				free($3);
1006				YYERROR;
1007			}
1008
1009			TAILQ_INIT(&al);
1010			if (host($3, &al, 1, $4, NULL) <= 0) {
1011				yyerror("invalid listen ip: %s", $3);
1012				free($3);
1013				YYERROR;
1014			}
1015			free($3);
1016			h = TAILQ_FIRST(&al);
1017			bcopy(&h->ss, &rlay->conf.dstss,
1018			    sizeof(rlay->conf.dstss));
1019			rlay->conf.dstport = h->port;
1020			rlay->conf.dstretry = $5;
1021		}
1022		| SERVICE STRING retry {
1023			struct service	*svc;
1024			struct address	*h;
1025
1026			if (rlay->conf.dstss.ss_family != AF_UNSPEC) {
1027				yyerror("relay %s target or service already "
1028				    "specified", rlay->conf.name);
1029				free($2);
1030				YYERROR;
1031			}
1032
1033			if ((svc = service_findbyname(conf, $2)) == NULL) {
1034				yyerror("relay %s for unknown service %s",
1035				    rlay->conf.name, $2);
1036				free($2);
1037				YYERROR;
1038			}
1039			free($2);
1040			h = TAILQ_FIRST(&svc->virts);
1041			bcopy(&h->ss, &rlay->conf.dstss,
1042			    sizeof(rlay->conf.dstss));
1043			rlay->conf.dstport = h->port;
1044			rlay->conf.dstretry = $3;
1045		}
1046		| TABLE STRING dstport dstmode docheck {
1047			struct table	*tb;
1048
1049			rlay->conf.dstport = $3;
1050			if (rlay->conf.dstport == 0)
1051				rlay->conf.dstport = rlay->conf.port;
1052
1053			if ((tb = table_inherit($2, rlay->conf.dstport)) ==
1054			    NULL) {
1055				free($2);
1056				YYERROR;
1057			}
1058			free($2);
1059			rlay->conf.dsttable = tb->conf.id;
1060			rlay->dsttable = tb;
1061			rlay->conf.dstport = tb->conf.port;
1062			rlay->conf.dstmode = $4;
1063			rlay->conf.dstcheck = $5;
1064			rlay->dsttable->conf.flags |= F_USED;
1065		}
1066		| PROTO STRING {
1067			struct protocol *p;
1068
1069			TAILQ_FOREACH(p, conf->protos, entry)
1070				if (!strcmp(p->name, $2))
1071					break;
1072			if (p == NULL) {
1073				yyerror("no such protocol: %s", $2);
1074				free($2);
1075				YYERROR;
1076			}
1077			p->flags |= F_USED;
1078			rlay->conf.proto = p->id;
1079			rlay->proto = p;
1080			free($2);
1081		}
1082		| NAT LOOKUP retry	{
1083			rlay->conf.flags |= F_NATLOOK;
1084			rlay->conf.dstretry = $3;
1085		}
1086		| TIMEOUT NUMBER	{
1087			if ((rlay->conf.timeout.tv_sec = $2) < 0) {
1088				yyerror("invalid timeout: %d", $2);
1089				YYERROR;
1090			}
1091		}
1092		| DISABLE		{ rlay->conf.flags |= F_DISABLE; }
1093		;
1094
1095dstmode		: /* empty */		{ $$ = RELAY_DSTMODE_DEFAULT; }
1096		| LOADBALANCE		{ $$ = RELAY_DSTMODE_LOADBALANCE; }
1097		| ROUNDROBIN		{ $$ = RELAY_DSTMODE_ROUNDROBIN; }
1098		| HASH			{ $$ = RELAY_DSTMODE_HASH; }
1099		;
1100
1101docheck		: /* empty */		{ $$ = 1; }
1102		| NO CHECK		{ $$ = 0; }
1103		;
1104
1105interface	: /*empty*/		{ $$ = NULL; }
1106		| INTERFACE STRING	{ $$ = $2; }
1107		;
1108
1109dstport		: /* empty */		{ $$ = 0; }
1110		| port			{ $$ = $1; }
1111		;
1112
1113host		: HOST STRING retry {
1114			struct address *a;
1115			struct addresslist al;
1116
1117			if (($$ = calloc(1, sizeof(*($$)))) == NULL)
1118				fatal("out of memory");
1119
1120			TAILQ_INIT(&al);
1121			if (host($2, &al, 1, 0, NULL) <= 0) {
1122				yyerror("invalid host %s", $2);
1123				free($2);
1124				free($$);
1125				YYERROR;
1126			}
1127			a = TAILQ_FIRST(&al);
1128			memcpy(&$$->conf.ss, &a->ss, sizeof($$->conf.ss));
1129			free(a);
1130
1131			if (strlcpy($$->conf.name, $2, sizeof($$->conf.name)) >=
1132			    sizeof($$->conf.name)) {
1133				yyerror("host name truncated");
1134				free($2);
1135				free($$);
1136				YYERROR;
1137			}
1138			free($2);
1139			$$->conf.id = last_host_id++;
1140			$$->conf.retry = $3;
1141			if (last_host_id == INT_MAX) {
1142				yyerror("too many hosts defined");
1143				free($$);
1144				YYERROR;
1145			}
1146		}
1147		;
1148
1149retry		: /* nothing */		{ $$ = 0; }
1150		| RETRY NUMBER		{
1151			if (($$ = $2) < 0) {
1152				yyerror("invalid retry value: %d\n", $2);
1153				YYERROR;
1154			}
1155		}
1156		;
1157
1158timeout		: NUMBER
1159		{
1160			if ($1 < 0) {
1161				yyerror("invalid timeout: %d\n", $1);
1162				YYERROR;
1163			}
1164			$$.tv_sec = $1 / 1000;
1165			$$.tv_usec = ($1 % 1000) * 1000;
1166		}
1167		;
1168
1169log		: /* empty */		{ $$ = 0; }
1170		| LOG			{ $$ = 1; }
1171		;
1172
1173comma		: ','
1174		| /* empty */
1175		;
1176
1177optnl		: '\n' optnl
1178		|
1179		;
1180
1181nl		: '\n' optnl
1182		;
1183
1184%%
1185
1186struct keywords {
1187	const char	*k_name;
1188	int		 k_val;
1189};
1190
1191int
1192yyerror(const char *fmt, ...)
1193{
1194	va_list		 ap;
1195
1196	file->errors++;
1197	va_start(ap, fmt);
1198	fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
1199	vfprintf(stderr, fmt, ap);
1200	fprintf(stderr, "\n");
1201	va_end(ap);
1202	return (0);
1203}
1204
1205int
1206kw_cmp(const void *k, const void *e)
1207{
1208	return (strcmp(k, ((const struct keywords *)e)->k_name));
1209}
1210
1211int
1212lookup(char *s)
1213{
1214	/* this has to be sorted always */
1215	static const struct keywords keywords[] = {
1216		{ "all",		ALL },
1217		{ "append",		APPEND },
1218		{ "backlog",		BACKLOG },
1219		{ "backup",		BACKUP },
1220		{ "buffer",		BUFFER },
1221		{ "cache",		CACHE },
1222		{ "change",		CHANGE },
1223		{ "check",		CHECK },
1224		{ "ciphers",		CIPHERS },
1225		{ "code",		CODE },
1226		{ "cookie",		COOKIE },
1227		{ "demote",		DEMOTE },
1228		{ "digest",		DIGEST },
1229		{ "disable",		DISABLE },
1230		{ "expect",		EXPECT },
1231		{ "external",		EXTERNAL },
1232		{ "filter",		FILTER },
1233		{ "forward",		FORWARD },
1234		{ "from",		FROM },
1235		{ "hash",		HASH },
1236		{ "header",		HEADER },
1237		{ "host",		HOST },
1238		{ "icmp",		ICMP },
1239		{ "include",		INCLUDE },
1240		{ "interface",		INTERFACE },
1241		{ "interval",		INTERVAL },
1242		{ "ip",			IP },
1243		{ "listen",		LISTEN },
1244		{ "loadbalance",	LOADBALANCE },
1245		{ "log",		LOG },
1246		{ "lookup",		LOOKUP },
1247		{ "mark",		MARK },
1248		{ "marked",		MARKED },
1249		{ "nat",		NAT },
1250		{ "no",			NO },
1251		{ "nodelay",		NODELAY },
1252		{ "nothing",		NOTHING },
1253		{ "on",			ON },
1254		{ "path",		PATH },
1255		{ "port",		PORT },
1256		{ "prefork",		PREFORK },
1257		{ "protocol",		PROTO },
1258		{ "real",		REAL },
1259		{ "relay",		RELAY },
1260		{ "remove",		REMOVE },
1261		{ "request",		REQUEST },
1262		{ "response",		RESPONSE },
1263		{ "retry",		RETRY },
1264		{ "roundrobin",		ROUNDROBIN },
1265		{ "sack",		SACK },
1266		{ "script",		SCRIPT },
1267		{ "send",		SEND },
1268		{ "service",		SERVICE },
1269		{ "session",		SESSION },
1270		{ "socket",		SOCKET },
1271		{ "ssl",		SSL },
1272		{ "sticky-address",	STICKYADDR },
1273		{ "table",		TABLE },
1274		{ "tag",		TAG },
1275		{ "tcp",		TCP },
1276		{ "timeout",		TIMEOUT },
1277		{ "to",			TO },
1278		{ "updates",		UPDATES },
1279		{ "url",		URL },
1280		{ "virtual",		VIRTUAL }
1281	};
1282	const struct keywords	*p;
1283
1284	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
1285	    sizeof(keywords[0]), kw_cmp);
1286
1287	if (p)
1288		return (p->k_val);
1289	else
1290		return (STRING);
1291}
1292
1293#define MAXPUSHBACK	128
1294
1295char	*parsebuf;
1296int	 parseindex;
1297char	 pushback_buffer[MAXPUSHBACK];
1298int	 pushback_index = 0;
1299
1300int
1301lgetc(int quotec)
1302{
1303	int		c, next;
1304
1305	if (parsebuf) {
1306		/* Read character from the parsebuffer instead of input. */
1307		if (parseindex >= 0) {
1308			c = parsebuf[parseindex++];
1309			if (c != '\0')
1310				return (c);
1311			parsebuf = NULL;
1312		} else
1313			parseindex++;
1314	}
1315
1316	if (pushback_index)
1317		return (pushback_buffer[--pushback_index]);
1318
1319	if (quotec) {
1320		if ((c = getc(file->stream)) == EOF) {
1321			yyerror("reached end of file while parsing quoted string");
1322			if (popfile() == EOF)
1323				return (EOF);
1324			return (quotec);
1325		}
1326		return (c);
1327	}
1328
1329	while ((c = getc(file->stream)) == '\\') {
1330		next = getc(file->stream);
1331		if (next != '\n') {
1332			c = next;
1333			break;
1334		}
1335		yylval.lineno = file->lineno;
1336		file->lineno++;
1337	}
1338
1339	while (c == EOF) {
1340		if (popfile() == EOF)
1341			return (EOF);
1342		c = getc(file->stream);
1343	}
1344	return (c);
1345}
1346
1347int
1348lungetc(int c)
1349{
1350	if (c == EOF)
1351		return (EOF);
1352	if (parsebuf) {
1353		parseindex--;
1354		if (parseindex >= 0)
1355			return (c);
1356	}
1357	if (pushback_index < MAXPUSHBACK-1)
1358		return (pushback_buffer[pushback_index++] = c);
1359	else
1360		return (EOF);
1361}
1362
1363int
1364findeol(void)
1365{
1366	int	c;
1367
1368	parsebuf = NULL;
1369	pushback_index = 0;
1370
1371	/* skip to either EOF or the first real EOL */
1372	while (1) {
1373		c = lgetc(0);
1374		if (c == '\n') {
1375			file->lineno++;
1376			break;
1377		}
1378		if (c == EOF)
1379			break;
1380	}
1381	return (ERROR);
1382}
1383
1384int
1385yylex(void)
1386{
1387	char	 buf[8096];
1388	char	*p, *val;
1389	int	 quotec, next, c;
1390	int	 token;
1391
1392top:
1393	p = buf;
1394	while ((c = lgetc(0)) == ' ' || c == '\t')
1395		; /* nothing */
1396
1397	yylval.lineno = file->lineno;
1398	if (c == '#')
1399		while ((c = lgetc(0)) != '\n' && c != EOF)
1400			; /* nothing */
1401	if (c == '$' && parsebuf == NULL) {
1402		while (1) {
1403			if ((c = lgetc(0)) == EOF)
1404				return (0);
1405
1406			if (p + 1 >= buf + sizeof(buf) - 1) {
1407				yyerror("string too long");
1408				return (findeol());
1409			}
1410			if (isalnum(c) || c == '_') {
1411				*p++ = (char)c;
1412				continue;
1413			}
1414			*p = '\0';
1415			lungetc(c);
1416			break;
1417		}
1418		val = symget(buf);
1419		if (val == NULL) {
1420			yyerror("macro '%s' not defined", buf);
1421			return (findeol());
1422		}
1423		parsebuf = val;
1424		parseindex = 0;
1425		goto top;
1426	}
1427
1428	switch (c) {
1429	case '\'':
1430	case '"':
1431		quotec = c;
1432		while (1) {
1433			if ((c = lgetc(quotec)) == EOF)
1434				return (0);
1435			if (c == '\n') {
1436				file->lineno++;
1437				continue;
1438			} else if (c == '\\') {
1439				if ((next = lgetc(quotec)) == EOF)
1440					return (0);
1441				if (next == quotec || c == ' ' || c == '\t')
1442					c = next;
1443				else if (next == '\n')
1444					continue;
1445				else
1446					lungetc(next);
1447			} else if (c == quotec) {
1448				*p = '\0';
1449				break;
1450			}
1451			if (p + 1 >= buf + sizeof(buf) - 1) {
1452				yyerror("string too long");
1453				return (findeol());
1454			}
1455			*p++ = (char)c;
1456		}
1457		yylval.v.string = strdup(buf);
1458		if (yylval.v.string == NULL)
1459			err(1, "yylex: strdup");
1460		return (STRING);
1461	}
1462
1463#define allowed_to_end_number(x) \
1464	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
1465
1466	if (c == '-' || isdigit(c)) {
1467		do {
1468			*p++ = c;
1469			if ((unsigned)(p-buf) >= sizeof(buf)) {
1470				yyerror("string too long");
1471				return (findeol());
1472			}
1473		} while ((c = lgetc(0)) != EOF && isdigit(c));
1474		lungetc(c);
1475		if (p == buf + 1 && buf[0] == '-')
1476			goto nodigits;
1477		if (c == EOF || allowed_to_end_number(c)) {
1478			const char *errstr = NULL;
1479
1480			*p = '\0';
1481			yylval.v.number = strtonum(buf, LLONG_MIN,
1482			    LLONG_MAX, &errstr);
1483			if (errstr) {
1484				yyerror("\"%s\" invalid number: %s",
1485				    buf, errstr);
1486				return (findeol());
1487			}
1488			return (NUMBER);
1489		} else {
1490nodigits:
1491			while (p > buf + 1)
1492				lungetc(*--p);
1493			c = *--p;
1494			if (c == '-')
1495				return (c);
1496		}
1497	}
1498
1499#define allowed_in_string(x) \
1500	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
1501	x != '{' && x != '}' && \
1502	x != '!' && x != '=' && x != '#' && \
1503	x != ','))
1504
1505	if (isalnum(c) || c == ':' || c == '_') {
1506		do {
1507			*p++ = c;
1508			if ((unsigned)(p-buf) >= sizeof(buf)) {
1509				yyerror("string too long");
1510				return (findeol());
1511			}
1512		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
1513		lungetc(c);
1514		*p = '\0';
1515		if ((token = lookup(buf)) == STRING)
1516			if ((yylval.v.string = strdup(buf)) == NULL)
1517				err(1, "yylex: strdup");
1518		return (token);
1519	}
1520	if (c == '\n') {
1521		yylval.lineno = file->lineno;
1522		file->lineno++;
1523	}
1524	if (c == EOF)
1525		return (0);
1526	return (c);
1527}
1528
1529int
1530check_file_secrecy(int fd, const char *fname)
1531{
1532	struct stat	st;
1533
1534	if (fstat(fd, &st)) {
1535		log_warn("cannot stat %s", fname);
1536		return (-1);
1537	}
1538	if (st.st_uid != 0 && st.st_uid != getuid()) {
1539		log_warnx("%s: owner not root or current user", fname);
1540		return (-1);
1541	}
1542	if (st.st_mode & (S_IRWXG | S_IRWXO)) {
1543		log_warnx("%s: group/world readable/writeable", fname);
1544		return (-1);
1545	}
1546	return (0);
1547}
1548
1549struct file *
1550pushfile(const char *name, int secret)
1551{
1552	struct file	*nfile;
1553
1554	if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
1555	    (nfile->name = strdup(name)) == NULL) {
1556		log_warn("malloc");
1557		return (NULL);
1558	}
1559	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
1560		log_warn("%s", nfile->name);
1561		free(nfile->name);
1562		free(nfile);
1563		return (NULL);
1564	} else if (secret &&
1565	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
1566		fclose(nfile->stream);
1567		free(nfile->name);
1568		free(nfile);
1569		return (NULL);
1570	}
1571	nfile->lineno = 1;
1572	TAILQ_INSERT_TAIL(&files, nfile, entry);
1573	return (nfile);
1574}
1575
1576int
1577popfile(void)
1578{
1579	struct file	*prev;
1580
1581	if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
1582		prev->errors += file->errors;
1583		TAILQ_REMOVE(&files, file, entry);
1584		fclose(file->stream);
1585		free(file->name);
1586		free(file);
1587		file = prev;
1588		return (0);
1589	}
1590	return (EOF);
1591}
1592
1593struct hoststated *
1594parse_config(const char *filename, int opts)
1595{
1596	struct sym	*sym, *next;
1597	struct table	*nexttb;
1598	struct host	*h;
1599
1600	if ((conf = calloc(1, sizeof(*conf))) == NULL ||
1601	    (conf->tables = calloc(1, sizeof(*conf->tables))) == NULL ||
1602	    (conf->relays = calloc(1, sizeof(*conf->relays))) == NULL ||
1603	    (conf->protos = calloc(1, sizeof(*conf->protos))) == NULL ||
1604	    (conf->services = calloc(1, sizeof(*conf->services))) == NULL) {
1605		log_warn("cannot allocate memory");
1606		return (NULL);
1607	}
1608
1609	errors = 0;
1610	last_host_id = last_table_id = last_service_id = last_proto_id =
1611	    last_relay_id = 0;
1612
1613	service = NULL;
1614	table = NULL;
1615	rlay = NULL;
1616	proto = NULL;
1617
1618	TAILQ_INIT(conf->services);
1619	TAILQ_INIT(conf->tables);
1620	TAILQ_INIT(conf->protos);
1621	TAILQ_INIT(conf->relays);
1622
1623	memset(&conf->empty_table, 0, sizeof(conf->empty_table));
1624	conf->empty_table.conf.id = EMPTY_TABLE;
1625	conf->empty_table.conf.flags |= F_DISABLE;
1626	(void)strlcpy(conf->empty_table.conf.name, "empty",
1627	    sizeof(conf->empty_table.conf.name));
1628
1629	bzero(&conf->proto_default, sizeof(conf->proto_default));
1630	conf->proto_default.flags = F_USED;
1631	conf->proto_default.cache = RELAY_CACHESIZE;
1632	conf->proto_default.type = RELAY_PROTO_TCP;
1633	(void)strlcpy(conf->proto_default.name, "default",
1634	    sizeof(conf->proto_default.name));
1635	RB_INIT(&conf->proto_default.request_tree);
1636	RB_INIT(&conf->proto_default.response_tree);
1637
1638	conf->timeout.tv_sec = CHECK_TIMEOUT / 1000;
1639	conf->timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000;
1640	conf->interval.tv_sec = CHECK_INTERVAL;
1641	conf->interval.tv_usec = 0;
1642	conf->prefork_relay = RELAY_NUMPROC;
1643	conf->statinterval.tv_sec = RELAY_STATINTERVAL;
1644	conf->opts = opts;
1645	conf->confpath = filename;
1646
1647	if ((file = pushfile(filename, 0)) == NULL) {
1648		free(conf);
1649		return (NULL);
1650	}
1651	setservent(1);
1652
1653	yyparse();
1654	errors = file->errors;
1655	popfile();
1656
1657	endservent();
1658
1659	/* Free macros and check which have not been used. */
1660	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
1661		next = TAILQ_NEXT(sym, entry);
1662		if ((conf->opts & HOSTSTATED_OPT_VERBOSE) && !sym->used)
1663			fprintf(stderr, "warning: macro '%s' not "
1664			    "used\n", sym->nam);
1665		if (!sym->persist) {
1666			free(sym->nam);
1667			free(sym->val);
1668			TAILQ_REMOVE(&symhead, sym, entry);
1669			free(sym);
1670		}
1671	}
1672
1673	if (TAILQ_EMPTY(conf->services) && TAILQ_EMPTY(conf->relays)) {
1674		log_warnx("no services, nothing to do");
1675		errors++;
1676	}
1677
1678	if (TAILQ_EMPTY(conf->relays))
1679		conf->prefork_relay = 0;
1680
1681	if (timercmp(&conf->timeout, &conf->interval, >=)) {
1682		log_warnx("global timeout exceeds interval");
1683		errors++;
1684	}
1685
1686	/* Verify that every table is used */
1687	for (table = TAILQ_FIRST(conf->tables); table != NULL;
1688	     table = nexttb) {
1689		nexttb = TAILQ_NEXT(table, entry);
1690		if (table->conf.port == 0) {
1691			TAILQ_REMOVE(conf->tables, table, entry);
1692			while ((h = TAILQ_FIRST(&table->hosts)) != NULL) {
1693				TAILQ_REMOVE(&table->hosts, h, entry);
1694				free(h);
1695			}
1696			if (table->sendbuf != NULL)
1697				free(table->sendbuf);
1698			free(table);
1699			continue;
1700		}
1701		if (!(table->conf.flags & F_USED)) {
1702			log_warnx("unused table: %s", table->conf.name);
1703			errors++;
1704		}
1705		if (timercmp(&table->conf.timeout, &conf->interval, >=)) {
1706			log_warnx("table timeout exceeds interval: %s",
1707			    table->conf.name);
1708			errors++;
1709		}
1710	}
1711
1712	/* Verify that every non-default protocol is used */
1713	TAILQ_FOREACH(proto, conf->protos, entry) {
1714		if (!(proto->flags & F_USED)) {
1715			log_warnx("unused protocol: %s", proto->name);
1716		}
1717	}
1718
1719	if (errors) {
1720		free(conf);
1721		return (NULL);
1722	}
1723
1724	return (conf);
1725}
1726
1727int
1728symset(const char *nam, const char *val, int persist)
1729{
1730	struct sym	*sym;
1731
1732	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
1733	    sym = TAILQ_NEXT(sym, entry))
1734		;	/* nothing */
1735
1736	if (sym != NULL) {
1737		if (sym->persist == 1)
1738			return (0);
1739		else {
1740			free(sym->nam);
1741			free(sym->val);
1742			TAILQ_REMOVE(&symhead, sym, entry);
1743			free(sym);
1744		}
1745	}
1746	if ((sym = calloc(1, sizeof(*sym))) == NULL)
1747		return (-1);
1748
1749	sym->nam = strdup(nam);
1750	if (sym->nam == NULL) {
1751		free(sym);
1752		return (-1);
1753	}
1754	sym->val = strdup(val);
1755	if (sym->val == NULL) {
1756		free(sym->nam);
1757		free(sym);
1758		return (-1);
1759	}
1760	sym->used = 0;
1761	sym->persist = persist;
1762	TAILQ_INSERT_TAIL(&symhead, sym, entry);
1763	return (0);
1764}
1765
1766int
1767cmdline_symset(char *s)
1768{
1769	char	*sym, *val;
1770	int	ret;
1771	size_t	len;
1772
1773	if ((val = strrchr(s, '=')) == NULL)
1774		return (-1);
1775
1776	len = strlen(s) - strlen(val) + 1;
1777	if ((sym = malloc(len)) == NULL)
1778		errx(1, "cmdline_symset: malloc");
1779
1780	(void)strlcpy(sym, s, len);
1781
1782	ret = symset(sym, val + 1, 1);
1783	free(sym);
1784
1785	return (ret);
1786}
1787
1788char *
1789symget(const char *nam)
1790{
1791	struct sym	*sym;
1792
1793	TAILQ_FOREACH(sym, &symhead, entry)
1794		if (strcmp(nam, sym->nam) == 0) {
1795			sym->used = 1;
1796			return (sym->val);
1797		}
1798	return (NULL);
1799}
1800
1801struct address *
1802host_v4(const char *s)
1803{
1804	struct in_addr		 ina;
1805	struct sockaddr_in	*sain;
1806	struct address		*h;
1807
1808	bzero(&ina, sizeof(ina));
1809	if (inet_pton(AF_INET, s, &ina) != 1)
1810		return (NULL);
1811
1812	if ((h = calloc(1, sizeof(*h))) == NULL)
1813		fatal(NULL);
1814	sain = (struct sockaddr_in *)&h->ss;
1815	sain->sin_len = sizeof(struct sockaddr_in);
1816	sain->sin_family = AF_INET;
1817	sain->sin_addr.s_addr = ina.s_addr;
1818
1819	return (h);
1820}
1821
1822struct address *
1823host_v6(const char *s)
1824{
1825	struct in6_addr		 ina6;
1826	struct sockaddr_in6	*sin6;
1827	struct address		*h;
1828
1829	bzero(&ina6, sizeof(ina6));
1830	if (inet_pton(AF_INET6, s, &ina6) != 1)
1831		return (NULL);
1832
1833	if ((h = calloc(1, sizeof(*h))) == NULL)
1834		fatal(NULL);
1835	sin6 = (struct sockaddr_in6 *)&h->ss;
1836	sin6->sin6_len = sizeof(struct sockaddr_in6);
1837	sin6->sin6_family = AF_INET6;
1838	memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6));
1839
1840	return (h);
1841}
1842
1843int
1844host_dns(const char *s, struct addresslist *al, int max,
1845	 in_port_t port, const char *ifname)
1846{
1847	struct addrinfo		 hints, *res0, *res;
1848	int			 error, cnt = 0;
1849	struct sockaddr_in	*sain;
1850	struct sockaddr_in6	*sin6;
1851	struct address		*h;
1852
1853	bzero(&hints, sizeof(hints));
1854	hints.ai_family = PF_UNSPEC;
1855	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
1856	error = getaddrinfo(s, NULL, &hints, &res0);
1857	if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
1858		return (0);
1859	if (error) {
1860		log_warnx("host_dns: could not parse \"%s\": %s", s,
1861		    gai_strerror(error));
1862		return (-1);
1863	}
1864
1865	for (res = res0; res && cnt < max; res = res->ai_next) {
1866		if (res->ai_family != AF_INET &&
1867		    res->ai_family != AF_INET6)
1868			continue;
1869		if ((h = calloc(1, sizeof(*h))) == NULL)
1870			fatal(NULL);
1871
1872		h->port = port;
1873		if (ifname != NULL) {
1874			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
1875			    sizeof(h->ifname))
1876				log_warnx("host_dns: interface name truncated");
1877			return (-1);
1878		}
1879		h->ss.ss_family = res->ai_family;
1880		if (res->ai_family == AF_INET) {
1881			sain = (struct sockaddr_in *)&h->ss;
1882			sain->sin_len = sizeof(struct sockaddr_in);
1883			sain->sin_addr.s_addr = ((struct sockaddr_in *)
1884			    res->ai_addr)->sin_addr.s_addr;
1885		} else {
1886			sin6 = (struct sockaddr_in6 *)&h->ss;
1887			sin6->sin6_len = sizeof(struct sockaddr_in6);
1888			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
1889			    res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
1890		}
1891
1892		TAILQ_INSERT_HEAD(al, h, entry);
1893		cnt++;
1894	}
1895	if (cnt == max && res) {
1896		log_warnx("host_dns: %s resolves to more than %d hosts",
1897		    s, max);
1898	}
1899	freeaddrinfo(res0);
1900	return (cnt);
1901}
1902
1903int
1904host(const char *s, struct addresslist *al, int max,
1905    in_port_t port, const char *ifname)
1906{
1907	struct address *h;
1908
1909	h = host_v4(s);
1910
1911	/* IPv6 address? */
1912	if (h == NULL)
1913		h = host_v6(s);
1914
1915	if (h != NULL) {
1916		h->port = port;
1917		if (ifname != NULL) {
1918			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
1919			    sizeof(h->ifname)) {
1920				log_warnx("host: interface name truncated");
1921				return (-1);
1922			}
1923		}
1924
1925		TAILQ_INSERT_HEAD(al, h, entry);
1926		return (1);
1927	}
1928
1929	return (host_dns(s, al, max, port, ifname));
1930}
1931
1932struct table *
1933table_inherit(const char *name, in_port_t port)
1934{
1935	char		pname[TABLE_NAME_SIZE + 6];
1936	struct host	*h, *dsth;
1937	struct table	*dsttb, *tb;
1938
1939	/* Get the table or table template */
1940	if ((dsttb = table_findbyname(conf, name)) == NULL) {
1941		yyerror("unknown table or template %s", name);
1942		return (NULL);
1943	}
1944	if (dsttb->conf.port != 0)
1945		return (dsttb);
1946
1947	if (port == 0) {
1948		yyerror("invalid port");
1949		return (NULL);
1950	}
1951
1952	/* Check if a matching table already exists */
1953	snprintf(pname, sizeof(pname), "%s:%u", name, ntohs(port));
1954	if ((tb = table_findbyname(conf, pname)) != NULL) {
1955		if (tb->conf.port == 0) {
1956			yyerror("invalid table");
1957			return (NULL);
1958		}
1959		return (tb);
1960	}
1961
1962	/* Create a new table */
1963	if ((tb = calloc(1, sizeof (*tb))) == NULL)
1964		fatal("out of memory");
1965	bcopy(dsttb, tb, sizeof(*tb));
1966	if (strlcpy(tb->conf.name, pname, sizeof(tb->conf.name))
1967	    >= sizeof(tb->conf.name)) {
1968		yyerror("table name truncated");
1969		return (NULL);
1970	}
1971	if (dsttb->sendbuf != NULL &&
1972	    (tb->sendbuf = strdup(dsttb->sendbuf)) == NULL)
1973		fatal("out of memory");
1974	tb->conf.port = port;
1975	tb->conf.id = last_table_id++;
1976	if (last_table_id == INT_MAX) {
1977		yyerror("too many tables defined");
1978		return (NULL);
1979	}
1980
1981	/* Copy the associated hosts */
1982	bzero(&tb->hosts, sizeof(tb->hosts));
1983	TAILQ_FOREACH(dsth, &dsttb->hosts, entry) {
1984		if ((h = (struct host *)
1985		    calloc(1, sizeof (*h))) == NULL)
1986			fatal("out of memory");
1987		bcopy(dsth, h, sizeof(*h));
1988		h->conf.id = last_host_id++;
1989		if (last_host_id == INT_MAX) {
1990			yyerror("too many hosts defined");
1991			return (NULL);
1992		}
1993		h->conf.tableid = tb->conf.id;
1994		h->tablename = tb->conf.name;
1995		TAILQ_INSERT_HEAD(&tb->hosts, h, entry);
1996	}
1997
1998	conf->tablecount++;
1999	TAILQ_INSERT_HEAD(conf->tables, tb, entry);
2000
2001	return (tb);
2002}
2003