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