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