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