GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/relayd/parse.y Lines: 222 613 36.2 %
Date: 2017-11-13 Branches: 131 421 31.1 %

Line Branch Exec Source
1
/*	$OpenBSD: parse.y,v 1.216 2017/08/28 06:00:05 florian Exp $	*/
2
3
/*
4
 * Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
5
 * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org>
6
 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
7
 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
8
 * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
9
 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
10
 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
11
 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
12
 * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
13
 *
14
 * Permission to use, copy, modify, and distribute this software for any
15
 * purpose with or without fee is hereby granted, provided that the above
16
 * copyright notice and this permission notice appear in all copies.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
 */
26
27
%{
28
#include <sys/types.h>
29
#include <sys/socket.h>
30
#include <sys/stat.h>
31
#include <sys/queue.h>
32
#include <sys/ioctl.h>
33
#include <sys/time.h>
34
#include <sys/tree.h>
35
36
#include <netinet/in.h>
37
#include <arpa/inet.h>
38
#include <net/if.h>
39
#include <net/pfvar.h>
40
#include <net/route.h>
41
42
#include <stdint.h>
43
#include <stdarg.h>
44
#include <stdio.h>
45
#include <unistd.h>
46
#include <ctype.h>
47
#include <err.h>
48
#include <endian.h>
49
#include <errno.h>
50
#include <limits.h>
51
#include <netdb.h>
52
#include <string.h>
53
#include <ifaddrs.h>
54
#include <syslog.h>
55
#include <md5.h>
56
57
#include "relayd.h"
58
#include "http.h"
59
#include "snmp.h"
60
61
TAILQ_HEAD(files, file)		 files = TAILQ_HEAD_INITIALIZER(files);
62
static struct file {
63
	TAILQ_ENTRY(file)	 entry;
64
	FILE			*stream;
65
	char			*name;
66
	int			 lineno;
67
	int			 errors;
68
} *file, *topfile;
69
struct file	*pushfile(const char *, int);
70
int		 popfile(void);
71
int		 check_file_secrecy(int, const char *);
72
int		 yyparse(void);
73
int		 yylex(void);
74
int		 yyerror(const char *, ...);
75
int		 kw_cmp(const void *, const void *);
76
int		 lookup(char *);
77
int		 lgetc(int);
78
int		 lungetc(int);
79
int		 findeol(void);
80
81
TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
82
struct sym {
83
	TAILQ_ENTRY(sym)	 entry;
84
	int			 used;
85
	int			 persist;
86
	char			*nam;
87
	char			*val;
88
};
89
int		 symset(const char *, const char *, int);
90
char		*symget(const char *);
91
92
struct relayd		*conf = NULL;
93
static int		 errors = 0;
94
static int		 loadcfg = 0;
95
objid_t			 last_rdr_id = 0;
96
objid_t			 last_table_id = 0;
97
objid_t			 last_host_id = 0;
98
objid_t			 last_relay_id = 0;
99
objid_t			 last_proto_id = 0;
100
objid_t			 last_rt_id = 0;
101
objid_t			 last_nr_id = 0;
102
objid_t			 last_key_id = 0;
103
104
static struct rdr	*rdr = NULL;
105
static struct table	*table = NULL;
106
static struct relay	*rlay = NULL;
107
static struct host	*hst = NULL;
108
struct relaylist	 relays;
109
static struct protocol	*proto = NULL;
110
static struct relay_rule *rule = NULL;
111
static struct router	*router = NULL;
112
static int		 label = 0;
113
static int		 tagged = 0;
114
static int		 tag = 0;
115
static in_port_t	 tableport = 0;
116
static int		 dstmode;
117
static enum key_type	 keytype = KEY_TYPE_NONE;
118
static enum direction	 dir = RELAY_DIR_ANY;
119
static char		*rulefile = NULL;
120
static union hashkey	*hashkey = NULL;
121
122
struct address	*host_v4(const char *);
123
struct address	*host_v6(const char *);
124
int		 host_dns(const char *, struct addresslist *,
125
		    int, struct portrange *, const char *, int);
126
int		 host_if(const char *, struct addresslist *,
127
		    int, struct portrange *, const char *, int);
128
int		 host(const char *, struct addresslist *,
129
		    int, struct portrange *, const char *, int);
130
void		 host_free(struct addresslist *);
131
132
struct table	*table_inherit(struct table *);
133
int		 relay_id(struct relay *);
134
struct relay	*relay_inherit(struct relay *, struct relay *);
135
int		 getservice(char *);
136
int		 is_if_in_group(const char *, const char *);
137
138
typedef struct {
139
	union {
140
		int64_t			 number;
141
		char			*string;
142
		struct host		*host;
143
		struct timeval		 tv;
144
		struct table		*table;
145
		struct portrange	 port;
146
		struct {
147
			union hashkey	 key;
148
			int		 keyset;
149
		}			 key;
150
		enum direction		 dir;
151
		struct {
152
			struct sockaddr_storage	 ss;
153
			char			 name[HOST_NAME_MAX+1];
154
		}			 addr;
155
		struct {
156
			enum digest_type type;
157
			char		*digest;
158
		}			 digest;
159
	} v;
160
	int lineno;
161
} YYSTYPE;
162
163
%}
164
165
%token	ALL APPEND BACKLOG BACKUP BUFFER CA CACHE SET CHECK CIPHERS CODE
166
%token	COOKIE DEMOTE DIGEST DISABLE ERROR EXPECT PASS BLOCK EXTERNAL FILENAME
167
%token	FORWARD FROM HASH HEADER HOST ICMP INCLUDE INET INET6 INTERFACE
168
%token	INTERVAL IP LABEL LISTEN VALUE LOADBALANCE LOG LOOKUP METHOD MODE NAT
169
%token	NO DESTINATION NODELAY NOTHING ON PARENT PATH PFTAG PORT PREFORK
170
%token	PRIORITY PROTO QUERYSTR REAL REDIRECT RELAY REMOVE REQUEST RESPONSE
171
%token	RETRY QUICK RETURN ROUNDROBIN ROUTE SACK SCRIPT SEND SESSION SNMP
172
%token	SOCKET SPLICE SSL STICKYADDR STYLE TABLE TAG TAGGED TCP TIMEOUT TLS TO
173
%token	ROUTER RTLABEL TRANSPARENT TRAP UPDATES URL VIRTUAL WITH TTL RTABLE
174
%token	MATCH PARAMS RANDOM LEASTSTATES SRCHASH KEY CERTIFICATE PASSWORD ECDH
175
%token	EDH CURVE TICKETS
176
%token	<v.string>	STRING
177
%token  <v.number>	NUMBER
178
%type	<v.string>	hostname interface table value optstring
179
%type	<v.number>	http_type loglevel quick trap
180
%type	<v.number>	dstmode flag forwardmode retry
181
%type	<v.number>	opttls opttlsclient
182
%type	<v.number>	redirect_proto relay_proto match
183
%type	<v.number>	action ruleaf key_option
184
%type	<v.port>	port
185
%type	<v.host>	host
186
%type	<v.addr>	address
187
%type	<v.tv>		timeout
188
%type	<v.digest>	digest optdigest
189
%type	<v.table>	tablespec
190
%type	<v.dir>		dir
191
%type	<v.key>		hashkey
192
193
%%
194
195
grammar		: /* empty */
196
		| grammar include '\n'
197
		| grammar '\n'
198
		| grammar varset '\n'
199
		| grammar main '\n'
200
		| grammar rdr '\n'
201
		| grammar tabledef '\n'
202
		| grammar relay '\n'
203
		| grammar proto '\n'
204
		| grammar router '\n'
205
		| grammar error '\n'		{ file->errors++; }
206
		;
207
208
include		: INCLUDE STRING		{
209
			struct file	*nfile;
210
211
			if ((nfile = pushfile($2, 0)) == NULL) {
212
				yyerror("failed to include file %s", $2);
213
				free($2);
214
				YYERROR;
215
			}
216
			free($2);
217
218
			file = nfile;
219
			lungetc('\n');
220
		}
221
		;
222
223
ssltls		: SSL		{
224
			log_warnx("%s:%d: %s",
225
			    file->name, yylval.lineno,
226
			    "please use the \"tls\" keyword"
227
			    " instead of \"ssl\"");
228
		}
229
		| TLS
230
		;
231
232
opttls		: /*empty*/	{ $$ = 0; }
233
		| ssltls	{ $$ = 1; }
234
		;
235
236
opttlsclient	: /*empty*/	{ $$ = 0; }
237
		| WITH ssltls	{ $$ = 1; }
238
		;
239
240
http_type	: STRING	{
241
			if (strcmp("https", $1) == 0) {
242
				$$ = 1;
243
			} else if (strcmp("http", $1) == 0) {
244
				$$ = 0;
245
			} else {
246
				yyerror("invalid check type: %s", $1);
247
				free($1);
248
				YYERROR;
249
			}
250
			free($1);
251
		}
252
		;
253
254
hostname	: /* empty */		{
255
			$$ = strdup("");
256
			if ($$ == NULL)
257
				fatal("calloc");
258
		}
259
		| HOST STRING	{
260
			if (asprintf(&$$, "Host: %s\r\nConnection: close\r\n",
261
			    $2) == -1)
262
				fatal("asprintf");
263
		}
264
		;
265
266
relay_proto	: /* empty */			{ $$ = RELAY_PROTO_TCP; }
267
		| TCP				{ $$ = RELAY_PROTO_TCP; }
268
		| STRING			{
269
			if (strcmp("http", $1) == 0) {
270
				$$ = RELAY_PROTO_HTTP;
271
			} else if (strcmp("dns", $1) == 0) {
272
				$$ = RELAY_PROTO_DNS;
273
			} else {
274
				yyerror("invalid protocol type: %s", $1);
275
				free($1);
276
				YYERROR;
277
			}
278
			free($1);
279
		}
280
		;
281
282
redirect_proto	: /* empty */			{ $$ = IPPROTO_TCP; }
283
		| TCP				{ $$ = IPPROTO_TCP; }
284
		| STRING			{
285
			struct protoent	*p;
286
287
			if ((p = getprotobyname($1)) == NULL) {
288
				yyerror("invalid protocol: %s", $1);
289
				free($1);
290
				YYERROR;
291
			}
292
			free($1);
293
294
			$$ = p->p_proto;
295
		}
296
		;
297
298
eflags_l	: eflags comma eflags_l
299
		| eflags
300
		;
301
302
opteflags	: /* nothing */
303
		| eflags
304
		;
305
306
eflags		: STYLE STRING
307
		{
308
			if ((proto->style = strdup($2)) == NULL)
309
				fatal("out of memory");
310
			free($2);
311
		}
312
		;
313
314
port		: PORT STRING {
315
			char		*a, *b;
316
			int		 p[2];
317
318
			p[0] = p[1] = 0;
319
320
			a = $2;
321
			b = strchr($2, ':');
322
			if (b == NULL)
323
				$$.op = PF_OP_EQ;
324
			else {
325
				*b++ = '\0';
326
				if ((p[1] = getservice(b)) == -1) {
327
					free($2);
328
					YYERROR;
329
				}
330
				$$.op = PF_OP_RRG;
331
			}
332
			if ((p[0] = getservice(a)) == -1) {
333
				free($2);
334
				YYERROR;
335
			}
336
			$$.val[0] = p[0];
337
			$$.val[1] = p[1];
338
			free($2);
339
		}
340
		| PORT NUMBER {
341
			if ($2 <= 0 || $2 > (int)USHRT_MAX) {
342
				yyerror("invalid port: %d", $2);
343
				YYERROR;
344
			}
345
			$$.val[0] = htons($2);
346
			$$.op = PF_OP_EQ;
347
		}
348
		;
349
350
varset		: STRING '=' STRING	{
351
			char *s = $1;
352
			while (*s++) {
353
				if (isspace((unsigned char)*s)) {
354
					yyerror("macro name cannot contain "
355
					    "whitespace");
356
					YYERROR;
357
				}
358
			}
359
			if (symset($1, $3, 0) == -1)
360
				fatal("cannot store variable");
361
			free($1);
362
			free($3);
363
		}
364
		;
365
366
sendbuf		: NOTHING		{
367
			table->sendbuf = NULL;
368
		}
369
		| STRING		{
370
			table->sendbuf = strdup($1);
371
			if (table->sendbuf == NULL)
372
				fatal("out of memory");
373
			free($1);
374
		}
375
		;
376
377
main		: INTERVAL NUMBER	{
378
			if ((conf->sc_conf.interval.tv_sec = $2) < 0) {
379
				yyerror("invalid interval: %d", $2);
380
				YYERROR;
381
			}
382
		}
383
		| LOG loglevel		{
384
			conf->sc_conf.opts |= $2;
385
		}
386
		| TIMEOUT timeout	{
387
			bcopy(&$2, &conf->sc_conf.timeout,
388
			    sizeof(struct timeval));
389
		}
390
		| PREFORK NUMBER	{
391
			if ($2 <= 0 || $2 > PROC_MAX_INSTANCES) {
392
				yyerror("invalid number of preforked "
393
				    "relays: %d", $2);
394
				YYERROR;
395
			}
396
			conf->sc_conf.prefork_relay = $2;
397
		}
398
		| SNMP trap optstring	{
399
			conf->sc_conf.flags |= F_SNMP;
400
			if ($2)
401
				conf->sc_conf.flags |= F_SNMP_TRAPONLY;
402
			if ($3) {
403
				if (strlcpy(conf->sc_conf.snmp_path,
404
				    $3, sizeof(conf->sc_conf.snmp_path)) >=
405
				    sizeof(conf->sc_conf.snmp_path)) {
406
					yyerror("snmp path truncated");
407
					free($3);
408
					YYERROR;
409
				}
410
				free($3);
411
			} else
412
				(void)strlcpy(conf->sc_conf.snmp_path,
413
				    AGENTX_SOCKET,
414
				    sizeof(conf->sc_conf.snmp_path));
415
		}
416
		;
417
418
trap		: /* nothing */		{ $$ = 0; }
419
		| TRAP			{ $$ = 1; }
420
421
loglevel	: UPDATES		{ $$ = RELAYD_OPT_LOGUPDATE; }
422
		| ALL			{ $$ = RELAYD_OPT_LOGALL; }
423
		;
424
425
rdr		: REDIRECT STRING	{
426
			struct rdr *srv;
427
428
			conf->sc_conf.flags |= F_NEEDPF;
429
430
			if (!loadcfg) {
431
				free($2);
432
				YYACCEPT;
433
			}
434
435
			TAILQ_FOREACH(srv, conf->sc_rdrs, entry)
436
				if (!strcmp(srv->conf.name, $2))
437
					break;
438
			if (srv != NULL) {
439
				yyerror("redirection %s defined twice", $2);
440
				free($2);
441
				YYERROR;
442
			}
443
			if ((srv = calloc(1, sizeof (*srv))) == NULL)
444
				fatal("out of memory");
445
446
			if (strlcpy(srv->conf.name, $2,
447
			    sizeof(srv->conf.name)) >=
448
			    sizeof(srv->conf.name)) {
449
				yyerror("redirection name truncated");
450
				free($2);
451
				free(srv);
452
				YYERROR;
453
			}
454
			free($2);
455
			srv->conf.id = ++last_rdr_id;
456
			srv->conf.timeout.tv_sec = RELAY_TIMEOUT;
457
			if (last_rdr_id == INT_MAX) {
458
				yyerror("too many redirections defined");
459
				free(srv);
460
				YYERROR;
461
			}
462
			rdr = srv;
463
		} '{' optnl rdropts_l '}'	{
464
			if (rdr->table == NULL) {
465
				yyerror("redirection %s has no table",
466
				    rdr->conf.name);
467
				YYERROR;
468
			}
469
			if (TAILQ_EMPTY(&rdr->virts)) {
470
				yyerror("redirection %s has no virtual ip",
471
				    rdr->conf.name);
472
				YYERROR;
473
			}
474
			conf->sc_rdrcount++;
475
			if (rdr->backup == NULL) {
476
				rdr->conf.backup_id =
477
				    conf->sc_empty_table.conf.id;
478
				rdr->backup = &conf->sc_empty_table;
479
			} else if (rdr->backup->conf.port !=
480
			    rdr->table->conf.port) {
481
				yyerror("redirection %s uses two different "
482
				    "ports for its table and backup table",
483
				    rdr->conf.name);
484
				YYERROR;
485
			}
486
			if (!(rdr->conf.flags & F_DISABLE))
487
				rdr->conf.flags |= F_ADD;
488
			TAILQ_INSERT_TAIL(conf->sc_rdrs, rdr, entry);
489
			tableport = 0;
490
			rdr = NULL;
491
		}
492
		;
493
494
rdropts_l	: rdropts_l rdroptsl nl
495
		| rdroptsl optnl
496
		;
497
498
rdroptsl	: forwardmode TO tablespec interface	{
499
			if (hashkey != NULL) {
500
				memcpy(&rdr->conf.key,
501
				    hashkey, sizeof(rdr->conf.key));
502
				rdr->conf.flags |= F_HASHKEY;
503
				free(hashkey);
504
				hashkey = NULL;
505
			}
506
507
			switch ($1) {
508
			case FWD_NORMAL:
509
				if ($4 == NULL)
510
					break;
511
				yyerror("superfluous interface");
512
				free($4);
513
				YYERROR;
514
			case FWD_ROUTE:
515
				if ($4 != NULL)
516
					break;
517
				yyerror("missing interface to route to");
518
				free($4);
519
				YYERROR;
520
			case FWD_TRANS:
521
				yyerror("no transparent forward here");
522
				if ($4 != NULL)
523
					free($4);
524
				YYERROR;
525
			}
526
			if ($4 != NULL) {
527
				if (strlcpy($3->conf.ifname, $4,
528
				    sizeof($3->conf.ifname)) >=
529
				    sizeof($3->conf.ifname)) {
530
					yyerror("interface name truncated");
531
					free($4);
532
					YYERROR;
533
				}
534
				free($4);
535
			}
536
537
			if ($3->conf.check == CHECK_NOCHECK) {
538
				yyerror("table %s has no check", $3->conf.name);
539
				purge_table(conf, conf->sc_tables, $3);
540
				YYERROR;
541
			}
542
			if (rdr->backup) {
543
				yyerror("only one backup table is allowed");
544
				purge_table(conf, conf->sc_tables, $3);
545
				YYERROR;
546
			}
547
			if (rdr->table) {
548
				rdr->backup = $3;
549
				rdr->conf.backup_id = $3->conf.id;
550
				if (dstmode != rdr->conf.mode) {
551
					yyerror("backup table for %s with "
552
					    "different mode", rdr->conf.name);
553
					YYERROR;
554
				}
555
			} else {
556
				rdr->table = $3;
557
				rdr->conf.table_id = $3->conf.id;
558
				rdr->conf.mode = dstmode;
559
			}
560
			$3->conf.fwdmode = $1;
561
			$3->conf.rdrid = rdr->conf.id;
562
			$3->conf.flags |= F_USED;
563
		}
564
		| LISTEN ON STRING redirect_proto port interface {
565
			if (host($3, &rdr->virts,
566
			    SRV_MAX_VIRTS, &$5, $6, $4) <= 0) {
567
				yyerror("invalid virtual ip: %s", $3);
568
				free($3);
569
				free($6);
570
				YYERROR;
571
			}
572
			free($3);
573
			free($6);
574
			if (rdr->conf.port == 0)
575
				rdr->conf.port = $5.val[0];
576
			tableport = rdr->conf.port;
577
		}
578
		| DISABLE		{ rdr->conf.flags |= F_DISABLE; }
579
		| STICKYADDR		{ rdr->conf.flags |= F_STICKY; }
580
		| match PFTAG STRING {
581
			conf->sc_conf.flags |= F_NEEDPF;
582
			if (strlcpy(rdr->conf.tag, $3,
583
			    sizeof(rdr->conf.tag)) >=
584
			    sizeof(rdr->conf.tag)) {
585
				yyerror("redirection tag name truncated");
586
				free($3);
587
				YYERROR;
588
			}
589
			if ($1)
590
				rdr->conf.flags |= F_MATCH;
591
			free($3);
592
		}
593
		| SESSION TIMEOUT NUMBER		{
594
			if ((rdr->conf.timeout.tv_sec = $3) < 0) {
595
				yyerror("invalid timeout: %lld", $3);
596
				YYERROR;
597
			}
598
			if (rdr->conf.timeout.tv_sec > INT_MAX) {
599
				yyerror("timeout too large: %lld", $3);
600
				YYERROR;
601
			}
602
		}
603
		| include
604
		;
605
606
match		: /* empty */		{ $$ = 0; }
607
		| MATCH			{ $$ = 1; }
608
		;
609
610
forwardmode	: FORWARD		{ $$ = FWD_NORMAL; }
611
		| ROUTE			{ $$ = FWD_ROUTE; }
612
		| TRANSPARENT FORWARD	{ $$ = FWD_TRANS; }
613
		;
614
615
table		: '<' STRING '>'	{
616
			if (strlen($2) >= TABLE_NAME_SIZE) {
617
				yyerror("invalid table name");
618
				free($2);
619
				YYERROR;
620
			}
621
			$$ = $2;
622
		}
623
		;
624
625
tabledef	: TABLE table		{
626
			struct table *tb;
627
628
			if (!loadcfg) {
629
				free($2);
630
				YYACCEPT;
631
			}
632
633
			TAILQ_FOREACH(tb, conf->sc_tables, entry)
634
				if (!strcmp(tb->conf.name, $2))
635
					break;
636
			if (tb != NULL) {
637
				yyerror("table %s defined twice", $2);
638
				free($2);
639
				YYERROR;
640
			}
641
642
			if ((tb = calloc(1, sizeof (*tb))) == NULL)
643
				fatal("out of memory");
644
645
			if (strlcpy(tb->conf.name, $2,
646
			    sizeof(tb->conf.name)) >= sizeof(tb->conf.name)) {
647
				yyerror("table name truncated");
648
				free($2);
649
				YYERROR;
650
			}
651
			free($2);
652
653
			tb->conf.id = 0; /* will be set later */
654
			bcopy(&conf->sc_conf.timeout, &tb->conf.timeout,
655
			    sizeof(struct timeval));
656
			TAILQ_INIT(&tb->hosts);
657
			table = tb;
658
			dstmode = RELAY_DSTMODE_DEFAULT;
659
		} tabledefopts_l	{
660
			if (TAILQ_EMPTY(&table->hosts)) {
661
				yyerror("table %s has no hosts",
662
				    table->conf.name);
663
				YYERROR;
664
			}
665
			conf->sc_tablecount++;
666
			TAILQ_INSERT_TAIL(conf->sc_tables, table, entry);
667
		}
668
		;
669
670
tabledefopts_l	: tabledefopts_l tabledefopts
671
		| tabledefopts
672
		;
673
674
tabledefopts	: DISABLE		{ table->conf.flags |= F_DISABLE; }
675
		| '{' optnl tablelist_l '}'
676
		;
677
678
tablelist_l	: tablelist comma tablelist_l
679
		| tablelist optnl
680
		;
681
682
tablelist	: host			{
683
			$1->conf.tableid = table->conf.id;
684
			$1->tablename = table->conf.name;
685
			TAILQ_INSERT_TAIL(&table->hosts, $1, entry);
686
		}
687
		| include
688
		;
689
690
tablespec	: table			{
691
			struct table	*tb;
692
			if ((tb = calloc(1, sizeof (*tb))) == NULL)
693
				fatal("out of memory");
694
			if (strlcpy(tb->conf.name, $1,
695
			    sizeof(tb->conf.name)) >= sizeof(tb->conf.name)) {
696
				yyerror("table name truncated");
697
				free($1);
698
				YYERROR;
699
			}
700
			free($1);
701
			table = tb;
702
			dstmode = RELAY_DSTMODE_DEFAULT;
703
			hashkey = NULL;
704
		} tableopts_l		{
705
			struct table	*tb;
706
			if (table->conf.port == 0)
707
				table->conf.port = tableport;
708
			else
709
				table->conf.flags |= F_PORT;
710
			if ((tb = table_inherit(table)) == NULL)
711
				YYERROR;
712
			$$ = tb;
713
		}
714
		;
715
716
tableopts_l	: tableopts tableopts_l
717
		| tableopts
718
		;
719
720
tableopts	: CHECK tablecheck
721
		| port			{
722
			if ($1.op != PF_OP_EQ) {
723
				yyerror("invalid port");
724
				YYERROR;
725
			}
726
			table->conf.port = $1.val[0];
727
		}
728
		| TIMEOUT timeout	{
729
			bcopy(&$2, &table->conf.timeout,
730
			    sizeof(struct timeval));
731
		}
732
		| DEMOTE STRING		{
733
			table->conf.flags |= F_DEMOTE;
734
			if (strlcpy(table->conf.demote_group, $2,
735
			    sizeof(table->conf.demote_group))
736
			    >= sizeof(table->conf.demote_group)) {
737
				yyerror("yyparse: demote group name too long");
738
				free($2);
739
				YYERROR;
740
			}
741
			free($2);
742
			if (carp_demote_init(table->conf.demote_group, 1)
743
			    == -1) {
744
				yyerror("yyparse: error initializing group "
745
				    "'%s'", table->conf.demote_group);
746
				YYERROR;
747
			}
748
		}
749
		| INTERVAL NUMBER	{
750
			if ($2 < conf->sc_conf.interval.tv_sec ||
751
			    $2 % conf->sc_conf.interval.tv_sec) {
752
				yyerror("table interval must be "
753
				    "divisible by global interval");
754
				YYERROR;
755
			}
756
			table->conf.skip_cnt =
757
			    ($2 / conf->sc_conf.interval.tv_sec) - 1;
758
		}
759
		| MODE dstmode hashkey	{
760
			switch ($2) {
761
			case RELAY_DSTMODE_LOADBALANCE:
762
			case RELAY_DSTMODE_HASH:
763
			case RELAY_DSTMODE_SRCHASH:
764
				if (hashkey != NULL) {
765
					yyerror("key already specified");
766
					free(hashkey);
767
					YYERROR;
768
				}
769
				if ((hashkey = calloc(1,
770
				    sizeof(*hashkey))) == NULL)
771
					fatal("out of memory");
772
				memcpy(hashkey, &$3.key, sizeof(*hashkey));
773
				break;
774
			default:
775
				if ($3.keyset) {
776
					yyerror("key not supported by mode");
777
					YYERROR;
778
				}
779
				hashkey = NULL;
780
				break;
781
			}
782
783
			switch ($2) {
784
			case RELAY_DSTMODE_LOADBALANCE:
785
			case RELAY_DSTMODE_HASH:
786
				if (rdr != NULL) {
787
					yyerror("mode not supported "
788
					    "for redirections");
789
					YYERROR;
790
				}
791
				/* FALLTHROUGH */
792
			case RELAY_DSTMODE_RANDOM:
793
			case RELAY_DSTMODE_ROUNDROBIN:
794
			case RELAY_DSTMODE_SRCHASH:
795
				dstmode = $2;
796
				break;
797
			case RELAY_DSTMODE_LEASTSTATES:
798
				if (rdr == NULL) {
799
					yyerror("mode not supported "
800
					    "for relays");
801
					YYERROR;
802
				}
803
				dstmode = $2;
804
				break;
805
			}
806
		}
807
		;
808
809
/* should be in sync with sbin/pfctl/parse.y's hashkey */
810
hashkey		: /* empty */		{
811
			$$.keyset = 0;
812
			$$.key.data[0] = arc4random();
813
			$$.key.data[1] = arc4random();
814
			$$.key.data[2] = arc4random();
815
			$$.key.data[3] = arc4random();
816
		}
817
		| STRING		{
818
			/* manual key configuration */
819
			$$.keyset = 1;
820
821
			if (!strncmp($1, "0x", 2)) {
822
				if (strlen($1) != 34) {
823
					free($1);
824
					yyerror("hex key must be 128 bits "
825
					    "(32 hex digits) long");
826
					YYERROR;
827
				}
828
829
				if (sscanf($1, "0x%8x%8x%8x%8x",
830
				    &$$.key.data[0], &$$.key.data[1],
831
				    &$$.key.data[2], &$$.key.data[3]) != 4) {
832
					free($1);
833
					yyerror("invalid hex key");
834
					YYERROR;
835
				}
836
			} else {
837
				MD5_CTX	context;
838
839
				MD5Init(&context);
840
				MD5Update(&context, (unsigned char *)$1,
841
				    strlen($1));
842
				MD5Final((unsigned char *)$$.key.data,
843
				    &context);
844
				HTONL($$.key.data[0]);
845
				HTONL($$.key.data[1]);
846
				HTONL($$.key.data[2]);
847
				HTONL($$.key.data[3]);
848
			}
849
			free($1);
850
		}
851
		;
852
853
tablecheck	: ICMP			{ table->conf.check = CHECK_ICMP; }
854
		| TCP			{ table->conf.check = CHECK_TCP; }
855
		| ssltls		{
856
			table->conf.check = CHECK_TCP;
857
			conf->sc_conf.flags |= F_TLS;
858
			table->conf.flags |= F_TLS;
859
		}
860
		| http_type STRING hostname CODE NUMBER {
861
			if ($1) {
862
				conf->sc_conf.flags |= F_TLS;
863
				table->conf.flags |= F_TLS;
864
			}
865
			table->conf.check = CHECK_HTTP_CODE;
866
			if ((table->conf.retcode = $5) <= 0) {
867
				yyerror("invalid HTTP code: %d", $5);
868
				free($2);
869
				free($3);
870
				YYERROR;
871
			}
872
			if (asprintf(&table->sendbuf,
873
			    "HEAD %s HTTP/1.%c\r\n%s\r\n",
874
			    $2, strlen($3) ? '1' : '0', $3) == -1)
875
				fatal("asprintf");
876
			free($2);
877
			free($3);
878
			if (table->sendbuf == NULL)
879
				fatal("out of memory");
880
		}
881
		| http_type STRING hostname digest {
882
			if ($1) {
883
				conf->sc_conf.flags |= F_TLS;
884
				table->conf.flags |= F_TLS;
885
			}
886
			table->conf.check = CHECK_HTTP_DIGEST;
887
			if (asprintf(&table->sendbuf,
888
			    "GET %s HTTP/1.%c\r\n%s\r\n",
889
			    $2, strlen($3) ? '1' : '0', $3) == -1)
890
				fatal("asprintf");
891
			free($2);
892
			free($3);
893
			if (table->sendbuf == NULL)
894
				fatal("out of memory");
895
			if (strlcpy(table->conf.digest, $4.digest,
896
			    sizeof(table->conf.digest)) >=
897
			    sizeof(table->conf.digest)) {
898
				yyerror("digest truncated");
899
				free($4.digest);
900
				YYERROR;
901
			}
902
			table->conf.digest_type = $4.type;
903
			free($4.digest);
904
		}
905
		| SEND sendbuf EXPECT STRING opttls {
906
			table->conf.check = CHECK_SEND_EXPECT;
907
			if ($5) {
908
				conf->sc_conf.flags |= F_TLS;
909
				table->conf.flags |= F_TLS;
910
			}
911
			if (strlcpy(table->conf.exbuf, $4,
912
			    sizeof(table->conf.exbuf))
913
			    >= sizeof(table->conf.exbuf)) {
914
				yyerror("yyparse: expect buffer truncated");
915
				free($4);
916
				YYERROR;
917
			}
918
			translate_string(table->conf.exbuf);
919
			free($4);
920
		}
921
		| SCRIPT STRING {
922
			table->conf.check = CHECK_SCRIPT;
923
			if (strlcpy(table->conf.path, $2,
924
			    sizeof(table->conf.path)) >=
925
			    sizeof(table->conf.path)) {
926
				yyerror("script path truncated");
927
				free($2);
928
				YYERROR;
929
			}
930
			conf->sc_conf.flags |= F_SCRIPT;
931
			free($2);
932
		}
933
		;
934
935
digest		: DIGEST STRING
936
		{
937
			switch (strlen($2)) {
938
			case 40:
939
				$$.type = DIGEST_SHA1;
940
				break;
941
			case 32:
942
				$$.type = DIGEST_MD5;
943
				break;
944
			default:
945
				yyerror("invalid http digest");
946
				free($2);
947
				YYERROR;
948
			}
949
			$$.digest = $2;
950
		}
951
		;
952
953
optdigest	: digest			{
954
			$$.digest = $1.digest;
955
			$$.type = $1.type;
956
		}
957
		| STRING			{
958
			$$.digest = $1;
959
			$$.type = DIGEST_NONE;
960
		}
961
		;
962
963
proto		: relay_proto PROTO STRING	{
964
			struct protocol *p;
965
966
			if (!loadcfg) {
967
				free($3);
968
				YYACCEPT;
969
			}
970
971
			if (strcmp($3, "default") == 0) {
972
				p = &conf->sc_proto_default;
973
			} else {
974
				TAILQ_FOREACH(p, conf->sc_protos, entry)
975
					if (!strcmp(p->name, $3))
976
						break;
977
			}
978
			if (p != NULL) {
979
				yyerror("protocol %s defined twice", $3);
980
				free($3);
981
				YYERROR;
982
			}
983
			if ((p = calloc(1, sizeof (*p))) == NULL)
984
				fatal("out of memory");
985
986
			if (strlcpy(p->name, $3, sizeof(p->name)) >=
987
			    sizeof(p->name)) {
988
				yyerror("protocol name truncated");
989
				free($3);
990
				free(p);
991
				YYERROR;
992
			}
993
			free($3);
994
			p->id = ++last_proto_id;
995
			p->type = $1;
996
			p->tcpflags = TCPFLAG_DEFAULT;
997
			p->tlsflags = TLSFLAG_DEFAULT;
998
			p->tcpbacklog = RELAY_BACKLOG;
999
			TAILQ_INIT(&p->rules);
1000
			(void)strlcpy(p->tlsciphers, TLSCIPHERS_DEFAULT,
1001
			    sizeof(p->tlsciphers));
1002
			(void)strlcpy(p->tlsecdhcurve, TLSECDHCURVE_DEFAULT,
1003
			    sizeof(p->tlsecdhcurve));
1004
			(void)strlcpy(p->tlsdhparams, TLSDHPARAM_DEFAULT,
1005
			    sizeof(p->tlsdhparams));
1006
			if (last_proto_id == INT_MAX) {
1007
				yyerror("too many protocols defined");
1008
				free(p);
1009
				YYERROR;
1010
			}
1011
			proto = p;
1012
		} protopts_n			{
1013
			conf->sc_protocount++;
1014
1015
			if ((proto->tlsflags & TLSFLAG_VERSION) == 0) {
1016
				yyerror("invalid TLS protocol");
1017
				YYERROR;
1018
			}
1019
1020
			TAILQ_INSERT_TAIL(conf->sc_protos, proto, entry);
1021
		}
1022
		;
1023
1024
protopts_n	: /* empty */
1025
		| '{' '}'
1026
		| '{' optnl protopts_l '}'
1027
		;
1028
1029
protopts_l	: protopts_l protoptsl nl
1030
		| protoptsl optnl
1031
		;
1032
1033
protoptsl	: ssltls tlsflags
1034
		| ssltls '{' tlsflags_l '}'
1035
		| TCP tcpflags
1036
		| TCP '{' tcpflags_l '}'
1037
		| RETURN ERROR opteflags	{ proto->flags |= F_RETURN; }
1038
		| RETURN ERROR '{' eflags_l '}'	{ proto->flags |= F_RETURN; }
1039
		| filterrule
1040
		| include
1041
		;
1042
1043
tcpflags_l	: tcpflags comma tcpflags_l
1044
		| tcpflags
1045
		;
1046
1047
tcpflags	: SACK			{ proto->tcpflags |= TCPFLAG_SACK; }
1048
		| NO SACK		{ proto->tcpflags |= TCPFLAG_NSACK; }
1049
		| NODELAY		{ proto->tcpflags |= TCPFLAG_NODELAY; }
1050
		| NO NODELAY		{ proto->tcpflags |= TCPFLAG_NNODELAY; }
1051
		| SPLICE		{ /* default */ }
1052
		| NO SPLICE		{ proto->tcpflags |= TCPFLAG_NSPLICE; }
1053
		| BACKLOG NUMBER	{
1054
			if ($2 < 0 || $2 > RELAY_MAX_SESSIONS) {
1055
				yyerror("invalid backlog: %d", $2);
1056
				YYERROR;
1057
			}
1058
			proto->tcpbacklog = $2;
1059
		}
1060
		| SOCKET BUFFER NUMBER	{
1061
			proto->tcpflags |= TCPFLAG_BUFSIZ;
1062
			if ((proto->tcpbufsiz = $3) < 0) {
1063
				yyerror("invalid socket buffer size: %d", $3);
1064
				YYERROR;
1065
			}
1066
		}
1067
		| IP STRING NUMBER	{
1068
			if ($3 < 0) {
1069
				yyerror("invalid ttl: %d", $3);
1070
				free($2);
1071
				YYERROR;
1072
			}
1073
			if (strcasecmp("ttl", $2) == 0) {
1074
				proto->tcpflags |= TCPFLAG_IPTTL;
1075
				proto->tcpipttl = $3;
1076
			} else if (strcasecmp("minttl", $2) == 0) {
1077
				proto->tcpflags |= TCPFLAG_IPMINTTL;
1078
				proto->tcpipminttl = $3;
1079
			} else {
1080
				yyerror("invalid TCP/IP flag: %s", $2);
1081
				free($2);
1082
				YYERROR;
1083
			}
1084
			free($2);
1085
		}
1086
		;
1087
1088
tlsflags_l	: tlsflags comma tlsflags_l
1089
		| tlsflags
1090
		;
1091
1092
tlsflags	: SESSION TICKETS { proto->tickets = 1; }
1093
		| NO SESSION TICKETS { proto->tickets = 0; }
1094
		| CIPHERS STRING		{
1095
			if (strlcpy(proto->tlsciphers, $2,
1096
			    sizeof(proto->tlsciphers)) >=
1097
			    sizeof(proto->tlsciphers)) {
1098
				yyerror("tlsciphers truncated");
1099
				free($2);
1100
				YYERROR;
1101
			}
1102
			free($2);
1103
		}
1104
		| NO EDH			{
1105
			(void)strlcpy(proto->tlsdhparams, "none",
1106
			    sizeof(proto->tlsdhparams));
1107
		}
1108
		| EDH			{
1109
			(void)strlcpy(proto->tlsdhparams, "auto",
1110
			    sizeof(proto->tlsdhparams));
1111
		}
1112
		| EDH PARAMS STRING		{
1113
			struct tls_config	*tls_cfg;
1114
			if ((tls_cfg = tls_config_new()) == NULL) {
1115
				yyerror("tls_config_new failed");
1116
				free($3);
1117
				YYERROR;
1118
			}
1119
			if (tls_config_set_dheparams(tls_cfg, $3) != 0) {
1120
				yyerror("tls edh params %s: %s", $3,
1121
				    tls_config_error(tls_cfg));
1122
				tls_config_free(tls_cfg);
1123
				free($3);
1124
				YYERROR;
1125
			}
1126
			tls_config_free(tls_cfg);
1127
			if (strlcpy(proto->tlsdhparams, $3,
1128
			    sizeof(proto->tlsdhparams)) >=
1129
			    sizeof(proto->tlsdhparams)) {
1130
				yyerror("tls edh truncated");
1131
				free($3);
1132
				YYERROR;
1133
			}
1134
			free($3);
1135
		}
1136
		| NO ECDH			{
1137
			(void)strlcpy(proto->tlsecdhcurve, "none",
1138
			    sizeof(proto->tlsecdhcurve));
1139
		}
1140
		| ECDH			{
1141
			(void)strlcpy(proto->tlsecdhcurve, "auto",
1142
			    sizeof(proto->tlsecdhcurve));
1143
		}
1144
		| ECDH CURVE STRING			{
1145
			struct tls_config	*tls_cfg;
1146
			if ((tls_cfg = tls_config_new()) == NULL) {
1147
				yyerror("tls_config_new failed");
1148
				free($3);
1149
				YYERROR;
1150
			}
1151
			if (tls_config_set_ecdhecurve(tls_cfg, $3) != 0) {
1152
				yyerror("tls ecdh curve %s: %s", $3,
1153
				    tls_config_error(tls_cfg));
1154
				tls_config_free(tls_cfg);
1155
				free($3);
1156
				YYERROR;
1157
			}
1158
			tls_config_free(tls_cfg);
1159
			if (strlcpy(proto->tlsecdhcurve, $3,
1160
			    sizeof(proto->tlsecdhcurve)) >=
1161
			    sizeof(proto->tlsecdhcurve)) {
1162
				yyerror("tls ecdh truncated");
1163
				free($3);
1164
				YYERROR;
1165
			}
1166
			free($3);
1167
		}
1168
		| CA FILENAME STRING		{
1169
			if (strlcpy(proto->tlsca, $3,
1170
			    sizeof(proto->tlsca)) >=
1171
			    sizeof(proto->tlsca)) {
1172
				yyerror("tlsca truncated");
1173
				free($3);
1174
				YYERROR;
1175
			}
1176
			free($3);
1177
		}
1178
		| CA KEY STRING PASSWORD STRING	{
1179
			if (strlcpy(proto->tlscakey, $3,
1180
			    sizeof(proto->tlscakey)) >=
1181
			    sizeof(proto->tlscakey)) {
1182
				yyerror("tlscakey truncated");
1183
				free($3);
1184
				free($5);
1185
				YYERROR;
1186
			}
1187
			if ((proto->tlscapass = strdup($5)) == NULL) {
1188
				yyerror("tlscapass");
1189
				free($3);
1190
				free($5);
1191
				YYERROR;
1192
			}
1193
			free($3);
1194
			free($5);
1195
		}
1196
		| CA CERTIFICATE STRING		{
1197
			if (strlcpy(proto->tlscacert, $3,
1198
			    sizeof(proto->tlscacert)) >=
1199
			    sizeof(proto->tlscacert)) {
1200
				yyerror("tlscacert truncated");
1201
				free($3);
1202
				YYERROR;
1203
			}
1204
			free($3);
1205
		}
1206
		| NO flag			{ proto->tlsflags &= ~($2); }
1207
		| flag				{ proto->tlsflags |= $1; }
1208
		;
1209
1210
flag		: STRING			{
1211
			if (strcmp("sslv3", $1) == 0)
1212
				$$ = TLSFLAG_SSLV3;
1213
			else if (strcmp("tlsv1", $1) == 0)
1214
				$$ = TLSFLAG_TLSV1;
1215
			else if (strcmp("tlsv1.0", $1) == 0)
1216
				$$ = TLSFLAG_TLSV1_0;
1217
			else if (strcmp("tlsv1.1", $1) == 0)
1218
				$$ = TLSFLAG_TLSV1_1;
1219
			else if (strcmp("tlsv1.2", $1) == 0)
1220
				$$ = TLSFLAG_TLSV1_2;
1221
			else if (strcmp("cipher-server-preference", $1) == 0)
1222
				$$ = TLSFLAG_CIPHER_SERVER_PREF;
1223
			else if (strcmp("client-renegotiation", $1) == 0)
1224
				$$ = TLSFLAG_CLIENT_RENEG;
1225
			else {
1226
				yyerror("invalid TLS flag: %s", $1);
1227
				free($1);
1228
				YYERROR;
1229
			}
1230
			free($1);
1231
		}
1232
		;
1233
1234
filterrule	: action dir quick ruleaf rulesrc ruledst {
1235
			if ((rule = calloc(1, sizeof(*rule))) == NULL)
1236
				fatal("out of memory");
1237
1238
			rule->rule_action = $1;
1239
			rule->rule_proto = proto->type;
1240
			rule->rule_dir = $2;
1241
			rule->rule_flags |= $3;
1242
			rule->rule_af = $4;
1243
1244
			rulefile = NULL;
1245
		} ruleopts_l {
1246
			if (rule_add(proto, rule, rulefile) == -1) {
1247
				if (rulefile == NULL) {
1248
					yyerror("failed to load rule");
1249
				} else {
1250
					yyerror("failed to load rules from %s",
1251
					    rulefile);
1252
					free(rulefile);
1253
				}
1254
				rule_free(rule);
1255
				free(rule);
1256
				YYERROR;
1257
			}
1258
			if (rulefile)
1259
				free(rulefile);
1260
			rulefile = NULL;
1261
			rule = NULL;
1262
			keytype = KEY_TYPE_NONE;
1263
		}
1264
		;
1265
1266
action		: PASS				{ $$ = RULE_ACTION_PASS; }
1267
		| BLOCK				{ $$ = RULE_ACTION_BLOCK; }
1268
		| MATCH				{ $$ = RULE_ACTION_MATCH; }
1269
		;
1270
1271
dir		: /* empty */			{
1272
			$$ = dir = RELAY_DIR_REQUEST;
1273
		}
1274
		| REQUEST			{
1275
			$$ = dir = RELAY_DIR_REQUEST;
1276
		}
1277
		| RESPONSE			{
1278
			$$ = dir = RELAY_DIR_RESPONSE;
1279
		}
1280
		;
1281
1282
quick		: /* empty */			{ $$ = 0; }
1283
		| QUICK				{ $$ = RULE_FLAG_QUICK; }
1284
		;
1285
1286
ruleaf		: /* empty */			{ $$ = AF_UNSPEC; }
1287
		| INET6				{ $$ = AF_INET6; }
1288
		| INET				{ $$ = AF_INET; }
1289
		;
1290
1291
rulesrc		: /* XXX */
1292
		;
1293
1294
ruledst		: /* XXX */
1295
		;
1296
1297
ruleopts_l	: /* empty */
1298
		| ruleopts_t
1299
		;
1300
1301
ruleopts_t	: ruleopts ruleopts_t
1302
		| ruleopts
1303
		;
1304
1305
ruleopts	: METHOD STRING					{
1306
			u_int	id;
1307
			if ((id = relay_httpmethod_byname($2)) ==
1308
			    HTTP_METHOD_NONE) {
1309
				yyerror("unknown HTTP method currently not "
1310
				    "supported");
1311
				free($2);
1312
				YYERROR;
1313
			}
1314
			rule->rule_method = id;
1315
			free($2);
1316
		}
1317
		| COOKIE key_option STRING value		{
1318
			keytype = KEY_TYPE_COOKIE;
1319
			rule->rule_kv[keytype].kv_key = strdup($3);
1320
			rule->rule_kv[keytype].kv_option = $2;
1321
			rule->rule_kv[keytype].kv_value = (($4 != NULL) ?
1322
			    strdup($4) : strdup("*"));
1323
			if (rule->rule_kv[keytype].kv_key == NULL ||
1324
			    rule->rule_kv[keytype].kv_value == NULL)
1325
				fatal("out of memory");
1326
			free($3);
1327
			if ($4)
1328
				free($4);
1329
			rule->rule_kv[keytype].kv_type = keytype;
1330
		}
1331
		| COOKIE key_option				{
1332
			keytype = KEY_TYPE_COOKIE;
1333
			rule->rule_kv[keytype].kv_option = $2;
1334
			rule->rule_kv[keytype].kv_type = keytype;
1335
		}
1336
		| HEADER key_option STRING value		{
1337
			keytype = KEY_TYPE_HEADER;
1338
			memset(&rule->rule_kv[keytype], 0,
1339
			    sizeof(rule->rule_kv[keytype]));
1340
			rule->rule_kv[keytype].kv_option = $2;
1341
			rule->rule_kv[keytype].kv_key = strdup($3);
1342
			rule->rule_kv[keytype].kv_value = (($4 != NULL) ?
1343
			    strdup($4) : strdup("*"));
1344
			if (rule->rule_kv[keytype].kv_key == NULL ||
1345
			    rule->rule_kv[keytype].kv_value == NULL)
1346
				fatal("out of memory");
1347
			free($3);
1348
			if ($4)
1349
				free($4);
1350
			rule->rule_kv[keytype].kv_type = keytype;
1351
		}
1352
		| HEADER key_option				{
1353
			keytype = KEY_TYPE_HEADER;
1354
			rule->rule_kv[keytype].kv_option = $2;
1355
			rule->rule_kv[keytype].kv_type = keytype;
1356
		}
1357
		| PATH key_option STRING value			{
1358
			keytype = KEY_TYPE_PATH;
1359
			rule->rule_kv[keytype].kv_option = $2;
1360
			rule->rule_kv[keytype].kv_key = strdup($3);
1361
			rule->rule_kv[keytype].kv_value = (($4 != NULL) ?
1362
			    strdup($4) : strdup("*"));
1363
			if (rule->rule_kv[keytype].kv_key == NULL ||
1364
			    rule->rule_kv[keytype].kv_value == NULL)
1365
				fatal("out of memory");
1366
			free($3);
1367
			if ($4)
1368
				free($4);
1369
			rule->rule_kv[keytype].kv_type = keytype;
1370
		}
1371
		| PATH key_option				{
1372
			keytype = KEY_TYPE_PATH;
1373
			rule->rule_kv[keytype].kv_option = $2;
1374
			rule->rule_kv[keytype].kv_type = keytype;
1375
		}
1376
		| QUERYSTR key_option STRING value		{
1377
			switch ($2) {
1378
			case KEY_OPTION_APPEND:
1379
			case KEY_OPTION_SET:
1380
			case KEY_OPTION_REMOVE:
1381
				yyerror("combining query type and the given "
1382
				    "option is not supported");
1383
				free($3);
1384
				if ($4)
1385
					free($4);
1386
				YYERROR;
1387
				break;
1388
			}
1389
			keytype = KEY_TYPE_QUERY;
1390
			rule->rule_kv[keytype].kv_option = $2;
1391
			rule->rule_kv[keytype].kv_key = strdup($3);
1392
			rule->rule_kv[keytype].kv_value = (($4 != NULL) ?
1393
			    strdup($4) : strdup("*"));
1394
			if (rule->rule_kv[keytype].kv_key == NULL ||
1395
			    rule->rule_kv[keytype].kv_value == NULL)
1396
				fatal("out of memory");
1397
			free($3);
1398
			if ($4)
1399
				free($4);
1400
			rule->rule_kv[keytype].kv_type = keytype;
1401
		}
1402
		| QUERYSTR key_option				{
1403
			switch ($2) {
1404
			case KEY_OPTION_APPEND:
1405
			case KEY_OPTION_SET:
1406
			case KEY_OPTION_REMOVE:
1407
				yyerror("combining query type and the given "
1408
				    "option is not supported");
1409
				YYERROR;
1410
				break;
1411
			}
1412
			keytype = KEY_TYPE_QUERY;
1413
			rule->rule_kv[keytype].kv_option = $2;
1414
			rule->rule_kv[keytype].kv_type = keytype;
1415
		}
1416
		| URL key_option optdigest value			{
1417
			switch ($2) {
1418
			case KEY_OPTION_APPEND:
1419
			case KEY_OPTION_SET:
1420
			case KEY_OPTION_REMOVE:
1421
				yyerror("combining url type and the given "
1422
				"option is not supported");
1423
				free($3.digest);
1424
				free($4);
1425
				YYERROR;
1426
				break;
1427
			}
1428
			keytype = KEY_TYPE_URL;
1429
			rule->rule_kv[keytype].kv_option = $2;
1430
			rule->rule_kv[keytype].kv_key = strdup($3.digest);
1431
			rule->rule_kv[keytype].kv_digest = $3.type;
1432
			rule->rule_kv[keytype].kv_value = (($4 != NULL) ?
1433
			    strdup($4) : strdup("*"));
1434
			if (rule->rule_kv[keytype].kv_key == NULL ||
1435
			    rule->rule_kv[keytype].kv_value == NULL)
1436
				fatal("out of memory");
1437
			free($3.digest);
1438
			if ($4)
1439
				free($4);
1440
			rule->rule_kv[keytype].kv_type = keytype;
1441
		}
1442
		| URL key_option					{
1443
			switch ($2) {
1444
			case KEY_OPTION_APPEND:
1445
			case KEY_OPTION_SET:
1446
			case KEY_OPTION_REMOVE:
1447
				yyerror("combining url type and the given "
1448
				    "option is not supported");
1449
				YYERROR;
1450
				break;
1451
			}
1452
			keytype = KEY_TYPE_URL;
1453
			rule->rule_kv[keytype].kv_option = $2;
1454
			rule->rule_kv[keytype].kv_type = keytype;
1455
		}
1456
		| FORWARD TO table				{
1457
			if (table_findbyname(conf, $3) == NULL) {
1458
				yyerror("undefined forward table");
1459
				free($3);
1460
				YYERROR;
1461
			}
1462
			if (strlcpy(rule->rule_tablename, $3,
1463
			    sizeof(rule->rule_tablename)) >=
1464
			    sizeof(rule->rule_tablename)) {
1465
				yyerror("invalid forward table name");
1466
				free($3);
1467
				YYERROR;
1468
			}
1469
			free($3);
1470
		}
1471
		| TAG STRING					{
1472
			tag = tag_name2id($2);
1473
			if (rule->rule_tag) {
1474
				yyerror("tag already defined");
1475
				free($2);
1476
				rule_free(rule);
1477
				free(rule);
1478
				YYERROR;
1479
			}
1480
			if (tag == 0) {
1481
				yyerror("invalid tag");
1482
				free($2);
1483
				rule_free(rule);
1484
				free(rule);
1485
				YYERROR;
1486
			}
1487
			rule->rule_tag = tag;
1488
			if (strlcpy(rule->rule_tagname, $2,
1489
			    sizeof(rule->rule_tagname)) >=
1490
			    sizeof(rule->rule_tagname)) {
1491
				yyerror("tag truncated");
1492
				free($2);
1493
				rule_free(rule);
1494
				free(rule);
1495
				YYERROR;
1496
			}
1497
			free($2);
1498
		}
1499
		| NO TAG					{
1500
			if (tag == 0) {
1501
				yyerror("no tag defined");
1502
				YYERROR;
1503
			}
1504
			rule->rule_tag = -1;
1505
			memset(rule->rule_tagname, 0,
1506
			    sizeof(rule->rule_tagname));
1507
		}
1508
		| TAGGED STRING					{
1509
			tagged = tag_name2id($2);
1510
			if (rule->rule_tagged) {
1511
				yyerror("tagged already defined");
1512
				free($2);
1513
				rule_free(rule);
1514
				free(rule);
1515
				YYERROR;
1516
			}
1517
			if (tagged == 0) {
1518
				yyerror("invalid tag");
1519
				free($2);
1520
				rule_free(rule);
1521
				free(rule);
1522
				YYERROR;
1523
			}
1524
			rule->rule_tagged = tagged;
1525
			if (strlcpy(rule->rule_taggedname, $2,
1526
			    sizeof(rule->rule_taggedname)) >=
1527
			    sizeof(rule->rule_taggedname)) {
1528
				yyerror("tagged truncated");
1529
				free($2);
1530
				rule_free(rule);
1531
				free(rule);
1532
				YYERROR;
1533
			}
1534
			free($2);
1535
		}
1536
		| LABEL STRING					{
1537
			label = label_name2id($2);
1538
			if (rule->rule_label) {
1539
				yyerror("label already defined");
1540
				free($2);
1541
				rule_free(rule);
1542
				free(rule);
1543
				YYERROR;
1544
			}
1545
			if (label == 0) {
1546
				yyerror("invalid label");
1547
				free($2);
1548
				rule_free(rule);
1549
				free(rule);
1550
				YYERROR;
1551
			}
1552
			rule->rule_label = label;
1553
			if (strlcpy(rule->rule_labelname, $2,
1554
			    sizeof(rule->rule_labelname)) >=
1555
			    sizeof(rule->rule_labelname)) {
1556
				yyerror("label truncated");
1557
				free($2);
1558
				rule_free(rule);
1559
				free(rule);
1560
				YYERROR;
1561
			}
1562
			free($2);
1563
		}
1564
		| NO LABEL					{
1565
			if (label == 0) {
1566
				yyerror("no label defined");
1567
				YYERROR;
1568
			}
1569
			rule->rule_label = -1;
1570
			memset(rule->rule_labelname, 0,
1571
			    sizeof(rule->rule_labelname));
1572
		}
1573
		| FILENAME STRING value				{
1574
			if (rulefile != NULL) {
1575
				yyerror("only one file per rule supported");
1576
				free($2);
1577
				free($3);
1578
				rule_free(rule);
1579
				free(rule);
1580
				YYERROR;
1581
			}
1582
			if ($3) {
1583
				if ((rule->rule_kv[keytype].kv_value =
1584
				    strdup($3)) == NULL)
1585
					fatal("out of memory");
1586
				free($3);
1587
			} else
1588
				rule->rule_kv[keytype].kv_value = NULL;
1589
			rulefile = $2;
1590
		}
1591
		;
1592
1593
value		: /* empty */		{ $$ = NULL; }
1594
		| VALUE STRING		{ $$ = $2; }
1595
		;
1596
1597
key_option	: /* empty */		{ $$ = KEY_OPTION_NONE; }
1598
		| APPEND		{ $$ = KEY_OPTION_APPEND; }
1599
		| SET			{ $$ = KEY_OPTION_SET; }
1600
		| REMOVE		{ $$ = KEY_OPTION_REMOVE; }
1601
		| HASH			{ $$ = KEY_OPTION_HASH; }
1602
		| LOG			{ $$ = KEY_OPTION_LOG; }
1603
		;
1604
1605
relay		: RELAY STRING	{
1606
			struct relay *r;
1607
1608
			if (!loadcfg) {
1609
				free($2);
1610
				YYACCEPT;
1611
			}
1612
1613
			TAILQ_FOREACH(r, conf->sc_relays, rl_entry)
1614
				if (!strcmp(r->rl_conf.name, $2))
1615
					break;
1616
			if (r != NULL) {
1617
				yyerror("relay %s defined twice", $2);
1618
				free($2);
1619
				YYERROR;
1620
			}
1621
			TAILQ_INIT(&relays);
1622
1623
			if ((r = calloc(1, sizeof (*r))) == NULL)
1624
				fatal("out of memory");
1625
1626
			if (strlcpy(r->rl_conf.name, $2,
1627
			    sizeof(r->rl_conf.name)) >=
1628
			    sizeof(r->rl_conf.name)) {
1629
				yyerror("relay name truncated");
1630
				free($2);
1631
				free(r);
1632
				YYERROR;
1633
			}
1634
			free($2);
1635
			if (relay_id(r) == -1) {
1636
				yyerror("too many relays defined");
1637
				free(r);
1638
				YYERROR;
1639
			}
1640
			r->rl_conf.timeout.tv_sec = RELAY_TIMEOUT;
1641
			r->rl_proto = NULL;
1642
			r->rl_conf.proto = EMPTY_ID;
1643
			r->rl_conf.dstretry = 0;
1644
			TAILQ_INIT(&r->rl_tables);
1645
			if (last_relay_id == INT_MAX) {
1646
				yyerror("too many relays defined");
1647
				free(r);
1648
				YYERROR;
1649
			}
1650
			dstmode = RELAY_DSTMODE_DEFAULT;
1651
			rlay = r;
1652
		} '{' optnl relayopts_l '}'	{
1653
			struct relay	*r;
1654
1655
			if (rlay->rl_conf.ss.ss_family == AF_UNSPEC) {
1656
				yyerror("relay %s has no listener",
1657
				    rlay->rl_conf.name);
1658
				YYERROR;
1659
			}
1660
			if ((rlay->rl_conf.flags & (F_NATLOOK|F_DIVERT)) ==
1661
			    (F_NATLOOK|F_DIVERT)) {
1662
				yyerror("relay %s with conflicting nat lookup "
1663
				    "and peer options", rlay->rl_conf.name);
1664
				YYERROR;
1665
			}
1666
			if ((rlay->rl_conf.flags & (F_NATLOOK|F_DIVERT)) == 0 &&
1667
			    rlay->rl_conf.dstss.ss_family == AF_UNSPEC &&
1668
			    TAILQ_EMPTY(&rlay->rl_tables)) {
1669
				yyerror("relay %s has no target, rdr, "
1670
				    "or table", rlay->rl_conf.name);
1671
				YYERROR;
1672
			}
1673
			if (rlay->rl_conf.proto == EMPTY_ID) {
1674
				rlay->rl_proto = &conf->sc_proto_default;
1675
				rlay->rl_conf.proto = conf->sc_proto_default.id;
1676
			}
1677
			if (relay_load_certfiles(rlay) == -1) {
1678
				yyerror("cannot load certificates for relay %s",
1679
				    rlay->rl_conf.name);
1680
				YYERROR;
1681
			}
1682
			conf->sc_relaycount++;
1683
			SPLAY_INIT(&rlay->rl_sessions);
1684
			TAILQ_INSERT_TAIL(conf->sc_relays, rlay, rl_entry);
1685
1686
			tableport = 0;
1687
1688
			while ((r = TAILQ_FIRST(&relays)) != NULL) {
1689
				TAILQ_REMOVE(&relays, r, rl_entry);
1690
				if (relay_inherit(rlay, r) == NULL) {
1691
					YYERROR;
1692
				}
1693
			}
1694
			rlay = NULL;
1695
		}
1696
		;
1697
1698
relayopts_l	: relayopts_l relayoptsl nl
1699
		| relayoptsl optnl
1700
		;
1701
1702
relayoptsl	: LISTEN ON STRING port opttls {
1703
			struct addresslist	 al;
1704
			struct address		*h;
1705
			struct relay		*r;
1706
1707
			if (rlay->rl_conf.ss.ss_family != AF_UNSPEC) {
1708
				if ((r = calloc(1, sizeof (*r))) == NULL)
1709
					fatal("out of memory");
1710
				TAILQ_INSERT_TAIL(&relays, r, rl_entry);
1711
			} else
1712
				r = rlay;
1713
			if ($4.op != PF_OP_EQ) {
1714
				yyerror("invalid port");
1715
				free($3);
1716
				YYERROR;
1717
			}
1718
1719
			TAILQ_INIT(&al);
1720
			if (host($3, &al, 1, &$4, NULL, -1) <= 0) {
1721
				yyerror("invalid listen ip: %s", $3);
1722
				free($3);
1723
				YYERROR;
1724
			}
1725
			free($3);
1726
			h = TAILQ_FIRST(&al);
1727
			bcopy(&h->ss, &r->rl_conf.ss, sizeof(r->rl_conf.ss));
1728
			r->rl_conf.port = h->port.val[0];
1729
			if ($5) {
1730
				r->rl_conf.flags |= F_TLS;
1731
				conf->sc_conf.flags |= F_TLS;
1732
			}
1733
			tableport = h->port.val[0];
1734
			host_free(&al);
1735
		}
1736
		| forwardmode opttlsclient TO forwardspec dstaf {
1737
			rlay->rl_conf.fwdmode = $1;
1738
			if ($1 == FWD_ROUTE) {
1739
				yyerror("no route for relays");
1740
				YYERROR;
1741
			}
1742
			if ($2) {
1743
				rlay->rl_conf.flags |= F_TLSCLIENT;
1744
				conf->sc_conf.flags |= F_TLSCLIENT;
1745
			}
1746
		}
1747
		| SESSION TIMEOUT NUMBER		{
1748
			if ((rlay->rl_conf.timeout.tv_sec = $3) < 0) {
1749
				yyerror("invalid timeout: %lld", $3);
1750
				YYERROR;
1751
			}
1752
			if (rlay->rl_conf.timeout.tv_sec > INT_MAX) {
1753
				yyerror("timeout too large: %lld", $3);
1754
				YYERROR;
1755
			}
1756
		}
1757
		| PROTO STRING			{
1758
			struct protocol *p;
1759
1760
			TAILQ_FOREACH(p, conf->sc_protos, entry)
1761
				if (!strcmp(p->name, $2))
1762
					break;
1763
			if (p == NULL) {
1764
				yyerror("no such protocol: %s", $2);
1765
				free($2);
1766
				YYERROR;
1767
			}
1768
			p->flags |= F_USED;
1769
			rlay->rl_conf.proto = p->id;
1770
			rlay->rl_proto = p;
1771
			free($2);
1772
		}
1773
		| DISABLE		{ rlay->rl_conf.flags |= F_DISABLE; }
1774
		| include
1775
		;
1776
1777
forwardspec	: STRING port retry	{
1778
			struct addresslist	 al;
1779
			struct address		*h;
1780
1781
			if (rlay->rl_conf.dstss.ss_family != AF_UNSPEC) {
1782
				yyerror("relay %s target or redirection "
1783
				    "already specified", rlay->rl_conf.name);
1784
				free($1);
1785
				YYERROR;
1786
			}
1787
			if ($2.op != PF_OP_EQ) {
1788
				yyerror("invalid port");
1789
				free($1);
1790
				YYERROR;
1791
			}
1792
1793
			TAILQ_INIT(&al);
1794
			if (host($1, &al, 1, &$2, NULL, -1) <= 0) {
1795
				yyerror("invalid listen ip: %s", $1);
1796
				free($1);
1797
				YYERROR;
1798
			}
1799
			free($1);
1800
			h = TAILQ_FIRST(&al);
1801
			bcopy(&h->ss, &rlay->rl_conf.dstss,
1802
			    sizeof(rlay->rl_conf.dstss));
1803
			rlay->rl_conf.dstport = h->port.val[0];
1804
			rlay->rl_conf.dstretry = $3;
1805
			host_free(&al);
1806
		}
1807
		| NAT LOOKUP retry	{
1808
			conf->sc_conf.flags |= F_NEEDPF;
1809
			rlay->rl_conf.flags |= F_NATLOOK;
1810
			rlay->rl_conf.dstretry = $3;
1811
		}
1812
		| DESTINATION retry		{
1813
			conf->sc_conf.flags |= F_NEEDPF;
1814
			rlay->rl_conf.flags |= F_DIVERT;
1815
			rlay->rl_conf.dstretry = $2;
1816
		}
1817
		| tablespec	{
1818
			struct relay_table	*rlt;
1819
1820
			if ((rlt = calloc(1, sizeof(*rlt))) == NULL) {
1821
				yyerror("failed to allocate table reference");
1822
				YYERROR;
1823
			}
1824
1825
			rlt->rlt_table = $1;
1826
			rlt->rlt_table->conf.flags |= F_USED;
1827
			rlt->rlt_mode = dstmode;
1828
			rlt->rlt_flags = F_USED;
1829
			if (!TAILQ_EMPTY(&rlay->rl_tables))
1830
				rlt->rlt_flags |= F_BACKUP;
1831
1832
			if (hashkey != NULL &&
1833
			    (rlay->rl_conf.flags & F_HASHKEY) == 0) {
1834
				memcpy(&rlay->rl_conf.hashkey,
1835
				    hashkey, sizeof(rlay->rl_conf.hashkey));
1836
				rlay->rl_conf.flags |= F_HASHKEY;
1837
			}
1838
			free(hashkey);
1839
			hashkey = NULL;
1840
1841
			TAILQ_INSERT_TAIL(&rlay->rl_tables, rlt, rlt_entry);
1842
		}
1843
		;
1844
1845
dstmode		: /* empty */		{ $$ = RELAY_DSTMODE_DEFAULT; }
1846
		| LOADBALANCE		{ $$ = RELAY_DSTMODE_LOADBALANCE; }
1847
		| ROUNDROBIN		{ $$ = RELAY_DSTMODE_ROUNDROBIN; }
1848
		| HASH			{ $$ = RELAY_DSTMODE_HASH; }
1849
		| LEASTSTATES		{ $$ = RELAY_DSTMODE_LEASTSTATES; }
1850
		| SRCHASH		{ $$ = RELAY_DSTMODE_SRCHASH; }
1851
		| RANDOM		{ $$ = RELAY_DSTMODE_RANDOM; }
1852
		;
1853
1854
router		: ROUTER STRING		{
1855
			struct router *rt = NULL;
1856
1857
			if (!loadcfg) {
1858
				free($2);
1859
				YYACCEPT;
1860
			}
1861
1862
			conf->sc_conf.flags |= F_NEEDRT;
1863
			TAILQ_FOREACH(rt, conf->sc_rts, rt_entry)
1864
				if (!strcmp(rt->rt_conf.name, $2))
1865
					break;
1866
			if (rt != NULL) {
1867
				yyerror("router %s defined twice", $2);
1868
				free($2);
1869
				YYERROR;
1870
			}
1871
1872
			if ((rt = calloc(1, sizeof (*rt))) == NULL)
1873
				fatal("out of memory");
1874
1875
			if (strlcpy(rt->rt_conf.name, $2,
1876
			    sizeof(rt->rt_conf.name)) >=
1877
			    sizeof(rt->rt_conf.name)) {
1878
				yyerror("router name truncated");
1879
				free(rt);
1880
				YYERROR;
1881
			}
1882
			free($2);
1883
			rt->rt_conf.id = ++last_rt_id;
1884
			if (last_rt_id == INT_MAX) {
1885
				yyerror("too many routers defined");
1886
				free(rt);
1887
				YYERROR;
1888
			}
1889
			TAILQ_INIT(&rt->rt_netroutes);
1890
			router = rt;
1891
1892
			tableport = -1;
1893
		} '{' optnl routeopts_l '}'	{
1894
			if (!router->rt_conf.nroutes) {
1895
				yyerror("router %s without routes",
1896
				    router->rt_conf.name);
1897
				free(router);
1898
				router = NULL;
1899
				YYERROR;
1900
			}
1901
1902
			conf->sc_routercount++;
1903
			TAILQ_INSERT_TAIL(conf->sc_rts, router, rt_entry);
1904
			router = NULL;
1905
1906
			tableport = 0;
1907
		}
1908
		;
1909
1910
routeopts_l	: routeopts_l routeoptsl nl
1911
		| routeoptsl optnl
1912
		;
1913
1914
routeoptsl	: ROUTE address '/' NUMBER {
1915
			struct netroute	*nr;
1916
1917
			if (router->rt_conf.af == AF_UNSPEC)
1918
				router->rt_conf.af = $2.ss.ss_family;
1919
			else if (router->rt_conf.af != $2.ss.ss_family) {
1920
				yyerror("router %s address family mismatch",
1921
				    router->rt_conf.name);
1922
				YYERROR;
1923
			}
1924
1925
			if ((router->rt_conf.af == AF_INET &&
1926
			    ($4 > 32 || $4 < 0)) ||
1927
			    (router->rt_conf.af == AF_INET6 &&
1928
			    ($4 > 128 || $4 < 0))) {
1929
				yyerror("invalid prefixlen %d", $4);
1930
				YYERROR;
1931
			}
1932
1933
			if ((nr = calloc(1, sizeof(*nr))) == NULL)
1934
				fatal("out of memory");
1935
1936
			nr->nr_conf.id = ++last_nr_id;
1937
			if (last_nr_id == INT_MAX) {
1938
				yyerror("too many routes defined");
1939
				free(nr);
1940
				YYERROR;
1941
			}
1942
			nr->nr_conf.prefixlen = $4;
1943
			nr->nr_conf.routerid = router->rt_conf.id;
1944
			nr->nr_router = router;
1945
			bcopy(&$2.ss, &nr->nr_conf.ss, sizeof($2.ss));
1946
1947
			router->rt_conf.nroutes++;
1948
			conf->sc_routecount++;
1949
			TAILQ_INSERT_TAIL(&router->rt_netroutes, nr, nr_entry);
1950
			TAILQ_INSERT_TAIL(conf->sc_routes, nr, nr_route);
1951
		}
1952
		| FORWARD TO tablespec {
1953
			free(hashkey);
1954
			hashkey = NULL;
1955
1956
			if (router->rt_gwtable) {
1957
				yyerror("router %s table already specified",
1958
				    router->rt_conf.name);
1959
				purge_table(conf, conf->sc_tables, $3);
1960
				YYERROR;
1961
			}
1962
			router->rt_gwtable = $3;
1963
			router->rt_gwtable->conf.flags |= F_USED;
1964
			router->rt_conf.gwtable = $3->conf.id;
1965
			router->rt_conf.gwport = $3->conf.port;
1966
		}
1967
		| RTABLE NUMBER {
1968
			if (router->rt_conf.rtable) {
1969
				yyerror("router %s rtable already specified",
1970
				    router->rt_conf.name);
1971
				YYERROR;
1972
			}
1973
			if ($2 < 0 || $2 > RT_TABLEID_MAX) {
1974
				yyerror("invalid rtable id %d", $2);
1975
				YYERROR;
1976
			}
1977
			router->rt_conf.rtable = $2;
1978
		}
1979
		| RTLABEL STRING {
1980
			if (strlcpy(router->rt_conf.label, $2,
1981
			    sizeof(router->rt_conf.label)) >=
1982
			    sizeof(router->rt_conf.label)) {
1983
				yyerror("route label truncated");
1984
				free($2);
1985
				YYERROR;
1986
			}
1987
			free($2);
1988
		}
1989
		| DISABLE		{ rlay->rl_conf.flags |= F_DISABLE; }
1990
		| include
1991
		;
1992
1993
dstaf		: /* empty */		{
1994
			rlay->rl_conf.dstaf.ss_family = AF_UNSPEC;
1995
		}
1996
		| INET			{
1997
			rlay->rl_conf.dstaf.ss_family = AF_INET;
1998
		}
1999
		| INET6	STRING		{
2000
			struct sockaddr_in6	*sin6;
2001
2002
			sin6 = (struct sockaddr_in6 *)&rlay->rl_conf.dstaf;
2003
			if (inet_pton(AF_INET6, $2, &sin6->sin6_addr) == -1) {
2004
				yyerror("invalid ipv6 address %s", $2);
2005
				free($2);
2006
				YYERROR;
2007
			}
2008
			free($2);
2009
2010
			sin6->sin6_family = AF_INET6;
2011
			sin6->sin6_len = sizeof(*sin6);
2012
		}
2013
		;
2014
2015
interface	: /* empty */		{ $$ = NULL; }
2016
		| INTERFACE STRING	{ $$ = $2; }
2017
		;
2018
2019
host		: address	{
2020
			if ((hst = calloc(1, sizeof(*(hst)))) == NULL)
2021
				fatal("out of memory");
2022
2023
			if (strlcpy(hst->conf.name, $1.name,
2024
			    sizeof(hst->conf.name)) >= sizeof(hst->conf.name)) {
2025
				yyerror("host name truncated");
2026
				free(hst);
2027
				YYERROR;
2028
			}
2029
			bcopy(&$1.ss, &hst->conf.ss, sizeof($1.ss));
2030
			hst->conf.id = 0; /* will be set later */
2031
			SLIST_INIT(&hst->children);
2032
		} opthostflags {
2033
			$$ = hst;
2034
			hst = NULL;
2035
		}
2036
		;
2037
2038
opthostflags	: /* empty */
2039
		| hostflags_l
2040
		;
2041
2042
hostflags_l	: hostflags hostflags_l
2043
		| hostflags
2044
		;
2045
2046
hostflags	: RETRY NUMBER		{
2047
			if (hst->conf.retry) {
2048
				yyerror("retry value already set");
2049
				YYERROR;
2050
			}
2051
			if ($2 < 0) {
2052
				yyerror("invalid retry value: %d\n", $2);
2053
				YYERROR;
2054
			}
2055
			hst->conf.retry = $2;
2056
		}
2057
		| PARENT NUMBER		{
2058
			if (hst->conf.parentid) {
2059
				yyerror("parent value already set");
2060
				YYERROR;
2061
			}
2062
			if ($2 < 0) {
2063
				yyerror("invalid parent value: %d\n", $2);
2064
				YYERROR;
2065
			}
2066
			hst->conf.parentid = $2;
2067
		}
2068
		| PRIORITY NUMBER		{
2069
			if (hst->conf.priority) {
2070
				yyerror("priority already set");
2071
				YYERROR;
2072
			}
2073
			if ($2 < 0 || $2 > RTP_MAX) {
2074
				yyerror("invalid priority value: %d\n", $2);
2075
				YYERROR;
2076
			}
2077
			hst->conf.priority = $2;
2078
		}
2079
		| IP TTL NUMBER		{
2080
			if (hst->conf.ttl) {
2081
				yyerror("ttl value already set");
2082
				YYERROR;
2083
			}
2084
			if ($3 < 0) {
2085
				yyerror("invalid ttl value: %d\n", $3);
2086
				YYERROR;
2087
			}
2088
			hst->conf.ttl = $3;
2089
		}
2090
		;
2091
2092
address		: STRING	{
2093
			struct address *h;
2094
			struct addresslist al;
2095
2096
			if (strlcpy($$.name, $1,
2097
			    sizeof($$.name)) >= sizeof($$.name)) {
2098
				yyerror("host name truncated");
2099
				free($1);
2100
				YYERROR;
2101
			}
2102
2103
			TAILQ_INIT(&al);
2104
			if (host($1, &al, 1, NULL, NULL, -1) <= 0) {
2105
				yyerror("invalid host %s", $1);
2106
				free($1);
2107
				YYERROR;
2108
			}
2109
			free($1);
2110
			h = TAILQ_FIRST(&al);
2111
			memcpy(&$$.ss, &h->ss, sizeof($$.ss));
2112
			host_free(&al);
2113
		}
2114
		;
2115
2116
retry		: /* empty */		{ $$ = 0; }
2117
		| RETRY NUMBER		{
2118
			if (($$ = $2) < 0) {
2119
				yyerror("invalid retry value: %d\n", $2);
2120
				YYERROR;
2121
			}
2122
		}
2123
		;
2124
2125
timeout		: NUMBER
2126
		{
2127
			if ($1 < 0) {
2128
				yyerror("invalid timeout: %d\n", $1);
2129
				YYERROR;
2130
			}
2131
			$$.tv_sec = $1 / 1000;
2132
			$$.tv_usec = ($1 % 1000) * 1000;
2133
		}
2134
		;
2135
2136
comma		: ','
2137
		| nl
2138
		| /* empty */
2139
		;
2140
2141
optnl		: '\n' optnl
2142
		|
2143
		;
2144
2145
nl		: '\n' optnl
2146
		;
2147
2148
optstring	: STRING		{ $$ = $1; }
2149
		| /* nothing */		{ $$ = NULL; }
2150
		;
2151
%%
2152
2153
struct keywords {
2154
	const char	*k_name;
2155
	int		 k_val;
2156
};
2157
2158
int
2159
yyerror(const char *fmt, ...)
2160
{
2161
16
	va_list		 ap;
2162
8
	char		*msg;
2163
2164
8
	file->errors++;
2165
8
	va_start(ap, fmt);
2166
8
	if (vasprintf(&msg, fmt, ap) == -1)
2167
		fatalx("yyerror vasprintf");
2168
8
	va_end(ap);
2169
8
	logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
2170
8
	free(msg);
2171
8
	return (0);
2172
8
}
2173
2174
int
2175
kw_cmp(const void *k, const void *e)
2176
{
2177
237252
	return (strcmp(k, ((const struct keywords *)e)->k_name));
2178
}
2179
2180
int
2181
lookup(char *s)
2182
{
2183
	/* this has to be sorted always */
2184
	static const struct keywords keywords[] = {
2185
		{ "all",		ALL },
2186
		{ "append",		APPEND },
2187
		{ "backlog",		BACKLOG },
2188
		{ "backup",		BACKUP },
2189
		{ "block",		BLOCK },
2190
		{ "buffer",		BUFFER },
2191
		{ "ca",			CA },
2192
		{ "cache",		CACHE },
2193
		{ "cert",		CERTIFICATE },
2194
		{ "check",		CHECK },
2195
		{ "ciphers",		CIPHERS },
2196
		{ "code",		CODE },
2197
		{ "cookie",		COOKIE },
2198
		{ "curve",		CURVE },
2199
		{ "demote",		DEMOTE },
2200
		{ "destination",	DESTINATION },
2201
		{ "digest",		DIGEST },
2202
		{ "disable",		DISABLE },
2203
		{ "ecdh",		ECDH },
2204
		{ "edh",		EDH },
2205
		{ "error",		ERROR },
2206
		{ "expect",		EXPECT },
2207
		{ "external",		EXTERNAL },
2208
		{ "file",		FILENAME },
2209
		{ "forward",		FORWARD },
2210
		{ "from",		FROM },
2211
		{ "hash",		HASH },
2212
		{ "header",		HEADER },
2213
		{ "host",		HOST },
2214
		{ "icmp",		ICMP },
2215
		{ "include",		INCLUDE },
2216
		{ "inet",		INET },
2217
		{ "inet6",		INET6 },
2218
		{ "interface",		INTERFACE },
2219
		{ "interval",		INTERVAL },
2220
		{ "ip",			IP },
2221
		{ "key",		KEY },
2222
		{ "label",		LABEL },
2223
		{ "least-states",	LEASTSTATES },
2224
		{ "listen",		LISTEN },
2225
		{ "loadbalance",	LOADBALANCE },
2226
		{ "log",		LOG },
2227
		{ "lookup",		LOOKUP },
2228
		{ "match",		MATCH },
2229
		{ "method",		METHOD },
2230
		{ "mode",		MODE },
2231
		{ "nat",		NAT },
2232
		{ "no",			NO },
2233
		{ "nodelay",		NODELAY },
2234
		{ "nothing",		NOTHING },
2235
		{ "on",			ON },
2236
		{ "params",		PARAMS },
2237
		{ "parent",		PARENT },
2238
		{ "pass",		PASS },
2239
		{ "password",		PASSWORD },
2240
		{ "path",		PATH },
2241
		{ "pftag",		PFTAG },
2242
		{ "port",		PORT },
2243
		{ "prefork",		PREFORK },
2244
		{ "priority",		PRIORITY },
2245
		{ "protocol",		PROTO },
2246
		{ "query",		QUERYSTR },
2247
		{ "quick",		QUICK },
2248
		{ "random",		RANDOM },
2249
		{ "real",		REAL },
2250
		{ "redirect",		REDIRECT },
2251
		{ "relay",		RELAY },
2252
		{ "remove",		REMOVE },
2253
		{ "request",		REQUEST },
2254
		{ "response",		RESPONSE },
2255
		{ "retry",		RETRY },
2256
		{ "return",		RETURN },
2257
		{ "roundrobin",		ROUNDROBIN },
2258
		{ "route",		ROUTE },
2259
		{ "router",		ROUTER },
2260
		{ "rtable",		RTABLE },
2261
		{ "rtlabel",		RTLABEL },
2262
		{ "sack",		SACK },
2263
		{ "script",		SCRIPT },
2264
		{ "send",		SEND },
2265
		{ "session",		SESSION },
2266
		{ "set",		SET },
2267
		{ "snmp",		SNMP },
2268
		{ "socket",		SOCKET },
2269
		{ "source-hash",	SRCHASH },
2270
		{ "splice",		SPLICE },
2271
		{ "ssl",		SSL },
2272
		{ "sticky-address",	STICKYADDR },
2273
		{ "style",		STYLE },
2274
		{ "table",		TABLE },
2275
		{ "tag",		TAG },
2276
		{ "tagged",		TAGGED },
2277
		{ "tcp",		TCP },
2278
		{ "tickets",		TICKETS },
2279
		{ "timeout",		TIMEOUT },
2280
		{ "tls",		TLS },
2281
		{ "to",			TO },
2282
		{ "transparent",	TRANSPARENT },
2283
		{ "trap",		TRAP },
2284
		{ "ttl",		TTL },
2285
		{ "updates",		UPDATES },
2286
		{ "url",		URL },
2287
		{ "value",		VALUE },
2288
		{ "virtual",		VIRTUAL },
2289
		{ "with",		WITH }
2290
	};
2291
	const struct keywords	*p;
2292
2293
37896
	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
2294
	    sizeof(keywords[0]), kw_cmp);
2295
2296
18948
	if (p)
2297
14172
		return (p->k_val);
2298
	else
2299
4776
		return (STRING);
2300
18948
}
2301
2302
#define MAXPUSHBACK	128
2303
2304
u_char	*parsebuf;
2305
int	 parseindex;
2306
u_char	 pushback_buffer[MAXPUSHBACK];
2307
int	 pushback_index = 0;
2308
2309
int
2310
lgetc(int quotec)
2311
{
2312
	int		c, next;
2313
2314
423528
	if (parsebuf) {
2315
		/* Read character from the parsebuffer instead of input. */
2316
		if (parseindex >= 0) {
2317
			c = parsebuf[parseindex++];
2318
			if (c != '\0')
2319
				return (c);
2320
			parsebuf = NULL;
2321
		} else
2322
			parseindex++;
2323
	}
2324
2325
211764
	if (pushback_index)
2326
24476
		return (pushback_buffer[--pushback_index]);
2327
2328
187288
	if (quotec) {
2329

16928
		if ((c = getc(file->stream)) == EOF) {
2330
			yyerror("reached end of file while parsing "
2331
			    "quoted string");
2332
			if (file == topfile || popfile() == EOF)
2333
				return (EOF);
2334
			return (quotec);
2335
		}
2336
4232
		return (c);
2337
	}
2338
2339

915480
	while ((c = getc(file->stream)) == '\\') {
2340

160
		next = getc(file->stream);
2341
40
		if (next != '\n') {
2342
			c = next;
2343
			break;
2344
		}
2345
40
		yylval.lineno = file->lineno;
2346
40
		file->lineno++;
2347
	}
2348
2349
366112
	while (c == EOF) {
2350

548
		if (file == topfile || popfile() == EOF)
2351
548
			return (EOF);
2352
		c = getc(file->stream);
2353
	}
2354
182508
	return (c);
2355
211764
}
2356
2357
int
2358
lungetc(int c)
2359
{
2360
48968
	if (c == EOF)
2361
		return (EOF);
2362
24484
	if (parsebuf) {
2363
		parseindex--;
2364
		if (parseindex >= 0)
2365
			return (c);
2366
	}
2367
24484
	if (pushback_index < MAXPUSHBACK-1)
2368
24484
		return (pushback_buffer[pushback_index++] = c);
2369
	else
2370
		return (EOF);
2371
24484
}
2372
2373
int
2374
findeol(void)
2375
{
2376
	int	c;
2377
2378
	parsebuf = NULL;
2379
2380
	/* skip to either EOF or the first real EOL */
2381
	while (1) {
2382
		if (pushback_index)
2383
			c = pushback_buffer[--pushback_index];
2384
		else
2385
			c = lgetc(0);
2386
		if (c == '\n') {
2387
			file->lineno++;
2388
			break;
2389
		}
2390
		if (c == EOF)
2391
			break;
2392
	}
2393
	return (ERROR);
2394
}
2395
2396
int
2397
yylex(void)
2398
{
2399
64248
	u_char	 buf[8096];
2400
	u_char	*p, *val;
2401
	int	 quotec, next, c;
2402
32124
	int	 token;
2403
2404
top:
2405
32124
	p = buf;
2406
103456
	while ((c = lgetc(0)) == ' ' || c == '\t')
2407
		; /* nothing */
2408
2409
32124
	yylval.lineno = file->lineno;
2410
32124
	if (c == '#')
2411
		while ((c = lgetc(0)) != '\n' && c != EOF)
2412
			; /* nothing */
2413
32124
	if (c == '$' && parsebuf == NULL) {
2414
		while (1) {
2415
			if ((c = lgetc(0)) == EOF)
2416
				return (0);
2417
2418
			if (p + 1 >= buf + sizeof(buf) - 1) {
2419
				yyerror("string too long");
2420
				return (findeol());
2421
			}
2422
			if (isalnum(c) || c == '_') {
2423
				*p++ = c;
2424
				continue;
2425
			}
2426
			*p = '\0';
2427
			lungetc(c);
2428
			break;
2429
		}
2430
		val = symget(buf);
2431
		if (val == NULL) {
2432
			yyerror("macro '%s' not defined", buf);
2433
			return (findeol());
2434
		}
2435
		parsebuf = val;
2436
		parseindex = 0;
2437
		goto top;
2438
	}
2439
2440
32124
	switch (c) {
2441
	case '\'':
2442
	case '"':
2443
		quotec = c;
2444
4232
		while (1) {
2445
4232
			if ((c = lgetc(quotec)) == EOF)
2446
				return (0);
2447
4232
			if (c == '\n') {
2448
				file->lineno++;
2449
				continue;
2450
4232
			} else if (c == '\\') {
2451
				if ((next = lgetc(quotec)) == EOF)
2452
					return (0);
2453
				if (next == quotec || c == ' ' || c == '\t')
2454
					c = next;
2455
				else if (next == '\n') {
2456
					file->lineno++;
2457
					continue;
2458
				} else
2459
					lungetc(next);
2460
4232
			} else if (c == quotec) {
2461
552
				*p = '\0';
2462
				break;
2463
3680
			} else if (c == '\0') {
2464
				yyerror("syntax error");
2465
				return (findeol());
2466
			}
2467
3680
			if (p + 1 >= buf + sizeof(buf) - 1) {
2468
				yyerror("string too long");
2469
				return (findeol());
2470
			}
2471
3680
			*p++ = c;
2472
		}
2473
552
		yylval.v.string = strdup(buf);
2474
552
		if (yylval.v.string == NULL)
2475
			err(1, "yylex: strdup");
2476
552
		return (STRING);
2477
	}
2478
2479
#define allowed_to_end_number(x) \
2480
	(isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
2481
2482

63144
	if (c == '-' || isdigit(c)) {
2483
3344
		do {
2484
9754
			*p++ = c;
2485
9754
			if ((unsigned)(p-buf) >= sizeof(buf)) {
2486
				yyerror("string too long");
2487
				return (findeol());
2488
			}
2489

19508
		} while ((c = lgetc(0)) != EOF && isdigit(c));
2490
3344
		lungetc(c);
2491

4488
		if (p == buf + 1 && buf[0] == '-')
2492
			goto nodigits;
2493

6688
		if (c == EOF || allowed_to_end_number(c)) {
2494
2240
			const char *errstr = NULL;
2495
2496
2240
			*p = '\0';
2497
2240
			yylval.v.number = strtonum(buf, LLONG_MIN,
2498
			    LLONG_MAX, &errstr);
2499
2240
			if (errstr) {
2500
				yyerror("\"%s\" invalid number: %s",
2501
				    buf, errstr);
2502
				return (findeol());
2503
			}
2504
2240
			return (NUMBER);
2505
2240
		} else {
2506
nodigits:
2507
6592
			while (p > buf + 1)
2508
2192
				lungetc(*--p);
2509
			c = *--p;
2510
1104
			if (c == '-')
2511
				return (c);
2512
		}
2513
	}
2514
2515
#define allowed_in_string(x) \
2516
	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
2517
	x != '{' && x != '}' && x != '<' && x != '>' && \
2518
	x != '!' && x != '=' && x != '#' && \
2519
	x != ',' && x != '/'))
2520
2521
29332
	if (isalnum(c) || c == ':' || c == '_') {
2522
18948
		do {
2523
146050
			*p++ = c;
2524
146050
			if ((unsigned)(p-buf) >= sizeof(buf)) {
2525
				yyerror("string too long");
2526
				return (findeol());
2527
			}
2528

323776
		} while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
2529
18948
		lungetc(c);
2530
18948
		*p = '\0';
2531
18948
		if ((token = lookup(buf)) == STRING)
2532
4776
			if ((yylval.v.string = strdup(buf)) == NULL)
2533
				err(1, "yylex: strdup");
2534
18948
		return (token);
2535
	}
2536
10384
	if (c == '\n') {
2537
7564
		yylval.lineno = file->lineno;
2538
7564
		file->lineno++;
2539
7564
	}
2540
10384
	if (c == EOF)
2541
548
		return (0);
2542
9836
	return (c);
2543
32124
}
2544
2545
int
2546
check_file_secrecy(int fd, const char *fname)
2547
{
2548
	struct stat	st;
2549
2550
	if (fstat(fd, &st)) {
2551
		log_warn("cannot stat %s", fname);
2552
		return (-1);
2553
	}
2554
	if (st.st_uid != 0 && st.st_uid != getuid()) {
2555
		log_warnx("%s: owner not root or current user", fname);
2556
		return (-1);
2557
	}
2558
	if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
2559
		log_warnx("%s: group writable or world read/writable", fname);
2560
		return (-1);
2561
	}
2562
	return (0);
2563
}
2564
2565
struct file *
2566
pushfile(const char *name, int secret)
2567
{
2568
	struct file	*nfile;
2569
2570
2208
	if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
2571
		log_warn("%s: malloc", __func__);
2572
		return (NULL);
2573
	}
2574
1104
	if ((nfile->name = strdup(name)) == NULL) {
2575
		log_warn("%s: malloc", __func__);
2576
		free(nfile);
2577
		return (NULL);
2578
	}
2579
1104
	if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
2580
		log_warn("%s: %s", __func__, nfile->name);
2581
		free(nfile->name);
2582
		free(nfile);
2583
		return (NULL);
2584

1104
	} else if (secret &&
2585
	    check_file_secrecy(fileno(nfile->stream), nfile->name)) {
2586
		fclose(nfile->stream);
2587
		free(nfile->name);
2588
		free(nfile);
2589
		return (NULL);
2590
	}
2591
1104
	nfile->lineno = 1;
2592
1104
	TAILQ_INSERT_TAIL(&files, nfile, entry);
2593
1104
	return (nfile);
2594
1104
}
2595
2596
int
2597
popfile(void)
2598
{
2599
	struct file	*prev;
2600
2601
2208
	if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
2602
		prev->errors += file->errors;
2603
2604
2208
	TAILQ_REMOVE(&files, file, entry);
2605
1104
	fclose(file->stream);
2606
1104
	free(file->name);
2607
1104
	free(file);
2608
1104
	file = prev;
2609
1104
	return (file ? 0 : EOF);
2610
}
2611
2612
int
2613
parse_config(const char *filename, struct relayd *x_conf)
2614
{
2615
	struct sym	*sym, *next;
2616
2617
1112
	conf = x_conf;
2618
556
	if (config_init(conf) == -1) {
2619
		log_warn("%s: cannot initialize configuration", __func__);
2620
		return (-1);
2621
	}
2622
2623
556
	errors = 0;
2624
2625
556
	if ((file = pushfile(filename, 0)) == NULL)
2626
		return (-1);
2627
2628
556
	topfile = file;
2629
556
	setservent(1);
2630
2631
556
	yyparse();
2632
556
	errors = file->errors;
2633
556
	popfile();
2634
2635
556
	endservent();
2636
556
	endprotoent();
2637
2638
	/* Free macros */
2639
1112
	TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
2640
		if (!sym->persist) {
2641
			free(sym->nam);
2642
			free(sym->val);
2643
			TAILQ_REMOVE(&symhead, sym, entry);
2644
			free(sym);
2645
		}
2646
	}
2647
2648
556
	return (errors ? -1 : 0);
2649
556
}
2650
2651
int
2652
load_config(const char *filename, struct relayd *x_conf)
2653
{
2654
	struct sym		*sym, *next;
2655
	struct table		*nexttb;
2656
	struct host		*h, *ph;
2657
	struct relay_table	*rlt;
2658
2659
1096
	conf = x_conf;
2660
548
	conf->sc_conf.flags = 0;
2661
2662
548
	loadcfg = 1;
2663
548
	errors = 0;
2664
548
	last_host_id = last_table_id = last_rdr_id = last_proto_id =
2665
548
	    last_relay_id = last_rt_id = last_nr_id = 0;
2666
2667
548
	rdr = NULL;
2668
548
	table = NULL;
2669
548
	rlay = NULL;
2670
548
	proto = NULL;
2671
548
	router = NULL;
2672
2673
548
	if ((file = pushfile(filename, 0)) == NULL)
2674
		return (-1);
2675
2676
548
	topfile = file;
2677
548
	setservent(1);
2678
2679
548
	yyparse();
2680
548
	errors = file->errors;
2681
548
	popfile();
2682
2683
548
	endservent();
2684
548
	endprotoent();
2685
2686
	/* Free macros and check which have not been used. */
2687
1096
	for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
2688
		next = TAILQ_NEXT(sym, entry);
2689
		if ((conf->sc_conf.opts & RELAYD_OPT_VERBOSE) && !sym->used)
2690
			fprintf(stderr, "warning: macro '%s' not "
2691
			    "used\n", sym->nam);
2692
		if (!sym->persist) {
2693
			free(sym->nam);
2694
			free(sym->val);
2695
			TAILQ_REMOVE(&symhead, sym, entry);
2696
			free(sym);
2697
		}
2698
	}
2699
2700

548
	if (TAILQ_EMPTY(conf->sc_rdrs) &&
2701
548
	    TAILQ_EMPTY(conf->sc_relays) &&
2702
	    TAILQ_EMPTY(conf->sc_rts)) {
2703
		log_warnx("no actions, nothing to do");
2704
		errors++;
2705
	}
2706
2707
	/* Cleanup relay list to inherit */
2708
1096
	while ((rlay = TAILQ_FIRST(&relays)) != NULL) {
2709
		TAILQ_REMOVE(&relays, rlay, rl_entry);
2710
		while ((rlt = TAILQ_FIRST(&rlay->rl_tables))) {
2711
			TAILQ_REMOVE(&rlay->rl_tables, rlt, rlt_entry);
2712
			free(rlt);
2713
		}
2714
		free(rlay);
2715
	}
2716
2717

1096
	if (timercmp(&conf->sc_conf.timeout, &conf->sc_conf.interval, >=)) {
2718
		log_warnx("global timeout exceeds interval");
2719
		errors++;
2720
	}
2721
2722
	/* Verify that every table is used */
2723
1128
	for (table = TAILQ_FIRST(conf->sc_tables); table != NULL;
2724
	     table = nexttb) {
2725
16
		nexttb = TAILQ_NEXT(table, entry);
2726
16
		if (table->conf.port == 0) {
2727
24
			TAILQ_REMOVE(conf->sc_tables, table, entry);
2728
32
			while ((h = TAILQ_FIRST(&table->hosts)) != NULL) {
2729
24
				TAILQ_REMOVE(&table->hosts, h, entry);
2730
8
				free(h);
2731
			}
2732
8
			if (table->sendbuf != NULL)
2733
				free(table->sendbuf);
2734
8
			free(table);
2735
8
			continue;
2736
		}
2737
2738
32
		TAILQ_FOREACH(h, &table->hosts, entry) {
2739
8
			if (h->conf.parentid) {
2740
				ph = host_find(conf, h->conf.parentid);
2741
2742
				/* Validate the parent id */
2743
				if (h->conf.id == h->conf.parentid ||
2744
				    ph == NULL || ph->conf.parentid)
2745
					ph = NULL;
2746
2747
				if (ph == NULL) {
2748
					log_warnx("host parent id %d invalid",
2749
					    h->conf.parentid);
2750
					errors++;
2751
				} else
2752
					SLIST_INSERT_HEAD(&ph->children,
2753
					    h, child);
2754
			}
2755
		}
2756
2757
8
		if (!(table->conf.flags & F_USED)) {
2758
			log_warnx("unused table: %s", table->conf.name);
2759
			errors++;
2760
		}
2761

16
		if (timercmp(&table->conf.timeout,
2762
		    &conf->sc_conf.interval, >=)) {
2763
			log_warnx("table timeout exceeds interval: %s",
2764
			    table->conf.name);
2765
			errors++;
2766
		}
2767
	}
2768
2769
	/* Verify that every non-default protocol is used */
2770
2192
	TAILQ_FOREACH(proto, conf->sc_protos, entry) {
2771
548
		if (!(proto->flags & F_USED)) {
2772
			log_warnx("unused protocol: %s", proto->name);
2773
		}
2774
	}
2775
2776
548
	return (errors ? -1 : 0);
2777
548
}
2778
2779
int
2780
symset(const char *nam, const char *val, int persist)
2781
{
2782
	struct sym	*sym;
2783
2784
	TAILQ_FOREACH(sym, &symhead, entry) {
2785
		if (strcmp(nam, sym->nam) == 0)
2786
			break;
2787
	}
2788
2789
	if (sym != NULL) {
2790
		if (sym->persist == 1)
2791
			return (0);
2792
		else {
2793
			free(sym->nam);
2794
			free(sym->val);
2795
			TAILQ_REMOVE(&symhead, sym, entry);
2796
			free(sym);
2797
		}
2798
	}
2799
	if ((sym = calloc(1, sizeof(*sym))) == NULL)
2800
		return (-1);
2801
2802
	sym->nam = strdup(nam);
2803
	if (sym->nam == NULL) {
2804
		free(sym);
2805
		return (-1);
2806
	}
2807
	sym->val = strdup(val);
2808
	if (sym->val == NULL) {
2809
		free(sym->nam);
2810
		free(sym);
2811
		return (-1);
2812
	}
2813
	sym->used = 0;
2814
	sym->persist = persist;
2815
	TAILQ_INSERT_TAIL(&symhead, sym, entry);
2816
	return (0);
2817
}
2818
2819
int
2820
cmdline_symset(char *s)
2821
{
2822
	char	*sym, *val;
2823
	int	ret;
2824
	size_t	len;
2825
2826
	if ((val = strrchr(s, '=')) == NULL)
2827
		return (-1);
2828
2829
	len = strlen(s) - strlen(val) + 1;
2830
	if ((sym = malloc(len)) == NULL)
2831
		errx(1, "cmdline_symset: malloc");
2832
2833
	(void)strlcpy(sym, s, len);
2834
2835
	ret = symset(sym, val + 1, 1);
2836
	free(sym);
2837
2838
	return (ret);
2839
}
2840
2841
char *
2842
symget(const char *nam)
2843
{
2844
	struct sym	*sym;
2845
2846
	TAILQ_FOREACH(sym, &symhead, entry) {
2847
		if (strcmp(nam, sym->nam) == 0) {
2848
			sym->used = 1;
2849
			return (sym->val);
2850
		}
2851
	}
2852
	return (NULL);
2853
}
2854
2855
struct address *
2856
host_v4(const char *s)
2857
{
2858
2192
	struct in_addr		 ina;
2859
	struct sockaddr_in	*sain;
2860
	struct address		*h;
2861
2862
1096
	bzero(&ina, sizeof(ina));
2863
1096
	if (inet_pton(AF_INET, s, &ina) != 1)
2864
		return (NULL);
2865
2866
1096
	if ((h = calloc(1, sizeof(*h))) == NULL)
2867
		fatal(__func__);
2868
1096
	sain = (struct sockaddr_in *)&h->ss;
2869
1096
	sain->sin_len = sizeof(struct sockaddr_in);
2870
1096
	sain->sin_family = AF_INET;
2871
1096
	sain->sin_addr.s_addr = ina.s_addr;
2872
2873
1096
	return (h);
2874
1096
}
2875
2876
struct address *
2877
host_v6(const char *s)
2878
{
2879
	struct addrinfo		 hints, *res;
2880
	struct sockaddr_in6	*sa_in6;
2881
	struct address		*h = NULL;
2882
2883
	bzero(&hints, sizeof(hints));
2884
	hints.ai_family = AF_INET6;
2885
	hints.ai_socktype = SOCK_DGRAM; /* dummy */
2886
	hints.ai_flags = AI_NUMERICHOST;
2887
	if (getaddrinfo(s, "0", &hints, &res) == 0) {
2888
		if ((h = calloc(1, sizeof(*h))) == NULL)
2889
			fatal(__func__);
2890
		sa_in6 = (struct sockaddr_in6 *)&h->ss;
2891
		sa_in6->sin6_len = sizeof(struct sockaddr_in6);
2892
		sa_in6->sin6_family = AF_INET6;
2893
		memcpy(&sa_in6->sin6_addr,
2894
		    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
2895
		    sizeof(sa_in6->sin6_addr));
2896
		sa_in6->sin6_scope_id =
2897
		    ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
2898
2899
		freeaddrinfo(res);
2900
	}
2901
2902
	return (h);
2903
}
2904
2905
int
2906
host_dns(const char *s, struct addresslist *al, int max,
2907
    struct portrange *port, const char *ifname, int ipproto)
2908
{
2909
	struct addrinfo		 hints, *res0, *res;
2910
	int			 error, cnt = 0;
2911
	struct sockaddr_in	*sain;
2912
	struct sockaddr_in6	*sin6;
2913
	struct address		*h;
2914
2915
	if ((cnt = host_if(s, al, max, port, ifname, ipproto)) != 0)
2916
		return (cnt);
2917
2918
	bzero(&hints, sizeof(hints));
2919
	hints.ai_family = PF_UNSPEC;
2920
	hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
2921
	hints.ai_flags = AI_ADDRCONFIG;
2922
	error = getaddrinfo(s, NULL, &hints, &res0);
2923
	if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
2924
		return (0);
2925
	if (error) {
2926
		log_warnx("%s: could not parse \"%s\": %s", __func__, s,
2927
		    gai_strerror(error));
2928
		return (-1);
2929
	}
2930
2931
	for (res = res0; res && cnt < max; res = res->ai_next) {
2932
		if (res->ai_family != AF_INET &&
2933
		    res->ai_family != AF_INET6)
2934
			continue;
2935
		if ((h = calloc(1, sizeof(*h))) == NULL)
2936
			fatal(__func__);
2937
2938
		if (port != NULL)
2939
			bcopy(port, &h->port, sizeof(h->port));
2940
		if (ifname != NULL) {
2941
			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
2942
			    sizeof(h->ifname))
2943
				log_warnx("%s: interface name truncated",
2944
				    __func__);
2945
			freeaddrinfo(res0);
2946
			free(h);
2947
			return (-1);
2948
		}
2949
		if (ipproto != -1)
2950
			h->ipproto = ipproto;
2951
		h->ss.ss_family = res->ai_family;
2952
2953
		if (res->ai_family == AF_INET) {
2954
			sain = (struct sockaddr_in *)&h->ss;
2955
			sain->sin_len = sizeof(struct sockaddr_in);
2956
			sain->sin_addr.s_addr = ((struct sockaddr_in *)
2957
			    res->ai_addr)->sin_addr.s_addr;
2958
		} else {
2959
			sin6 = (struct sockaddr_in6 *)&h->ss;
2960
			sin6->sin6_len = sizeof(struct sockaddr_in6);
2961
			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
2962
			    res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
2963
		}
2964
2965
		TAILQ_INSERT_HEAD(al, h, entry);
2966
		cnt++;
2967
	}
2968
	if (cnt == max && res) {
2969
		log_warnx("%s: %s resolves to more than %d hosts", __func__,
2970
		    s, max);
2971
	}
2972
	freeaddrinfo(res0);
2973
	return (cnt);
2974
}
2975
2976
int
2977
host_if(const char *s, struct addresslist *al, int max,
2978
    struct portrange *port, const char *ifname, int ipproto)
2979
{
2980
	struct ifaddrs		*ifap, *p;
2981
	struct sockaddr_in	*sain;
2982
	struct sockaddr_in6	*sin6;
2983
	struct address		*h;
2984
	int			 cnt = 0, af;
2985
2986
	if (getifaddrs(&ifap) == -1)
2987
		fatal("getifaddrs");
2988
2989
	/* First search for IPv4 addresses */
2990
	af = AF_INET;
2991
2992
 nextaf:
2993
	for (p = ifap; p != NULL && cnt < max; p = p->ifa_next) {
2994
		if (p->ifa_addr->sa_family != af ||
2995
		    (strcmp(s, p->ifa_name) != 0 &&
2996
		    !is_if_in_group(p->ifa_name, s)))
2997
			continue;
2998
		if ((h = calloc(1, sizeof(*h))) == NULL)
2999
			fatal("calloc");
3000
3001
		if (port != NULL)
3002
			bcopy(port, &h->port, sizeof(h->port));
3003
		if (ifname != NULL) {
3004
			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
3005
			    sizeof(h->ifname))
3006
				log_warnx("%s: interface name truncated",
3007
				    __func__);
3008
			freeifaddrs(ifap);
3009
			return (-1);
3010
		}
3011
		if (ipproto != -1)
3012
			h->ipproto = ipproto;
3013
		h->ss.ss_family = af;
3014
3015
		if (af == AF_INET) {
3016
			sain = (struct sockaddr_in *)&h->ss;
3017
			sain->sin_len = sizeof(struct sockaddr_in);
3018
			sain->sin_addr.s_addr = ((struct sockaddr_in *)
3019
			    p->ifa_addr)->sin_addr.s_addr;
3020
		} else {
3021
			sin6 = (struct sockaddr_in6 *)&h->ss;
3022
			sin6->sin6_len = sizeof(struct sockaddr_in6);
3023
			memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
3024
			    p->ifa_addr)->sin6_addr, sizeof(struct in6_addr));
3025
			sin6->sin6_scope_id = ((struct sockaddr_in6 *)
3026
			    p->ifa_addr)->sin6_scope_id;
3027
		}
3028
3029
		TAILQ_INSERT_HEAD(al, h, entry);
3030
		cnt++;
3031
	}
3032
	if (af == AF_INET) {
3033
		/* Next search for IPv6 addresses */
3034
		af = AF_INET6;
3035
		goto nextaf;
3036
	}
3037
3038
	if (cnt > max) {
3039
		log_warnx("%s: %s resolves to more than %d hosts", __func__,
3040
		    s, max);
3041
	}
3042
	freeifaddrs(ifap);
3043
	return (cnt);
3044
}
3045
3046
int
3047
host(const char *s, struct addresslist *al, int max,
3048
    struct portrange *port, const char *ifname, int ipproto)
3049
{
3050
	struct address *h;
3051
3052
2192
	h = host_v4(s);
3053
3054
	/* IPv6 address? */
3055
1096
	if (h == NULL)
3056
		h = host_v6(s);
3057
3058
1096
	if (h != NULL) {
3059
1096
		if (port != NULL)
3060
1088
			bcopy(port, &h->port, sizeof(h->port));
3061
1096
		if (ifname != NULL) {
3062
			if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
3063
			    sizeof(h->ifname)) {
3064
				log_warnx("%s: interface name truncated",
3065
				    __func__);
3066
				free(h);
3067
				return (-1);
3068
			}
3069
		}
3070
1096
		if (ipproto != -1)
3071
			h->ipproto = ipproto;
3072
3073
3288
		TAILQ_INSERT_HEAD(al, h, entry);
3074
1096
		return (1);
3075
	}
3076
3077
	return (host_dns(s, al, max, port, ifname, ipproto));
3078
1096
}
3079
3080
void
3081
host_free(struct addresslist *al)
3082
{
3083
	struct address	 *h;
3084
3085
5480
	while ((h = TAILQ_FIRST(al)) != NULL) {
3086
3288
		TAILQ_REMOVE(al, h, entry);
3087
1096
		free(h);
3088
	}
3089
1096
}
3090
3091
struct table *
3092
table_inherit(struct table *tb)
3093
{
3094
16
	char		pname[TABLE_NAME_SIZE + 6];
3095
	struct host	*h, *dsth;
3096
	struct table	*dsttb, *oldtb;
3097
3098
	/* Get the table or table template */
3099
8
	if ((dsttb = table_findbyname(conf, tb->conf.name)) == NULL) {
3100
		yyerror("unknown table %s", tb->conf.name);
3101
		goto fail;
3102
	}
3103
8
	if (dsttb->conf.port != 0)
3104
		fatal("invalid table");	/* should not happen */
3105
3106
8
	if (tb->conf.port == 0) {
3107
		yyerror("invalid port");
3108
		goto fail;
3109
	}
3110
3111
	/* Check if a matching table already exists */
3112
24
	if (snprintf(pname, sizeof(pname), "%s:%u",
3113
16
	    tb->conf.name, ntohs(tb->conf.port)) >= (int)sizeof(pname)) {
3114
		yyerror("invalid table name");
3115
		goto fail;
3116
	}
3117
8
	if (strlcpy(tb->conf.name, pname, sizeof(tb->conf.name)) >=
3118
	    sizeof(tb->conf.name)) {
3119
		yyerror("invalid table mame");
3120
		goto fail;
3121
	}
3122
8
	if ((oldtb = table_findbyconf(conf, tb)) != NULL) {
3123
		purge_table(conf, NULL, tb);
3124
		return (oldtb);
3125
	}
3126
3127
	/* Create a new table */
3128
8
	tb->conf.id = ++last_table_id;
3129
8
	if (last_table_id == INT_MAX) {
3130
		yyerror("too many tables defined");
3131
		goto fail;
3132
	}
3133
8
	tb->conf.flags |= dsttb->conf.flags;
3134
3135
	/* Inherit global table options */
3136

16
	if (tb->conf.timeout.tv_sec == 0 && tb->conf.timeout.tv_usec == 0)
3137
8
		bcopy(&dsttb->conf.timeout, &tb->conf.timeout,
3138
		    sizeof(struct timeval));
3139
3140
	/* Copy the associated hosts */
3141
8
	TAILQ_INIT(&tb->hosts);
3142
32
	TAILQ_FOREACH(dsth, &dsttb->hosts, entry) {
3143
16
		if ((h = (struct host *)
3144
16
		    calloc(1, sizeof (*h))) == NULL)
3145
			fatal("out of memory");
3146
8
		bcopy(dsth, h, sizeof(*h));
3147
8
		h->conf.id = ++last_host_id;
3148
8
		if (last_host_id == INT_MAX) {
3149
			yyerror("too many hosts defined");
3150
			free(h);
3151
			goto fail;
3152
		}
3153
8
		h->conf.tableid = tb->conf.id;
3154
8
		h->tablename = tb->conf.name;
3155
8
		SLIST_INIT(&h->children);
3156
8
		TAILQ_INSERT_TAIL(&tb->hosts, h, entry);
3157
8
		TAILQ_INSERT_TAIL(&conf->sc_hosts, h, globalentry);
3158
	}
3159
3160
8
	conf->sc_tablecount++;
3161
8
	TAILQ_INSERT_TAIL(conf->sc_tables, tb, entry);
3162
3163
8
	return (tb);
3164
3165
 fail:
3166
	purge_table(conf, NULL, tb);
3167
	return (NULL);
3168
8
}
3169
3170
int
3171
relay_id(struct relay *rl)
3172
{
3173
1096
	rl->rl_conf.id = ++last_relay_id;
3174
548
	rl->rl_conf.tls_keyid = ++last_key_id;
3175
548
	rl->rl_conf.tls_cakeyid = ++last_key_id;
3176
3177
548
	if (last_relay_id == INT_MAX || last_key_id == INT_MAX)
3178
		return (-1);
3179
3180
548
	return (0);
3181
548
}
3182
3183
struct relay *
3184
relay_inherit(struct relay *ra, struct relay *rb)
3185
{
3186
	struct relay_config	 rc;
3187
	struct relay_table	*rta, *rtb;
3188
3189
	bcopy(&rb->rl_conf, &rc, sizeof(rc));
3190
	bcopy(ra, rb, sizeof(*rb));
3191
3192
	bcopy(&rc.ss, &rb->rl_conf.ss, sizeof(rb->rl_conf.ss));
3193
	rb->rl_conf.port = rc.port;
3194
	rb->rl_conf.flags =
3195
	    (ra->rl_conf.flags & ~F_TLS) | (rc.flags & F_TLS);
3196
	if (!(rb->rl_conf.flags & F_TLS)) {
3197
		rb->rl_tls_cert = NULL;
3198
		rb->rl_conf.tls_cert_len = 0;
3199
		rb->rl_tls_key = NULL;
3200
		rb->rl_conf.tls_key_len = 0;
3201
	}
3202
	TAILQ_INIT(&rb->rl_tables);
3203
3204
	if (relay_id(rb) == -1) {
3205
		yyerror("too many relays defined");
3206
		goto err;
3207
	}
3208
3209
	if (snprintf(rb->rl_conf.name, sizeof(rb->rl_conf.name), "%s%u:%u",
3210
	    ra->rl_conf.name, rb->rl_conf.id, ntohs(rc.port)) >=
3211
	    (int)sizeof(rb->rl_conf.name)) {
3212
		yyerror("invalid relay name");
3213
		goto err;
3214
	}
3215
3216
	if (relay_findbyname(conf, rb->rl_conf.name) != NULL ||
3217
	    relay_findbyaddr(conf, &rb->rl_conf) != NULL) {
3218
		yyerror("relay %s defined twice", rb->rl_conf.name);
3219
		goto err;
3220
	}
3221
	if (relay_load_certfiles(rb) == -1) {
3222
		yyerror("cannot load certificates for relay %s",
3223
		    rb->rl_conf.name);
3224
		goto err;
3225
	}
3226
3227
	TAILQ_FOREACH(rta, &ra->rl_tables, rlt_entry) {
3228
		if ((rtb = calloc(1, sizeof(*rtb))) == NULL) {
3229
			yyerror("cannot allocate relay table");
3230
			goto err;
3231
		}
3232
		rtb->rlt_table = rta->rlt_table;
3233
		rtb->rlt_mode = rta->rlt_mode;
3234
		rtb->rlt_flags = rta->rlt_flags;
3235
3236
		TAILQ_INSERT_TAIL(&rb->rl_tables, rtb, rlt_entry);
3237
	}
3238
3239
	conf->sc_relaycount++;
3240
	SPLAY_INIT(&rlay->rl_sessions);
3241
	TAILQ_INSERT_TAIL(conf->sc_relays, rb, rl_entry);
3242
3243
	return (rb);
3244
3245
 err:
3246
	while ((rtb = TAILQ_FIRST(&rb->rl_tables))) {
3247
		TAILQ_REMOVE(&rb->rl_tables, rtb, rlt_entry);
3248
		free(rtb);
3249
	}
3250
	free(rb);
3251
	return (NULL);
3252
}
3253
3254
int
3255
getservice(char *n)
3256
{
3257
	struct servent	*s;
3258
	const char	*errstr;
3259
	long long	 llval;
3260
3261
	llval = strtonum(n, 0, UINT16_MAX, &errstr);
3262
	if (errstr) {
3263
		s = getservbyname(n, "tcp");
3264
		if (s == NULL)
3265
			s = getservbyname(n, "udp");
3266
		if (s == NULL) {
3267
			yyerror("unknown port %s", n);
3268
			return (-1);
3269
		}
3270
		return (s->s_port);
3271
	}
3272
3273
	return (htons((u_short)llval));
3274
}
3275
3276
int
3277
is_if_in_group(const char *ifname, const char *groupname)
3278
{
3279
	unsigned int		 len;
3280
	struct ifgroupreq	 ifgr;
3281
	struct ifg_req		*ifg;
3282
	int			 s;
3283
	int			 ret = 0;
3284
3285
	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
3286
		err(1, "socket");
3287
3288
	memset(&ifgr, 0, sizeof(ifgr));
3289
	if (strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ) >= IFNAMSIZ)
3290
		err(1, "IFNAMSIZ");
3291
	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
3292
		if (errno == EINVAL || errno == ENOTTY)
3293
			goto end;
3294
		err(1, "SIOCGIFGROUP");
3295
	}
3296
3297
	len = ifgr.ifgr_len;
3298
	ifgr.ifgr_groups = calloc(len / sizeof(struct ifg_req),
3299
	    sizeof(struct ifg_req));
3300
	if (ifgr.ifgr_groups == NULL)
3301
		err(1, "getifgroups");
3302
	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
3303
		err(1, "SIOCGIFGROUP");
3304
3305
	ifg = ifgr.ifgr_groups;
3306
	for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
3307
		len -= sizeof(struct ifg_req);
3308
		if (strcmp(ifg->ifgrq_group, groupname) == 0) {
3309
			ret = 1;
3310
			break;
3311
		}
3312
	}
3313
	free(ifgr.ifgr_groups);
3314
3315
end:
3316
	close(s);
3317
	return (ret);
3318
}