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