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