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