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 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 2401 kw_cmp(const void *k, const void *e) 2402 { 2403 return (strcmp(k, ((const struct keywords *)e)->k_name)); 2404 } 2405 2406 int 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 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 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 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 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 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 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 * 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 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 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 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 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 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 * 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 * 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 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 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 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 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 * 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 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 * 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 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 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