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