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