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