parse.y revision 1.81
1/*	$OpenBSD: parse.y,v 1.81 2007/11/19 14:41:05 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, 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			pn = RB_FIND(proto_tree, tree, &node);
652			if (pn != NULL) {
653				yyerror("protocol node %s defined twice",
654				    node.key);
655				YYERROR;
656			}
657			if ((pn = calloc(1, sizeof (*pn))) == NULL)
658				fatal("out of memory");
659
660			bcopy(&node, pn, sizeof(*pn));
661			pn->key = node.key;
662			pn->value = node.value;
663			pn->type = node.type;
664			if ($1 == RELAY_DIR_RESPONSE)
665				pn->id = proto->response_nodes++;
666			else
667				pn->id = proto->request_nodes++;
668			if ($3)
669				pn->flags |= PNFLAG_LOG;
670			if (pn->id == INT_MAX) {
671				yyerror("too many protocol nodes defined");
672				YYERROR;
673			}
674			RB_INSERT(proto_tree, tree, pn);
675
676			if (node.type == NODE_TYPE_COOKIE)
677				pk.key = "Cookie";
678			else
679				pk.key = "GET";
680			if (node.type != NODE_TYPE_HEADER) {
681				pk.type = NODE_TYPE_HEADER;
682				pn = RB_FIND(proto_tree, tree, &pk);
683				if (pn == NULL) {
684					if ((pn = (struct protonode *)
685					    calloc(1, sizeof(*pn))) == NULL)
686						fatal("out of memory");
687					pn->key = strdup(pk.key);
688					if (pn->key == NULL)
689						fatal("out of memory");
690					pn->value = NULL;
691					pn->action = NODE_ACTION_NONE;
692					pn->type = pk.type;
693					if ($1 == RELAY_DIR_RESPONSE)
694						pn->id =
695						    proto->response_nodes++;
696					else
697						pn->id = proto->request_nodes++;
698					if (pn->id == INT_MAX) {
699						yyerror("too many protocol "
700						    "nodes defined");
701						YYERROR;
702					}
703					RB_INSERT(proto_tree, tree, pn);
704				}
705				switch (node.type) {
706				case NODE_TYPE_URL:
707					pn->flags |= PNFLAG_LOOKUP_URL;
708					break;
709				case NODE_TYPE_COOKIE:
710					pn->flags |= PNFLAG_LOOKUP_COOKIE;
711					break;
712				default:
713					break;
714				}
715			}
716
717			bzero(&node, sizeof(node));
718		}
719		;
720
721direction	: /* empty */		{ $$ = RELAY_DIR_REQUEST; }
722		| REQUEST		{ $$ = RELAY_DIR_REQUEST; }
723		| RESPONSE		{ $$ = RELAY_DIR_RESPONSE; }
724		;
725
726tcpflags_l	: tcpflags comma tcpflags_l
727		| tcpflags
728		;
729
730tcpflags	: SACK 			{ proto->tcpflags |= TCPFLAG_SACK; }
731		| NO SACK		{ proto->tcpflags |= TCPFLAG_NSACK; }
732		| NODELAY		{ proto->tcpflags |= TCPFLAG_NODELAY; }
733		| NO NODELAY		{ proto->tcpflags |= TCPFLAG_NNODELAY; }
734		| BACKLOG NUMBER	{
735			if ($2 < 0 || $2 > RELAY_MAX_SESSIONS) {
736				yyerror("invalid backlog: %d", $2);
737				YYERROR;
738			}
739			proto->tcpbacklog = $2;
740		}
741		| SOCKET BUFFER NUMBER	{
742			proto->tcpflags |= TCPFLAG_BUFSIZ;
743			if ((proto->tcpbufsiz = $3) < 0) {
744				yyerror("invalid socket buffer size: %d", $3);
745				YYERROR;
746			}
747		}
748		| IP STRING NUMBER	{
749			if ($3 < 0) {
750				yyerror("invalid ttl: %d", $3);
751				free($2);
752				YYERROR;
753			}
754			if (strcasecmp("ttl", $2) == 0) {
755				proto->tcpflags |= TCPFLAG_IPTTL;
756				proto->tcpipttl = $3;
757			} else if (strcasecmp("minttl", $2) == 0) {
758				proto->tcpflags |= TCPFLAG_IPMINTTL;
759				proto->tcpipminttl = $3;
760			} else {
761				yyerror("invalid TCP/IP flag: %s", $2);
762				free($2);
763				YYERROR;
764			}
765			free($2);
766		}
767		;
768
769sslflags_l	: sslflags comma sslflags_l
770		| sslflags
771		;
772
773sslflags	: SESSION CACHE sslcache	{ proto->cache = $3; }
774		| CIPHERS STRING		{
775			if (strlcpy(proto->sslciphers, $2,
776			    sizeof(proto->sslciphers)) >=
777			    sizeof(proto->sslciphers)) {
778				yyerror("sslciphers truncated");
779				free($2);
780				YYERROR;
781			}
782			free($2);
783		}
784		| NO flag			{ proto->sslflags &= ~($2); }
785		| flag				{ proto->sslflags |= $1; }
786		;
787
788flag		: STRING			{
789			if (strcmp("sslv2", $1) == 0)
790				$$ = SSLFLAG_SSLV2;
791			else if (strcmp("sslv3", $1) == 0)
792				$$ = SSLFLAG_SSLV3;
793			else if (strcmp("tlsv1", $1) == 0)
794				$$ = SSLFLAG_TLSV1;
795			else {
796				yyerror("invalid SSL flag: %s", $1);
797				free($1);
798				YYERROR;
799			}
800			free($1);
801		}
802		;
803
804protonode	: nodetype APPEND STRING TO STRING marked	{
805			node.action = NODE_ACTION_APPEND;
806			node.key = strdup($5);
807			node.value = strdup($3);
808			if (node.key == NULL || node.value == NULL)
809				fatal("out of memory");
810			if (strchr(node.value, '$') != NULL)
811				node.flags |= PNFLAG_MACRO;
812			free($5);
813			free($3);
814		}
815		| nodetype CHANGE STRING TO STRING marked {
816			node.action = NODE_ACTION_CHANGE;
817			node.key = strdup($3);
818			node.value = strdup($5);
819			if (node.key == NULL || node.value == NULL)
820				fatal("out of memory");
821			if (strchr(node.value, '$') != NULL)
822				node.flags |= PNFLAG_MACRO;
823			free($5);
824			free($3);
825		}
826		| nodetype REMOVE STRING marked	{
827			node.action = NODE_ACTION_REMOVE;
828			node.key = strdup($3);
829			node.value = NULL;
830			if (node.key == NULL)
831				fatal("out of memory");
832			free($3);
833		}
834		| nodetype EXPECT STRING FROM STRING mark	{
835			node.action = NODE_ACTION_EXPECT;
836			node.key = strdup($5);
837			node.value = strdup($3);;
838			if (node.key == NULL || node.value == NULL)
839				fatal("out of memory");
840			free($5);
841			free($3);
842			proto->lateconnect++;
843		}
844		| nodetype FILTER STRING FROM STRING mark	{
845			node.action = NODE_ACTION_FILTER;
846			node.key = strdup($5);
847			node.value = strdup($3);;
848			if (node.key == NULL || node.value == NULL)
849				fatal("out of memory");
850			free($5);
851			free($3);
852			proto->lateconnect++;
853		}
854		| nodetype HASH STRING marked			{
855			node.action = NODE_ACTION_HASH;
856			node.key = strdup($3);
857			node.value = NULL;
858			if (node.key == NULL)
859				fatal("out of memory");
860			free($3);
861			proto->lateconnect++;
862		}
863		| nodetype LOG STRING marked			{
864			node.action = NODE_ACTION_LOG;
865			node.key = strdup($3);
866			node.value = NULL;
867			node.flags |= PNFLAG_LOG;
868			if (node.key == NULL)
869				fatal("out of memory");
870			free($3);
871		}
872		;
873
874mark		: /* empty */
875		| MARK				{ node.flags |= PNFLAG_MARK; }
876		;
877
878marked		: /* empty */
879		| MARKED			{ node.flags |= PNFLAG_MARK; }
880		;
881
882nodetype	: HEADER			{
883			node.type = NODE_TYPE_HEADER;
884		}
885		| URL				{ node.type = NODE_TYPE_URL; }
886		| COOKIE			{
887			node.type = NODE_TYPE_COOKIE;
888		}
889		| PATH				{
890				proto->flags |= F_LOOKUP_PATH;
891				node.type = NODE_TYPE_PATH;
892		}
893		;
894
895sslcache	: NUMBER			{
896			if ($1 < 0) {
897				yyerror("invalid sslcache value: %d", $1);
898				YYERROR;
899			}
900			$$ = $1;
901		}
902		| DISABLE			{ $$ = -2; }
903		;
904
905relay		: RELAY STRING	{
906			struct relay *r;
907
908			TAILQ_FOREACH(r, conf->relays, entry)
909				if (!strcmp(r->conf.name, $2))
910					break;
911			if (r != NULL) {
912				yyerror("relay %s defined twice", $2);
913				free($2);
914				YYERROR;
915			}
916			if ((r = calloc(1, sizeof (*r))) == NULL)
917				fatal("out of memory");
918
919			if (strlcpy(r->conf.name, $2, sizeof(r->conf.name)) >=
920			    sizeof(r->conf.name)) {
921				yyerror("relay name truncated");
922				YYERROR;
923			}
924			free($2);
925			r->conf.id = last_relay_id++;
926			r->conf.timeout.tv_sec = RELAY_TIMEOUT;
927			r->proto = NULL;
928			r->conf.proto = EMPTY_ID;
929			r->conf.dsttable = EMPTY_ID;
930			r->conf.dstretry = 0;
931			if (last_relay_id == INT_MAX) {
932				yyerror("too many relays defined");
933				YYERROR;
934			}
935			rlay = r;
936		} '{' optnl relayopts_l '}'	{
937			if (rlay->conf.ss.ss_family == AF_UNSPEC) {
938				yyerror("relay %s has no listener",
939				    rlay->conf.name);
940				YYERROR;
941			}
942			if ((rlay->conf.flags & F_NATLOOK) == 0 &&
943			    rlay->conf.dstss.ss_family == AF_UNSPEC &&
944			    rlay->conf.dsttable == EMPTY_ID) {
945				yyerror("relay %s has no target, service, "
946				    "or table", rlay->conf.name);
947				YYERROR;
948			}
949			if (rlay->conf.proto == EMPTY_ID) {
950				rlay->proto = &conf->proto_default;
951				rlay->conf.proto = conf->proto_default.id;
952			}
953			if (relay_load_certfiles(rlay) == -1) {
954				yyerror("cannot load certificates for relay %s",
955				    rlay->conf.name);
956				YYERROR;
957			}
958			conf->relaycount++;
959			SPLAY_INIT(&rlay->sessions);
960			TAILQ_INSERT_HEAD(conf->relays, rlay, entry);
961		}
962		;
963
964relayopts_l	: relayopts_l relayoptsl nl
965		| relayoptsl optnl
966		;
967
968relayoptsl	: LISTEN ON STRING port optssl {
969			struct addresslist 	 al;
970			struct address		*h;
971
972			if (rlay->conf.ss.ss_family != AF_UNSPEC) {
973				yyerror("relay %s listener already specified",
974				    rlay->conf.name);
975				YYERROR;
976			}
977
978			TAILQ_INIT(&al);
979			if (host($3, &al, 1, $4, NULL) <= 0) {
980				yyerror("invalid listen ip: %s", $3);
981				free($3);
982				YYERROR;
983			}
984			free($3);
985			h = TAILQ_FIRST(&al);
986			bcopy(&h->ss, &rlay->conf.ss, sizeof(rlay->conf.ss));
987			rlay->conf.port = h->port;
988			if ($5) {
989				rlay->conf.flags |= F_SSL;
990				conf->flags |= F_SSL;
991			}
992		}
993		| FORWARD TO STRING port retry {
994			struct addresslist 	 al;
995			struct address		*h;
996
997			if (rlay->conf.dstss.ss_family != AF_UNSPEC) {
998				yyerror("relay %s target or service already "
999				    "specified", rlay->conf.name);
1000				free($3);
1001				YYERROR;
1002			}
1003
1004			TAILQ_INIT(&al);
1005			if (host($3, &al, 1, $4, NULL) <= 0) {
1006				yyerror("invalid listen ip: %s", $3);
1007				free($3);
1008				YYERROR;
1009			}
1010			free($3);
1011			h = TAILQ_FIRST(&al);
1012			bcopy(&h->ss, &rlay->conf.dstss,
1013			    sizeof(rlay->conf.dstss));
1014			rlay->conf.dstport = h->port;
1015			rlay->conf.dstretry = $5;
1016		}
1017		| SERVICE STRING retry {
1018			struct service	*svc;
1019			struct address	*h;
1020
1021			if (rlay->conf.dstss.ss_family != AF_UNSPEC) {
1022				yyerror("relay %s target or service already "
1023				    "specified", rlay->conf.name);
1024				free($2);
1025				YYERROR;
1026			}
1027
1028			if ((svc = service_findbyname(conf, $2)) == NULL) {
1029				yyerror("relay %s for unknown service %s",
1030				    rlay->conf.name, $2);
1031				free($2);
1032				YYERROR;
1033			}
1034			free($2);
1035			h = TAILQ_FIRST(&svc->virts);
1036			bcopy(&h->ss, &rlay->conf.dstss,
1037			    sizeof(rlay->conf.dstss));
1038			rlay->conf.dstport = h->port;
1039			rlay->conf.dstretry = $3;
1040		}
1041		| TABLE STRING dstport dstmode docheck {
1042			struct table	*tb;
1043
1044			rlay->conf.dstport = $3;
1045			if (rlay->conf.dstport == 0)
1046				rlay->conf.dstport = rlay->conf.port;
1047
1048			if ((tb = table_inherit($2, rlay->conf.dstport)) ==
1049			    NULL) {
1050				free($2);
1051				YYERROR;
1052			}
1053			free($2);
1054			rlay->conf.dsttable = tb->conf.id;
1055			rlay->dsttable = tb;
1056			rlay->conf.dstport = tb->conf.port;
1057			rlay->conf.dstmode = $4;
1058			rlay->conf.dstcheck = $5;
1059			rlay->dsttable->conf.flags |= F_USED;
1060		}
1061		| PROTO STRING {
1062			struct protocol *p;
1063
1064			TAILQ_FOREACH(p, conf->protos, entry)
1065				if (!strcmp(p->name, $2))
1066					break;
1067			if (p == NULL) {
1068				yyerror("no such protocol: %s", $2);
1069				free($2);
1070				YYERROR;
1071			}
1072			p->flags |= F_USED;
1073			rlay->conf.proto = p->id;
1074			rlay->proto = p;
1075			free($2);
1076		}
1077		| NAT LOOKUP retry	{
1078			rlay->conf.flags |= F_NATLOOK;
1079			rlay->conf.dstretry = $3;
1080		}
1081		| TIMEOUT NUMBER	{
1082			if ((rlay->conf.timeout.tv_sec = $2) < 0) {
1083				yyerror("invalid timeout: %d", $2);
1084				YYERROR;
1085			}
1086		}
1087		| DISABLE		{ rlay->conf.flags |= F_DISABLE; }
1088		;
1089
1090dstmode		: /* empty */		{ $$ = RELAY_DSTMODE_DEFAULT; }
1091		| LOADBALANCE		{ $$ = RELAY_DSTMODE_LOADBALANCE; }
1092		| ROUNDROBIN		{ $$ = RELAY_DSTMODE_ROUNDROBIN; }
1093		| HASH			{ $$ = RELAY_DSTMODE_HASH; }
1094		;
1095
1096docheck		: /* empty */		{ $$ = 1; }
1097		| NO CHECK		{ $$ = 0; }
1098		;
1099
1100interface	: /*empty*/		{ $$ = NULL; }
1101		| INTERFACE STRING	{ $$ = $2; }
1102		;
1103
1104dstport		: /* empty */		{ $$ = 0; }
1105		| port			{ $$ = $1; }
1106		;
1107
1108host		: HOST STRING retry {
1109			struct address *a;
1110			struct addresslist al;
1111
1112			if (($$ = calloc(1, sizeof(*($$)))) == NULL)
1113				fatal("out of memory");
1114
1115			TAILQ_INIT(&al);
1116			if (host($2, &al, 1, 0, NULL) <= 0) {
1117				yyerror("invalid host %s", $2);
1118				free($2);
1119				free($$);
1120				YYERROR;
1121			}
1122			a = TAILQ_FIRST(&al);
1123			memcpy(&$$->conf.ss, &a->ss, sizeof($$->conf.ss));
1124			free(a);
1125
1126			if (strlcpy($$->conf.name, $2, sizeof($$->conf.name)) >=
1127			    sizeof($$->conf.name)) {
1128				yyerror("host name truncated");
1129				free($2);
1130				free($$);
1131				YYERROR;
1132			}
1133			free($2);
1134			$$->conf.id = last_host_id++;
1135			$$->conf.retry = $3;
1136			if (last_host_id == INT_MAX) {
1137				yyerror("too many hosts defined");
1138				free($$);
1139				YYERROR;
1140			}
1141		}
1142		;
1143
1144retry		: /* nothing */		{ $$ = 0; }
1145		| RETRY NUMBER		{
1146			if (($$ = $2) < 0) {
1147				yyerror("invalid retry value: %d\n", $2);
1148				YYERROR;
1149			}
1150		}
1151		;
1152
1153timeout		: NUMBER
1154		{
1155			if ($1 < 0) {
1156				yyerror("invalid timeout: %d\n", $1);
1157				YYERROR;
1158			}
1159			$$.tv_sec = $1 / 1000;
1160			$$.tv_usec = ($1 % 1000) * 1000;
1161		}
1162		;
1163
1164log		: /* empty */		{ $$ = 0; }
1165		| LOG			{ $$ = 1; }
1166		;
1167
1168comma		: ','
1169		| /* empty */
1170		;
1171
1172optnl		: '\n' optnl
1173		|
1174		;
1175
1176nl		: '\n' optnl
1177		;
1178
1179%%
1180
1181struct keywords {
1182	const char	*k_name;
1183	int		 k_val;
1184};
1185
1186int
1187yyerror(const char *fmt, ...)
1188{
1189	va_list		 ap;
1190
1191	file->errors++;
1192	va_start(ap, fmt);
1193	fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
1194	vfprintf(stderr, fmt, ap);
1195	fprintf(stderr, "\n");
1196	va_end(ap);
1197	return (0);
1198}
1199
1200int
1201kw_cmp(const void *k, const void *e)
1202{
1203	return (strcmp(k, ((const struct keywords *)e)->k_name));
1204}
1205
1206int
1207lookup(char *s)
1208{
1209	/* this has to be sorted always */
1210	static const struct keywords keywords[] = {
1211		{ "all",		ALL },
1212		{ "append",		APPEND },
1213		{ "backlog",		BACKLOG },
1214		{ "backup",		BACKUP },
1215		{ "buffer",		BUFFER },
1216		{ "cache",		CACHE },
1217		{ "change",		CHANGE },
1218		{ "check",		CHECK },
1219		{ "ciphers",		CIPHERS },
1220		{ "code",		CODE },
1221		{ "cookie",		COOKIE },
1222		{ "demote",		DEMOTE },
1223		{ "digest",		DIGEST },
1224		{ "disable",		DISABLE },
1225		{ "expect",		EXPECT },
1226		{ "external",		EXTERNAL },
1227		{ "filter",		FILTER },
1228		{ "forward",		FORWARD },
1229		{ "from",		FROM },
1230		{ "hash",		HASH },
1231		{ "header",		HEADER },
1232		{ "host",		HOST },
1233		{ "icmp",		ICMP },
1234		{ "include",		INCLUDE },
1235		{ "interface",		INTERFACE },
1236		{ "interval",		INTERVAL },
1237		{ "ip",			IP },
1238		{ "listen",		LISTEN },
1239		{ "loadbalance",	LOADBALANCE },
1240		{ "log",		LOG },
1241		{ "lookup",		LOOKUP },
1242		{ "mark",		MARK },
1243		{ "marked",		MARKED },
1244		{ "nat",		NAT },
1245		{ "no",			NO },
1246		{ "nodelay",		NODELAY },
1247		{ "nothing",		NOTHING },
1248		{ "on",			ON },
1249		{ "path",		PATH },
1250		{ "port",		PORT },
1251		{ "prefork",		PREFORK },
1252		{ "protocol",		PROTO },
1253		{ "real",		REAL },
1254		{ "relay",		RELAY },
1255		{ "remove",		REMOVE },
1256		{ "request",		REQUEST },
1257		{ "response",		RESPONSE },
1258		{ "retry",		RETRY },
1259		{ "roundrobin",		ROUNDROBIN },
1260		{ "sack",		SACK },
1261		{ "script",		SCRIPT },
1262		{ "send",		SEND },
1263		{ "service",		SERVICE },
1264		{ "session",		SESSION },
1265		{ "socket",		SOCKET },
1266		{ "ssl",		SSL },
1267		{ "sticky-address",	STICKYADDR },
1268		{ "table",		TABLE },
1269		{ "tag",		TAG },
1270		{ "tcp",		TCP },
1271		{ "timeout",		TIMEOUT },
1272		{ "to",			TO },
1273		{ "updates",		UPDATES },
1274		{ "url",		URL },
1275		{ "virtual",		VIRTUAL }
1276	};
1277	const struct keywords	*p;
1278
1279	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
1280	    sizeof(keywords[0]), kw_cmp);
1281
1282	if (p)
1283		return (p->k_val);
1284	else
1285		return (STRING);
1286}
1287
1288#define MAXPUSHBACK	128
1289
1290char	*parsebuf;
1291int	 parseindex;
1292char	 pushback_buffer[MAXPUSHBACK];
1293int	 pushback_index = 0;
1294
1295int
1296lgetc(int quotec)
1297{
1298	int		c, next;
1299
1300	if (parsebuf) {
1301		/* Read character from the parsebuffer instead of input. */
1302		if (parseindex >= 0) {
1303			c = parsebuf[parseindex++];
1304			if (c != '\0')
1305				return (c);
1306			parsebuf = NULL;
1307		} else
1308			parseindex++;
1309	}
1310
1311	if (pushback_index)
1312		return (pushback_buffer[--pushback_index]);
1313
1314	if (quotec) {
1315		if ((c = getc(file->stream)) == EOF) {
1316			yyerror("reached end of file while parsing quoted string");
1317			if (popfile() == EOF)
1318				return (EOF);
1319			return (quotec);
1320		}
1321		return (c);
1322	}
1323
1324	while ((c = getc(file->stream)) == '\\') {
1325		next = getc(file->stream);
1326		if (next != '\n') {
1327			c = next;
1328			break;
1329		}
1330		yylval.lineno = file->lineno;
1331		file->lineno++;
1332	}
1333
1334	while (c == EOF) {
1335		if (popfile() == EOF)
1336			return (EOF);
1337		c = getc(file->stream);
1338	}
1339	return (c);
1340}
1341
1342int
1343lungetc(int c)
1344{
1345	if (c == EOF)
1346		return (EOF);
1347	if (parsebuf) {
1348		parseindex--;
1349		if (parseindex >= 0)
1350			return (c);
1351	}
1352	if (pushback_index < MAXPUSHBACK-1)
1353		return (pushback_buffer[pushback_index++] = c);
1354	else
1355		return (EOF);
1356}
1357
1358int
1359findeol(void)
1360{
1361	int	c;
1362
1363	parsebuf = NULL;
1364	pushback_index = 0;
1365
1366	/* skip to either EOF or the first real EOL */
1367	while (1) {
1368		c = lgetc(0);
1369		if (c == '\n') {
1370			file->lineno++;
1371			break;
1372		}
1373		if (c == EOF)
1374			break;
1375	}
1376	return (ERROR);
1377}
1378
1379int
1380yylex(void)
1381{
1382	char	 buf[8096];
1383	char	*p, *val;
1384	int	 quotec, next, c;
1385	int	 token;
1386
1387top:
1388	p = buf;
1389	while ((c = lgetc(0)) == ' ' || c == '\t')
1390		; /* nothing */
1391
1392	yylval.lineno = file->lineno;
1393	if (c == '#')
1394		while ((c = lgetc(0)) != '\n' && c != EOF)
1395			; /* nothing */
1396	if (c == '$' && parsebuf == NULL) {
1397		while (1) {
1398			if ((c = lgetc(0)) == EOF)
1399				return (0);
1400
1401			if (p + 1 >= buf + sizeof(buf) - 1) {
1402				yyerror("string too long");
1403				return (findeol());
1404			}
1405			if (isalnum(c) || c == '_') {
1406				*p++ = (char)c;
1407				continue;
1408			}
1409			*p = '\0';
1410			lungetc(c);
1411			break;
1412		}
1413		val = symget(buf);
1414		if (val == NULL) {
1415			yyerror("macro '%s' not defined", buf);
1416			return (findeol());
1417		}
1418		parsebuf = val;
1419		parseindex = 0;
1420		goto top;
1421	}
1422
1423	switch (c) {
1424	case '\'':
1425	case '"':
1426		quotec = c;
1427		while (1) {
1428			if ((c = lgetc(quotec)) == EOF)
1429				return (0);
1430			if (c == '\n') {
1431				file->lineno++;
1432				continue;
1433			} else if (c == '\\') {
1434				if ((next = lgetc(quotec)) == EOF)
1435					return (0);
1436				if (next == quotec || c == ' ' || c == '\t')
1437					c = next;
1438				else if (next == '\n')
1439					continue;
1440				else
1441					lungetc(next);
1442			} else if (c == quotec) {
1443				*p = '\0';
1444				break;
1445			}
1446			if (p + 1 >= buf + sizeof(buf) - 1) {
1447				yyerror("string too long");
1448				return (findeol());
1449			}
1450			*p++ = (char)c;
1451		}
1452		yylval.v.string = strdup(buf);
1453		if (yylval.v.string == NULL)
1454			err(1, "yylex: strdup");
1455		return (STRING);
1456	}
1457
1458#define allowed_to_end_number(x) \
1459	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
1460
1461	if (c == '-' || isdigit(c)) {
1462		do {
1463			*p++ = c;
1464			if ((unsigned)(p-buf) >= sizeof(buf)) {
1465				yyerror("string too long");
1466				return (findeol());
1467			}
1468		} while ((c = lgetc(0)) != EOF && isdigit(c));
1469		lungetc(c);
1470		if (p == buf + 1 && buf[0] == '-')
1471			goto nodigits;
1472		if (c == EOF || allowed_to_end_number(c)) {
1473			const char *errstr = NULL;
1474
1475			*p = '\0';
1476			yylval.v.number = strtonum(buf, LLONG_MIN,
1477			    LLONG_MAX, &errstr);
1478			if (errstr) {
1479				yyerror("\"%s\" invalid number: %s",
1480				    buf, errstr);
1481				return (findeol());
1482			}
1483			return (NUMBER);
1484		} else {
1485nodigits:
1486			while (p > buf + 1)
1487				lungetc(*--p);
1488			c = *--p;
1489			if (c == '-')
1490				return (c);
1491		}
1492	}
1493
1494#define allowed_in_string(x) \
1495	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
1496	x != '{' && x != '}' && \
1497	x != '!' && x != '=' && x != '#' && \
1498	x != ','))
1499
1500	if (isalnum(c) || c == ':' || c == '_') {
1501		do {
1502			*p++ = c;
1503			if ((unsigned)(p-buf) >= sizeof(buf)) {
1504				yyerror("string too long");
1505				return (findeol());
1506			}
1507		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
1508		lungetc(c);
1509		*p = '\0';
1510		if ((token = lookup(buf)) == STRING)
1511			if ((yylval.v.string = strdup(buf)) == NULL)
1512				err(1, "yylex: strdup");
1513		return (token);
1514	}
1515	if (c == '\n') {
1516		yylval.lineno = file->lineno;
1517		file->lineno++;
1518	}
1519	if (c == EOF)
1520		return (0);
1521	return (c);
1522}
1523
1524int
1525check_file_secrecy(int fd, const char *fname)
1526{
1527	struct stat	st;
1528
1529	if (fstat(fd, &st)) {
1530		log_warn("cannot stat %s", fname);
1531		return (-1);
1532	}
1533	if (st.st_uid != 0 && st.st_uid != getuid()) {
1534		log_warnx("%s: owner not root or current user", fname);
1535		return (-1);
1536	}
1537	if (st.st_mode & (S_IRWXG | S_IRWXO)) {
1538		log_warnx("%s: group/world readable/writeable", fname);
1539		return (-1);
1540	}
1541	return (0);
1542}
1543
1544struct file *
1545pushfile(const char *name, int secret)
1546{
1547	struct file	*nfile;
1548
1549	if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
1550	    (nfile->name = strdup(name)) == NULL) {
1551		log_warn("malloc");
1552		return (NULL);
1553	}
1554	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
1555		log_warn("%s", nfile->name);
1556		free(nfile->name);
1557		free(nfile);
1558		return (NULL);
1559	} else if (secret &&
1560	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
1561		fclose(nfile->stream);
1562		free(nfile->name);
1563		free(nfile);
1564		return (NULL);
1565	}
1566	nfile->lineno = 1;
1567	TAILQ_INSERT_TAIL(&files, nfile, entry);
1568	return (nfile);
1569}
1570
1571int
1572popfile(void)
1573{
1574	struct file	*prev;
1575
1576	if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
1577		prev->errors += file->errors;
1578		TAILQ_REMOVE(&files, file, entry);
1579		fclose(file->stream);
1580		free(file->name);
1581		free(file);
1582		file = prev;
1583		return (0);
1584	}
1585	return (EOF);
1586}
1587
1588struct hoststated *
1589parse_config(const char *filename, int opts)
1590{
1591	struct sym	*sym, *next;
1592	struct table	*nexttb;
1593	struct host	*h;
1594
1595	if ((conf = calloc(1, sizeof(*conf))) == NULL ||
1596	    (conf->tables = calloc(1, sizeof(*conf->tables))) == NULL ||
1597	    (conf->relays = calloc(1, sizeof(*conf->relays))) == NULL ||
1598	    (conf->protos = calloc(1, sizeof(*conf->protos))) == NULL ||
1599	    (conf->services = calloc(1, sizeof(*conf->services))) == NULL) {
1600		log_warn("cannot allocate memory");
1601		return (NULL);
1602	}
1603
1604	errors = 0;
1605	last_host_id = last_table_id = last_service_id = last_proto_id =
1606	    last_relay_id = 0;
1607
1608	service = NULL;
1609	table = NULL;
1610	rlay = NULL;
1611	proto = NULL;
1612
1613	TAILQ_INIT(conf->services);
1614	TAILQ_INIT(conf->tables);
1615	TAILQ_INIT(conf->protos);
1616	TAILQ_INIT(conf->relays);
1617
1618	memset(&conf->empty_table, 0, sizeof(conf->empty_table));
1619	conf->empty_table.conf.id = EMPTY_TABLE;
1620	conf->empty_table.conf.flags |= F_DISABLE;
1621	(void)strlcpy(conf->empty_table.conf.name, "empty",
1622	    sizeof(conf->empty_table.conf.name));
1623
1624	bzero(&conf->proto_default, sizeof(conf->proto_default));
1625	conf->proto_default.flags = F_USED;
1626	conf->proto_default.cache = RELAY_CACHESIZE;
1627	conf->proto_default.type = RELAY_PROTO_TCP;
1628	(void)strlcpy(conf->proto_default.name, "default",
1629	    sizeof(conf->proto_default.name));
1630	RB_INIT(&conf->proto_default.request_tree);
1631	RB_INIT(&conf->proto_default.response_tree);
1632
1633	conf->timeout.tv_sec = CHECK_TIMEOUT / 1000;
1634	conf->timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000;
1635	conf->interval.tv_sec = CHECK_INTERVAL;
1636	conf->interval.tv_usec = 0;
1637	conf->prefork_relay = RELAY_NUMPROC;
1638	conf->statinterval.tv_sec = RELAY_STATINTERVAL;
1639	conf->opts = opts;
1640	conf->confpath = filename;
1641
1642	if ((file = pushfile(filename, 0)) == NULL) {
1643		free(conf);
1644		return (NULL);
1645	}
1646	setservent(1);
1647
1648	yyparse();
1649	errors = file->errors;
1650	popfile();
1651
1652	endservent();
1653
1654	/* Free macros and check which have not been used. */
1655	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
1656		next = TAILQ_NEXT(sym, entry);
1657		if ((conf->opts & HOSTSTATED_OPT_VERBOSE) && !sym->used)
1658			fprintf(stderr, "warning: macro '%s' not "
1659			    "used\n", sym->nam);
1660		if (!sym->persist) {
1661			free(sym->nam);
1662			free(sym->val);
1663			TAILQ_REMOVE(&symhead, sym, entry);
1664			free(sym);
1665		}
1666	}
1667
1668	if (TAILQ_EMPTY(conf->services) && TAILQ_EMPTY(conf->relays)) {
1669		log_warnx("no services, nothing to do");
1670		errors++;
1671	}
1672
1673	if (TAILQ_EMPTY(conf->relays))
1674		conf->prefork_relay = 0;
1675
1676	if (timercmp(&conf->timeout, &conf->interval, >=)) {
1677		log_warnx("global timeout exceeds interval");
1678		errors++;
1679	}
1680
1681	/* Verify that every table is used */
1682	for (table = TAILQ_FIRST(conf->tables); table != NULL;
1683	     table = nexttb) {
1684		nexttb = TAILQ_NEXT(table, entry);
1685		if (table->conf.port == 0) {
1686			TAILQ_REMOVE(conf->tables, table, entry);
1687			while ((h = TAILQ_FIRST(&table->hosts)) != NULL) {
1688				TAILQ_REMOVE(&table->hosts, h, entry);
1689				free(h);
1690			}
1691			if (table->sendbuf != NULL)
1692				free(table->sendbuf);
1693			free(table);
1694			continue;
1695		}
1696		if (!(table->conf.flags & F_USED)) {
1697			log_warnx("unused table: %s", table->conf.name);
1698			errors++;
1699		}
1700		if (timercmp(&table->conf.timeout, &conf->interval, >=)) {
1701			log_warnx("table timeout exceeds interval: %s",
1702			    table->conf.name);
1703			errors++;
1704		}
1705	}
1706
1707	/* Verify that every non-default protocol is used */
1708	TAILQ_FOREACH(proto, conf->protos, entry) {
1709		if (!(proto->flags & F_USED)) {
1710			log_warnx("unused protocol: %s", proto->name);
1711		}
1712	}
1713
1714	if (errors) {
1715		free(conf);
1716		return (NULL);
1717	}
1718
1719	return (conf);
1720}
1721
1722int
1723symset(const char *nam, const char *val, int persist)
1724{
1725	struct sym	*sym;
1726
1727	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
1728	    sym = TAILQ_NEXT(sym, entry))
1729		;	/* nothing */
1730
1731	if (sym != NULL) {
1732		if (sym->persist == 1)
1733			return (0);
1734		else {
1735			free(sym->nam);
1736			free(sym->val);
1737			TAILQ_REMOVE(&symhead, sym, entry);
1738			free(sym);
1739		}
1740	}
1741	if ((sym = calloc(1, sizeof(*sym))) == NULL)
1742		return (-1);
1743
1744	sym->nam = strdup(nam);
1745	if (sym->nam == NULL) {
1746		free(sym);
1747		return (-1);
1748	}
1749	sym->val = strdup(val);
1750	if (sym->val == NULL) {
1751		free(sym->nam);
1752		free(sym);
1753		return (-1);
1754	}
1755	sym->used = 0;
1756	sym->persist = persist;
1757	TAILQ_INSERT_TAIL(&symhead, sym, entry);
1758	return (0);
1759}
1760
1761int
1762cmdline_symset(char *s)
1763{
1764	char	*sym, *val;
1765	int	ret;
1766	size_t	len;
1767
1768	if ((val = strrchr(s, '=')) == NULL)
1769		return (-1);
1770
1771	len = strlen(s) - strlen(val) + 1;
1772	if ((sym = malloc(len)) == NULL)
1773		errx(1, "cmdline_symset: malloc");
1774
1775	(void)strlcpy(sym, s, len);
1776
1777	ret = symset(sym, val + 1, 1);
1778	free(sym);
1779
1780	return (ret);
1781}
1782
1783char *
1784symget(const char *nam)
1785{
1786	struct sym	*sym;
1787
1788	TAILQ_FOREACH(sym, &symhead, entry)
1789		if (strcmp(nam, sym->nam) == 0) {
1790			sym->used = 1;
1791			return (sym->val);
1792		}
1793	return (NULL);
1794}
1795
1796struct address *
1797host_v4(const char *s)
1798{
1799	struct in_addr		 ina;
1800	struct sockaddr_in	*sain;
1801	struct address		*h;
1802
1803	bzero(&ina, sizeof(ina));
1804	if (inet_pton(AF_INET, s, &ina) != 1)
1805		return (NULL);
1806
1807	if ((h = calloc(1, sizeof(*h))) == NULL)
1808		fatal(NULL);
1809	sain = (struct sockaddr_in *)&h->ss;
1810	sain->sin_len = sizeof(struct sockaddr_in);
1811	sain->sin_family = AF_INET;
1812	sain->sin_addr.s_addr = ina.s_addr;
1813
1814	return (h);
1815}
1816
1817struct address *
1818host_v6(const char *s)
1819{
1820	struct in6_addr		 ina6;
1821	struct sockaddr_in6	*sin6;
1822	struct address		*h;
1823
1824	bzero(&ina6, sizeof(ina6));
1825	if (inet_pton(AF_INET6, s, &ina6) != 1)
1826		return (NULL);
1827
1828	if ((h = calloc(1, sizeof(*h))) == NULL)
1829		fatal(NULL);
1830	sin6 = (struct sockaddr_in6 *)&h->ss;
1831	sin6->sin6_len = sizeof(struct sockaddr_in6);
1832	sin6->sin6_family = AF_INET6;
1833	memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6));
1834
1835	return (h);
1836}
1837
1838int
1839host_dns(const char *s, struct addresslist *al, int max,
1840	 in_port_t port, const char *ifname)
1841{
1842	struct addrinfo		 hints, *res0, *res;
1843	int			 error, cnt = 0;
1844	struct sockaddr_in	*sain;
1845	struct sockaddr_in6	*sin6;
1846	struct address		*h;
1847
1848	bzero(&hints, sizeof(hints));
1849	hints.ai_family = PF_UNSPEC;
1850	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
1851	error = getaddrinfo(s, NULL, &hints, &res0);
1852	if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
1853		return (0);
1854	if (error) {
1855		log_warnx("host_dns: could not parse \"%s\": %s", s,
1856		    gai_strerror(error));
1857		return (-1);
1858	}
1859
1860	for (res = res0; res && cnt < max; res = res->ai_next) {
1861		if (res->ai_family != AF_INET &&
1862		    res->ai_family != AF_INET6)
1863			continue;
1864		if ((h = calloc(1, sizeof(*h))) == NULL)
1865			fatal(NULL);
1866
1867		h->port = port;
1868		if (ifname != NULL) {
1869			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
1870			    sizeof(h->ifname))
1871				log_warnx("host_dns: interface name truncated");
1872			return (-1);
1873		}
1874		h->ss.ss_family = res->ai_family;
1875		if (res->ai_family == AF_INET) {
1876			sain = (struct sockaddr_in *)&h->ss;
1877			sain->sin_len = sizeof(struct sockaddr_in);
1878			sain->sin_addr.s_addr = ((struct sockaddr_in *)
1879			    res->ai_addr)->sin_addr.s_addr;
1880		} else {
1881			sin6 = (struct sockaddr_in6 *)&h->ss;
1882			sin6->sin6_len = sizeof(struct sockaddr_in6);
1883			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
1884			    res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
1885		}
1886
1887		TAILQ_INSERT_HEAD(al, h, entry);
1888		cnt++;
1889	}
1890	if (cnt == max && res) {
1891		log_warnx("host_dns: %s resolves to more than %d hosts",
1892		    s, max);
1893	}
1894	freeaddrinfo(res0);
1895	return (cnt);
1896}
1897
1898int
1899host(const char *s, struct addresslist *al, int max,
1900    in_port_t port, const char *ifname)
1901{
1902	struct address *h;
1903
1904	h = host_v4(s);
1905
1906	/* IPv6 address? */
1907	if (h == NULL)
1908		h = host_v6(s);
1909
1910	if (h != NULL) {
1911		h->port = port;
1912		if (ifname != NULL) {
1913			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
1914			    sizeof(h->ifname)) {
1915				log_warnx("host: interface name truncated");
1916				return (-1);
1917			}
1918		}
1919
1920		TAILQ_INSERT_HEAD(al, h, entry);
1921		return (1);
1922	}
1923
1924	return (host_dns(s, al, max, port, ifname));
1925}
1926
1927struct table *
1928table_inherit(const char *name, in_port_t port)
1929{
1930	char		pname[TABLE_NAME_SIZE + 6];
1931	struct host	*h, *dsth;
1932	struct table	*dsttb, *tb;
1933
1934	/* Get the table or table template */
1935	if ((dsttb = table_findbyname(conf, name)) == NULL) {
1936		yyerror("unknown table or template %s", name);
1937		return (NULL);
1938	}
1939	if (dsttb->conf.port != 0)
1940		return (dsttb);
1941
1942	if (port == 0) {
1943		yyerror("invalid port");
1944		return (NULL);
1945	}
1946
1947	/* Check if a matching table already exists */
1948	snprintf(pname, sizeof(pname), "%s:%u", name, ntohs(port));
1949	if ((tb = table_findbyname(conf, pname)) != NULL) {
1950		if (tb->conf.port == 0) {
1951			yyerror("invalid table");
1952			return (NULL);
1953		}
1954		return (tb);
1955	}
1956
1957	/* Create a new table */
1958	if ((tb = calloc(1, sizeof (*tb))) == NULL)
1959		fatal("out of memory");
1960	bcopy(dsttb, tb, sizeof(*tb));
1961	if (strlcpy(tb->conf.name, pname, sizeof(tb->conf.name))
1962	    >= sizeof(tb->conf.name)) {
1963		yyerror("table name truncated");
1964		return (NULL);
1965	}
1966	if (dsttb->sendbuf != NULL &&
1967	    (tb->sendbuf = strdup(dsttb->sendbuf)) == NULL)
1968		fatal("out of memory");
1969	tb->conf.port = port;
1970	tb->conf.id = last_table_id++;
1971	if (last_table_id == INT_MAX) {
1972		yyerror("too many tables defined");
1973		return (NULL);
1974	}
1975
1976	/* Copy the associated hosts */
1977	bzero(&tb->hosts, sizeof(tb->hosts));
1978	TAILQ_FOREACH(dsth, &dsttb->hosts, entry) {
1979		if ((h = (struct host *)
1980		    calloc(1, sizeof (*h))) == NULL)
1981			fatal("out of memory");
1982		bcopy(dsth, h, sizeof(*h));
1983		h->conf.id = last_host_id++;
1984		if (last_host_id == INT_MAX) {
1985			yyerror("too many hosts defined");
1986			return (NULL);
1987		}
1988		h->conf.tableid = tb->conf.id;
1989		h->tablename = tb->conf.name;
1990		TAILQ_INSERT_HEAD(&tb->hosts, h, entry);
1991	}
1992
1993	conf->tablecount++;
1994	TAILQ_INSERT_HEAD(conf->tables, tb, entry);
1995
1996	return (tb);
1997}
1998