1 /* $OpenBSD: parse.y,v 1.142 2009/08/27 09:26:53 reyk Exp $ */ 2 3 /* 4 * Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org> 5 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> 6 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 7 * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org> 8 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> 9 * Copyright (c) 2001 Markus Friedl. All rights reserved. 10 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 11 * Copyright (c) 2001 Theo de Raadt. All rights reserved. 12 * 13 * Permission to use, copy, modify, and distribute this software for any 14 * purpose with or without fee is hereby granted, provided that the above 15 * copyright notice and this permission notice appear in all copies. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 18 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 20 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 22 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 23 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 */ 25 26 %{ 27 #include <sys/types.h> 28 #include <sys/socket.h> 29 #include <sys/stat.h> 30 #include <sys/queue.h> 31 32 #include <net/if.h> 33 #include <net/pfvar.h> 34 #include <netinet/in.h> 35 #include <arpa/inet.h> 36 #include <arpa/nameser.h> 37 38 #include <ctype.h> 39 #include <unistd.h> 40 #include <err.h> 41 #include <errno.h> 42 #include <event.h> 43 #include <limits.h> 44 #include <stdint.h> 45 #include <stdarg.h> 46 #include <stdio.h> 47 #include <netdb.h> 48 #include <string.h> 49 #include <ifaddrs.h> 50 51 #include <openssl/ssl.h> 52 53 #include "relayd.h" 54 55 TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); 56 static struct file { 57 TAILQ_ENTRY(file) entry; 58 FILE *stream; 59 char *name; 60 int lineno; 61 int errors; 62 } *file, *topfile; 63 struct file *pushfile(const char *, int); 64 int popfile(void); 65 int check_file_secrecy(int, const char *); 66 int yyparse(void); 67 int yylex(void); 68 int yyerror(const char *, ...); 69 int kw_cmp(const void *, const void *); 70 int lookup(char *); 71 int lgetc(int); 72 int lungetc(int); 73 int findeol(void); 74 75 TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 76 struct sym { 77 TAILQ_ENTRY(sym) entry; 78 int used; 79 int persist; 80 char *nam; 81 char *val; 82 }; 83 int symset(const char *, const char *, int); 84 char *symget(const char *); 85 86 struct relayd *conf = NULL; 87 static int errors = 0; 88 objid_t last_rdr_id = 0; 89 objid_t last_table_id = 0; 90 objid_t last_host_id = 0; 91 objid_t last_relay_id = 0; 92 objid_t last_proto_id = 0; 93 objid_t last_rt_id = 0; 94 objid_t last_nr_id = 0; 95 96 static struct rdr *rdr = NULL; 97 static struct table *table = NULL; 98 static struct relay *rlay = NULL; 99 static struct host *hst = NULL; 100 struct relaylist relays; 101 static struct protocol *proto = NULL; 102 static struct protonode node; 103 static struct router *router = NULL; 104 static u_int16_t label = 0; 105 static in_port_t tableport = 0; 106 static int nodedirection; 107 108 struct address *host_v4(const char *); 109 struct address *host_v6(const char *); 110 int host_dns(const char *, struct addresslist *, 111 int, struct portrange *, const char *, int); 112 int host_if(const char *, struct addresslist *, 113 int, struct portrange *, const char *, int); 114 int host(const char *, struct addresslist *, 115 int, struct portrange *, const char *, int); 116 117 struct table *table_inherit(struct table *); 118 struct relay *relay_inherit(struct relay *, struct relay *); 119 int getservice(char *); 120 121 typedef struct { 122 union { 123 int64_t number; 124 char *string; 125 struct host *host; 126 struct timeval tv; 127 struct table *table; 128 struct portrange port; 129 struct { 130 struct sockaddr_storage ss; 131 char name[MAXHOSTNAMELEN]; 132 } addr; 133 struct { 134 enum digest_type type; 135 char *digest; 136 } digest; 137 } v; 138 int lineno; 139 } YYSTYPE; 140 141 %} 142 143 %token ALL APPEND BACKLOG BACKUP BUFFER CA CACHE CHANGE CHECK 144 %token CIPHERS CODE COOKIE DEMOTE DIGEST DISABLE ERROR EXPECT 145 %token EXTERNAL FILENAME FILTER FORWARD FROM HASH HEADER HOST ICMP 146 %token INCLUDE INET INET6 INTERFACE INTERVAL IP LABEL LISTEN 147 %token LOADBALANCE LOG LOOKUP MARK MARKED MODE NAT NO 148 %token NODELAY NOTHING ON PARENT PATH PORT PREFORK PROTO 149 %token QUERYSTR REAL REDIRECT RELAY REMOVE REQUEST RESPONSE RETRY 150 %token RETURN ROUNDROBIN ROUTE SACK SCRIPT SEND SESSION SOCKET 151 %token SSL STICKYADDR STYLE TABLE TAG TCP TIMEOUT TO ROUTER RTLABEL 152 %token TRANSPARENT TRAP UPDATES URL VIRTUAL WITH TTL RTABLE 153 %token <v.string> STRING 154 %token <v.number> NUMBER 155 %type <v.string> hostname interface table 156 %type <v.number> http_type loglevel mark 157 %type <v.number> direction dstmode flag forwardmode retry 158 %type <v.number> optssl optsslclient sslcache 159 %type <v.number> redirect_proto relay_proto 160 %type <v.port> port 161 %type <v.host> host 162 %type <v.addr> address 163 %type <v.tv> timeout 164 %type <v.digest> digest 165 %type <v.table> tablespec 166 167 %% 168 169 grammar : /* empty */ 170 | grammar include '\n' 171 | grammar '\n' 172 | grammar varset '\n' 173 | grammar main '\n' 174 | grammar rdr '\n' 175 | grammar tabledef '\n' 176 | grammar relay '\n' 177 | grammar proto '\n' 178 | grammar router '\n' 179 | grammar error '\n' { file->errors++; } 180 ; 181 182 include : INCLUDE STRING { 183 struct file *nfile; 184 185 if ((nfile = pushfile($2, 0)) == NULL) { 186 yyerror("failed to include file %s", $2); 187 free($2); 188 YYERROR; 189 } 190 free($2); 191 192 file = nfile; 193 lungetc('\n'); 194 } 195 196 optssl : /*empty*/ { $$ = 0; } 197 | SSL { $$ = 1; } 198 ; 199 200 optsslclient : /*empty*/ { $$ = 0; } 201 | WITH SSL { $$ = 1; } 202 ; 203 204 http_type : STRING { 205 if (strcmp("https", $1) == 0) { 206 $$ = 1; 207 } else if (strcmp("http", $1) == 0) { 208 $$ = 0; 209 } else { 210 yyerror("invalid check type: %s", $1); 211 free($1); 212 YYERROR; 213 } 214 free($1); 215 } 216 ; 217 218 hostname : /* empty */ { 219 $$ = strdup(""); 220 if ($$ == NULL) 221 fatal("calloc"); 222 } 223 | HOST STRING { 224 if (asprintf(&$$, "Host: %s\r\nConnection: close\r\n", 225 $2) == -1) 226 fatal("asprintf"); 227 } 228 ; 229 230 relay_proto : /* empty */ { $$ = RELAY_PROTO_TCP; } 231 | TCP { $$ = RELAY_PROTO_TCP; } 232 | STRING { 233 if (strcmp("http", $1) == 0) { 234 $$ = RELAY_PROTO_HTTP; 235 } else if (strcmp("dns", $1) == 0) { 236 $$ = RELAY_PROTO_DNS; 237 } else { 238 yyerror("invalid protocol type: %s", $1); 239 free($1); 240 YYERROR; 241 } 242 free($1); 243 } 244 ; 245 246 redirect_proto : /* empty */ { $$ = IPPROTO_TCP; } 247 | TCP { $$ = IPPROTO_TCP; } 248 | STRING { 249 struct protoent *p; 250 251 if ((p = getprotobyname($1)) == NULL) { 252 yyerror("invalid protocol: %s", $1); 253 free($1); 254 YYERROR; 255 } 256 free($1); 257 258 $$ = p->p_proto; 259 } 260 ; 261 262 eflags_l : eflags comma eflags_l 263 | eflags 264 ; 265 266 opteflags : /* nothing */ 267 | eflags 268 ; 269 270 eflags : STYLE STRING 271 { 272 if ((proto->style = strdup($2)) == NULL) 273 fatal("out of memory"); 274 free($2); 275 } 276 ; 277 278 port : PORT STRING { 279 char *a, *b; 280 int p[2]; 281 282 p[0] = p[1] = 0; 283 284 a = $2; 285 b = strchr($2, ':'); 286 if (b == NULL) 287 $$.op = PF_OP_EQ; 288 else { 289 *b++ = '\0'; 290 if ((p[1] = getservice(b)) == -1) { 291 free($2); 292 YYERROR; 293 } 294 $$.op = PF_OP_RRG; 295 } 296 if ((p[0] = getservice(a)) == -1) { 297 free($2); 298 YYERROR; 299 } 300 $$.val[0] = p[0]; 301 $$.val[1] = p[1]; 302 free($2); 303 } 304 | PORT NUMBER { 305 if ($2 <= 0 || $2 >= (int)USHRT_MAX) { 306 yyerror("invalid port: %d", $2); 307 YYERROR; 308 } 309 $$.val[0] = htons($2); 310 $$.op = PF_OP_EQ; 311 } 312 ; 313 314 varset : STRING '=' STRING { 315 if (symset($1, $3, 0) == -1) 316 fatal("cannot store variable"); 317 free($1); 318 free($3); 319 } 320 ; 321 322 sendbuf : NOTHING { 323 table->sendbuf = NULL; 324 table->sendbuf_len = 0; 325 } 326 | STRING { 327 table->sendbuf = strdup($1); 328 if (table->sendbuf == NULL) 329 fatal("out of memory"); 330 table->sendbuf_len = strlen(table->sendbuf); 331 free($1); 332 } 333 ; 334 335 main : INTERVAL NUMBER { 336 if ((conf->sc_interval.tv_sec = $2) < 0) { 337 yyerror("invalid interval: %d", $2); 338 YYERROR; 339 } 340 } 341 | LOG loglevel { conf->sc_opts |= $2; } 342 | TIMEOUT timeout { 343 bcopy(&$2, &conf->sc_timeout, sizeof(struct timeval)); 344 } 345 | PREFORK NUMBER { 346 if ($2 <= 0 || $2 > RELAY_MAXPROC) { 347 yyerror("invalid number of preforked " 348 "relays: %d", $2); 349 YYERROR; 350 } 351 conf->sc_prefork_relay = $2; 352 } 353 | DEMOTE STRING { 354 conf->sc_flags |= F_DEMOTE; 355 if (strlcpy(conf->sc_demote_group, $2, 356 sizeof(conf->sc_demote_group)) 357 >= sizeof(conf->sc_demote_group)) { 358 yyerror("yyparse: demote group name too long"); 359 free($2); 360 YYERROR; 361 } 362 free($2); 363 if (carp_demote_init(conf->sc_demote_group, 1) == -1) { 364 yyerror("yyparse: error initializing group %s", 365 conf->sc_demote_group); 366 YYERROR; 367 } 368 } 369 | SEND TRAP { conf->sc_flags |= F_TRAP; } 370 ; 371 372 loglevel : UPDATES { $$ = RELAYD_OPT_LOGUPDATE; } 373 | ALL { $$ = RELAYD_OPT_LOGALL; } 374 ; 375 376 rdr : REDIRECT STRING { 377 struct rdr *srv; 378 379 conf->sc_flags |= F_NEEDPF; 380 TAILQ_FOREACH(srv, conf->sc_rdrs, entry) 381 if (!strcmp(srv->conf.name, $2)) 382 break; 383 if (srv != NULL) { 384 yyerror("redirection %s defined twice", $2); 385 free($2); 386 YYERROR; 387 } 388 if ((srv = calloc(1, sizeof (*srv))) == NULL) 389 fatal("out of memory"); 390 391 if (strlcpy(srv->conf.name, $2, 392 sizeof(srv->conf.name)) >= 393 sizeof(srv->conf.name)) { 394 yyerror("redirection name truncated"); 395 free(srv); 396 YYERROR; 397 } 398 free($2); 399 srv->conf.id = ++last_rdr_id; 400 srv->conf.timeout.tv_sec = RELAY_TIMEOUT; 401 if (last_rdr_id == INT_MAX) { 402 yyerror("too many redirections defined"); 403 free(srv); 404 YYERROR; 405 } 406 rdr = srv; 407 } '{' optnl rdropts_l '}' { 408 if (rdr->table == NULL) { 409 yyerror("redirection %s has no table", 410 rdr->conf.name); 411 YYERROR; 412 } 413 if (TAILQ_EMPTY(&rdr->virts)) { 414 yyerror("redirection %s has no virtual ip", 415 rdr->conf.name); 416 YYERROR; 417 } 418 conf->sc_rdrcount++; 419 if (rdr->backup == NULL) { 420 rdr->conf.backup_id = 421 conf->sc_empty_table.conf.id; 422 rdr->backup = &conf->sc_empty_table; 423 } else if (rdr->backup->conf.port != 424 rdr->table->conf.port) { 425 yyerror("redirection %s uses two different " 426 "ports for its table and backup table", 427 rdr->conf.name); 428 YYERROR; 429 } 430 if (!(rdr->conf.flags & F_DISABLE)) 431 rdr->conf.flags |= F_ADD; 432 TAILQ_INSERT_TAIL(conf->sc_rdrs, rdr, entry); 433 tableport = 0; 434 rdr = NULL; 435 } 436 ; 437 438 rdropts_l : rdropts_l rdroptsl nl 439 | rdroptsl optnl 440 ; 441 442 rdroptsl : forwardmode TO tablespec interface { 443 switch ($1) { 444 case FWD_NORMAL: 445 if ($4 == NULL) 446 break; 447 yyerror("superfluous interface"); 448 YYERROR; 449 case FWD_ROUTE: 450 if ($4 != NULL) 451 break; 452 yyerror("missing interface to route to"); 453 YYERROR; 454 case FWD_TRANS: 455 yyerror("no transparent forward here"); 456 YYERROR; 457 } 458 if ($4 != NULL) { 459 strlcpy($3->conf.ifname, $4, 460 sizeof($3->conf.ifname)); 461 free($4); 462 } 463 464 if ($3->conf.check == CHECK_NOCHECK) { 465 yyerror("table %s has no check", $3->conf.name); 466 purge_table(conf->sc_tables, $3); 467 YYERROR; 468 } 469 if (rdr->backup) { 470 yyerror("only one backup table is allowed"); 471 purge_table(conf->sc_tables, $3); 472 YYERROR; 473 } 474 if (rdr->table) { 475 rdr->backup = $3; 476 rdr->conf.backup_id = $3->conf.id; 477 } else { 478 rdr->table = $3; 479 rdr->conf.table_id = $3->conf.id; 480 } 481 $3->conf.fwdmode = $1; 482 $3->conf.rdrid = rdr->conf.id; 483 $3->conf.flags |= F_USED; 484 } 485 | LISTEN ON STRING redirect_proto port interface { 486 if (host($3, &rdr->virts, 487 SRV_MAX_VIRTS, &$5, $6, $4) <= 0) { 488 yyerror("invalid virtual ip: %s", $3); 489 free($3); 490 free($6); 491 YYERROR; 492 } 493 free($3); 494 free($6); 495 if (rdr->conf.port == 0) 496 rdr->conf.port = $5.val[0]; 497 tableport = rdr->conf.port; 498 } 499 | DISABLE { rdr->conf.flags |= F_DISABLE; } 500 | STICKYADDR { rdr->conf.flags |= F_STICKY; } 501 | TAG STRING { 502 conf->sc_flags |= F_NEEDPF; 503 if (strlcpy(rdr->conf.tag, $2, 504 sizeof(rdr->conf.tag)) >= 505 sizeof(rdr->conf.tag)) { 506 yyerror("redirection tag name truncated"); 507 free($2); 508 YYERROR; 509 } 510 free($2); 511 } 512 | SESSION TIMEOUT NUMBER { 513 if ((rdr->conf.timeout.tv_sec = $3) < 0) { 514 yyerror("invalid timeout: %d", $3); 515 YYERROR; 516 } 517 } 518 | include 519 ; 520 521 forwardmode : FORWARD { $$ = FWD_NORMAL; } 522 | ROUTE { $$ = FWD_ROUTE; } 523 | TRANSPARENT FORWARD { $$ = FWD_TRANS; } 524 ; 525 526 table : '<' STRING '>' { 527 if (strlen($2) >= TABLE_NAME_SIZE) { 528 yyerror("invalid table name"); 529 free($2); 530 YYERROR; 531 } 532 $$ = $2; 533 } 534 ; 535 536 tabledef : TABLE table { 537 struct table *tb; 538 539 TAILQ_FOREACH(tb, conf->sc_tables, entry) 540 if (!strcmp(tb->conf.name, $2)) 541 break; 542 if (tb != NULL) { 543 yyerror("table %s defined twice", $2); 544 free($2); 545 YYERROR; 546 } 547 548 if ((tb = calloc(1, sizeof (*tb))) == NULL) 549 fatal("out of memory"); 550 551 (void)strlcpy(tb->conf.name, $2, sizeof(tb->conf.name)); 552 free($2); 553 554 tb->conf.id = 0; /* will be set later */ 555 bcopy(&conf->sc_timeout, &tb->conf.timeout, 556 sizeof(struct timeval)); 557 TAILQ_INIT(&tb->hosts); 558 table = tb; 559 } tabledefopts_l { 560 if (TAILQ_EMPTY(&table->hosts)) { 561 yyerror("table %s has no hosts", 562 table->conf.name); 563 YYERROR; 564 } 565 conf->sc_tablecount++; 566 TAILQ_INSERT_TAIL(conf->sc_tables, table, entry); 567 } 568 ; 569 570 tabledefopts_l : tabledefopts_l tabledefopts 571 | tabledefopts 572 ; 573 574 tabledefopts : DISABLE { table->conf.flags |= F_DISABLE; } 575 | '{' optnl tablelist_l '}' 576 ; 577 578 tablelist_l : tablelist comma tablelist_l 579 | tablelist optnl 580 ; 581 582 tablelist : host { 583 $1->conf.tableid = table->conf.id; 584 $1->tablename = table->conf.name; 585 TAILQ_INSERT_TAIL(&table->hosts, $1, entry); 586 } 587 | include 588 ; 589 590 tablespec : table { 591 struct table *tb; 592 if ((tb = calloc(1, sizeof (*tb))) == NULL) 593 fatal("out of memory"); 594 (void)strlcpy(tb->conf.name, $1, sizeof(tb->conf.name)); 595 free($1); 596 table = tb; 597 } tableopts_l { 598 struct table *tb; 599 if (table->conf.port == 0) 600 table->conf.port = tableport; 601 else 602 table->conf.flags |= F_PORT; 603 if ((tb = table_inherit(table)) == NULL) 604 YYERROR; 605 $$ = tb; 606 } 607 ; 608 609 tableopts_l : tableopts tableopts_l 610 | tableopts 611 ; 612 613 tableopts : CHECK tablecheck 614 | port { 615 if ($1.op != PF_OP_EQ) { 616 yyerror("invalid port"); 617 YYERROR; 618 } 619 table->conf.port = $1.val[0]; 620 } 621 | TIMEOUT timeout { 622 bcopy(&$2, &table->conf.timeout, 623 sizeof(struct timeval)); 624 } 625 | DEMOTE STRING { 626 table->conf.flags |= F_DEMOTE; 627 if (strlcpy(table->conf.demote_group, $2, 628 sizeof(table->conf.demote_group)) 629 >= sizeof(table->conf.demote_group)) { 630 yyerror("yyparse: demote group name too long"); 631 free($2); 632 YYERROR; 633 } 634 free($2); 635 if (carp_demote_init(table->conf.demote_group, 1) 636 == -1) { 637 yyerror("yyparse: error initializing group " 638 "'%s'", table->conf.demote_group); 639 YYERROR; 640 } 641 } 642 | INTERVAL NUMBER { 643 if ($2 < conf->sc_interval.tv_sec || 644 $2 % conf->sc_interval.tv_sec) { 645 yyerror("table interval must be " 646 "divisible by global interval"); 647 YYERROR; 648 } 649 table->conf.skip_cnt = ($2 / conf->sc_interval.tv_sec) - 1; 650 } 651 | MODE dstmode { 652 switch ($2) { 653 case RELAY_DSTMODE_LOADBALANCE: 654 case RELAY_DSTMODE_HASH: 655 if (rdr != NULL) { 656 yyerror("mode not supported " 657 "for redirections"); 658 YYERROR; 659 } 660 /* FALLTHROUGH */ 661 case RELAY_DSTMODE_ROUNDROBIN: 662 if (rlay != NULL) 663 rlay->rl_conf.dstmode = $2; 664 break; 665 } 666 } 667 ; 668 669 tablecheck : ICMP { table->conf.check = CHECK_ICMP; } 670 | TCP { table->conf.check = CHECK_TCP; } 671 | SSL { 672 table->conf.check = CHECK_TCP; 673 conf->sc_flags |= F_SSL; 674 table->conf.flags |= F_SSL; 675 } 676 | http_type STRING hostname CODE NUMBER { 677 if ($1) { 678 conf->sc_flags |= F_SSL; 679 table->conf.flags |= F_SSL; 680 } 681 table->conf.check = CHECK_HTTP_CODE; 682 if ((table->conf.retcode = $5) <= 0) { 683 yyerror("invalid HTTP code: %d", $5); 684 free($2); 685 free($3); 686 YYERROR; 687 } 688 if (asprintf(&table->sendbuf, 689 "HEAD %s HTTP/1.%c\r\n%s\r\n", 690 $2, strlen($3) ? '1' : '0', $3) == -1) 691 fatal("asprintf"); 692 free($2); 693 free($3); 694 if (table->sendbuf == NULL) 695 fatal("out of memory"); 696 table->sendbuf_len = strlen(table->sendbuf); 697 } 698 | http_type STRING hostname digest { 699 if ($1) { 700 conf->sc_flags |= F_SSL; 701 table->conf.flags |= F_SSL; 702 } 703 table->conf.check = CHECK_HTTP_DIGEST; 704 if (asprintf(&table->sendbuf, 705 "GET %s HTTP/1.%c\r\n%s\r\n", 706 $2, strlen($3) ? '1' : '0', $3) == -1) 707 fatal("asprintf"); 708 free($2); 709 free($3); 710 if (table->sendbuf == NULL) 711 fatal("out of memory"); 712 table->sendbuf_len = strlen(table->sendbuf); 713 (void)strlcpy(table->conf.digest, $4.digest, 714 sizeof(table->conf.digest)); 715 table->conf.digest_type = $4.type; 716 free($4.digest); 717 } 718 | SEND sendbuf EXPECT STRING optssl { 719 table->conf.check = CHECK_SEND_EXPECT; 720 if ($5) { 721 conf->sc_flags |= F_SSL; 722 table->conf.flags |= F_SSL; 723 } 724 if (strlcpy(table->conf.exbuf, $4, 725 sizeof(table->conf.exbuf)) 726 >= sizeof(table->conf.exbuf)) { 727 yyerror("yyparse: expect buffer truncated"); 728 free($4); 729 YYERROR; 730 } 731 translate_string(table->conf.exbuf); 732 free($4); 733 } 734 | SCRIPT STRING { 735 table->conf.check = CHECK_SCRIPT; 736 if (strlcpy(table->conf.path, $2, 737 sizeof(table->conf.path)) >= 738 sizeof(table->conf.path)) { 739 yyerror("script path truncated"); 740 free($2); 741 YYERROR; 742 } 743 free($2); 744 } 745 ; 746 747 digest : DIGEST STRING 748 { 749 switch (strlen($2)) { 750 case 40: 751 $$.type = DIGEST_SHA1; 752 break; 753 case 32: 754 $$.type = DIGEST_MD5; 755 break; 756 default: 757 yyerror("invalid http digest"); 758 free($2); 759 YYERROR; 760 } 761 $$.digest = $2; 762 } 763 ; 764 765 proto : relay_proto PROTO STRING { 766 struct protocol *p; 767 768 if (strcmp($3, "default") == 0) { 769 p = &conf->sc_proto_default; 770 } else { 771 TAILQ_FOREACH(p, conf->sc_protos, entry) 772 if (!strcmp(p->name, $3)) 773 break; 774 } 775 if (p != NULL) { 776 yyerror("protocol %s defined twice", $3); 777 free($3); 778 YYERROR; 779 } 780 if ((p = calloc(1, sizeof (*p))) == NULL) 781 fatal("out of memory"); 782 783 if (strlcpy(p->name, $3, sizeof(p->name)) >= 784 sizeof(p->name)) { 785 yyerror("protocol name truncated"); 786 free(p); 787 YYERROR; 788 } 789 free($3); 790 p->id = ++last_proto_id; 791 p->type = $1; 792 p->cache = RELAY_CACHESIZE; 793 p->tcpflags = TCPFLAG_DEFAULT; 794 p->sslflags = SSLFLAG_DEFAULT; 795 p->tcpbacklog = RELAY_BACKLOG; 796 (void)strlcpy(p->sslciphers, SSLCIPHERS_DEFAULT, 797 sizeof(p->sslciphers)); 798 if (last_proto_id == INT_MAX) { 799 yyerror("too many protocols defined"); 800 free(p); 801 YYERROR; 802 } 803 RB_INIT(&p->request_tree); 804 RB_INIT(&p->response_tree); 805 proto = p; 806 } protopts_n { 807 conf->sc_protocount++; 808 809 if ((proto->sslflags & SSLFLAG_VERSION) == 0) { 810 yyerror("invalid SSL protocol"); 811 YYERROR; 812 } 813 814 TAILQ_INSERT_TAIL(conf->sc_protos, proto, entry); 815 } 816 ; 817 818 protopts_n : /* empty */ 819 | '{' '}' 820 | '{' optnl protopts_l '}' 821 ; 822 823 protopts_l : protopts_l protoptsl nl 824 | protoptsl optnl 825 ; 826 827 protoptsl : SSL sslflags 828 | SSL '{' sslflags_l '}' 829 | TCP tcpflags 830 | TCP '{' tcpflags_l '}' 831 | RETURN ERROR opteflags { proto->flags |= F_RETURN; } 832 | RETURN ERROR '{' eflags_l '}' { proto->flags |= F_RETURN; } 833 | LABEL STRING { 834 label = pn_name2id($2); 835 free($2); 836 if (label == 0) { 837 yyerror("invalid protocol action label"); 838 YYERROR; 839 } 840 } 841 | NO LABEL { 842 label = 0; 843 } 844 | direction { 845 node.label = label; 846 nodedirection = $1; 847 } protonode { 848 if (nodedirection != -1 && 849 protonode_add(nodedirection, proto, &node) == -1) { 850 yyerror("failed to add protocol node"); 851 YYERROR; 852 } 853 bzero(&node, sizeof(node)); 854 } 855 | include 856 ; 857 858 direction : /* empty */ { $$ = RELAY_DIR_REQUEST; } 859 | REQUEST { $$ = RELAY_DIR_REQUEST; } 860 | RESPONSE { $$ = RELAY_DIR_RESPONSE; } 861 ; 862 863 tcpflags_l : tcpflags comma tcpflags_l 864 | tcpflags 865 ; 866 867 tcpflags : SACK { proto->tcpflags |= TCPFLAG_SACK; } 868 | NO SACK { proto->tcpflags |= TCPFLAG_NSACK; } 869 | NODELAY { proto->tcpflags |= TCPFLAG_NODELAY; } 870 | NO NODELAY { proto->tcpflags |= TCPFLAG_NNODELAY; } 871 | BACKLOG NUMBER { 872 if ($2 < 0 || $2 > RELAY_MAX_SESSIONS) { 873 yyerror("invalid backlog: %d", $2); 874 YYERROR; 875 } 876 proto->tcpbacklog = $2; 877 } 878 | SOCKET BUFFER NUMBER { 879 proto->tcpflags |= TCPFLAG_BUFSIZ; 880 if ((proto->tcpbufsiz = $3) < 0) { 881 yyerror("invalid socket buffer size: %d", $3); 882 YYERROR; 883 } 884 } 885 | IP STRING NUMBER { 886 if ($3 < 0) { 887 yyerror("invalid ttl: %d", $3); 888 free($2); 889 YYERROR; 890 } 891 if (strcasecmp("ttl", $2) == 0) { 892 proto->tcpflags |= TCPFLAG_IPTTL; 893 proto->tcpipttl = $3; 894 } else if (strcasecmp("minttl", $2) == 0) { 895 proto->tcpflags |= TCPFLAG_IPMINTTL; 896 proto->tcpipminttl = $3; 897 } else { 898 yyerror("invalid TCP/IP flag: %s", $2); 899 free($2); 900 YYERROR; 901 } 902 free($2); 903 } 904 ; 905 906 sslflags_l : sslflags comma sslflags_l 907 | sslflags 908 ; 909 910 sslflags : SESSION CACHE sslcache { proto->cache = $3; } 911 | CIPHERS STRING { 912 if (strlcpy(proto->sslciphers, $2, 913 sizeof(proto->sslciphers)) >= 914 sizeof(proto->sslciphers)) { 915 yyerror("sslciphers truncated"); 916 free($2); 917 YYERROR; 918 } 919 free($2); 920 } 921 | CA FILENAME STRING { 922 if (proto->sslca != NULL) { 923 yyerror("sslca already specified"); 924 free($3); 925 YYERROR; 926 } 927 proto->sslca = $3; 928 } 929 | NO flag { proto->sslflags &= ~($2); } 930 | flag { proto->sslflags |= $1; } 931 ; 932 933 flag : STRING { 934 if (strcmp("sslv2", $1) == 0) 935 $$ = SSLFLAG_SSLV2; 936 else if (strcmp("sslv3", $1) == 0) 937 $$ = SSLFLAG_SSLV3; 938 else if (strcmp("tlsv1", $1) == 0) 939 $$ = SSLFLAG_TLSV1; 940 else { 941 yyerror("invalid SSL flag: %s", $1); 942 free($1); 943 YYERROR; 944 } 945 free($1); 946 } 947 ; 948 949 protonode : nodetype APPEND STRING TO STRING nodeopts { 950 node.action = NODE_ACTION_APPEND; 951 node.key = strdup($5); 952 node.value = strdup($3); 953 if (node.key == NULL || node.value == NULL) 954 fatal("out of memory"); 955 if (strchr(node.value, '$') != NULL) 956 node.flags |= PNFLAG_MACRO; 957 free($5); 958 free($3); 959 } 960 | nodetype CHANGE STRING TO STRING nodeopts { 961 node.action = NODE_ACTION_CHANGE; 962 node.key = strdup($3); 963 node.value = strdup($5); 964 if (node.key == NULL || node.value == NULL) 965 fatal("out of memory"); 966 if (strchr(node.value, '$') != NULL) 967 node.flags |= PNFLAG_MACRO; 968 free($5); 969 free($3); 970 } 971 | nodetype REMOVE STRING nodeopts { 972 node.action = NODE_ACTION_REMOVE; 973 node.key = strdup($3); 974 node.value = NULL; 975 if (node.key == NULL) 976 fatal("out of memory"); 977 free($3); 978 } 979 | nodetype REMOVE { 980 node.action = NODE_ACTION_REMOVE; 981 node.key = NULL; 982 node.value = NULL; 983 } nodefile 984 | nodetype EXPECT STRING FROM STRING nodeopts { 985 node.action = NODE_ACTION_EXPECT; 986 node.key = strdup($5); 987 node.value = strdup($3); 988 if (node.key == NULL || node.value == NULL) 989 fatal("out of memory"); 990 free($5); 991 free($3); 992 proto->lateconnect++; 993 } 994 | nodetype EXPECT STRING nodeopts { 995 node.action = NODE_ACTION_EXPECT; 996 node.key = strdup($3); 997 node.value = strdup("*"); 998 if (node.key == NULL || node.value == NULL) 999 fatal("out of memory"); 1000 free($3); 1001 proto->lateconnect++; 1002 } 1003 | nodetype EXPECT { 1004 node.action = NODE_ACTION_EXPECT; 1005 node.key = NULL; 1006 node.value = "*"; 1007 proto->lateconnect++; 1008 } nodefile 1009 | nodetype EXPECT digest nodeopts { 1010 if (node.type != NODE_TYPE_URL) { 1011 yyerror("digest not supported for this type"); 1012 free($3.digest); 1013 YYERROR; 1014 } 1015 node.action = NODE_ACTION_EXPECT; 1016 node.key = strdup($3.digest); 1017 node.flags |= PNFLAG_LOOKUP_DIGEST($3.type); 1018 node.value = strdup("*"); 1019 if (node.key == NULL || node.value == NULL) 1020 fatal("out of memory"); 1021 free($3.digest); 1022 proto->lateconnect++; 1023 } 1024 | nodetype FILTER STRING FROM STRING nodeopts { 1025 node.action = NODE_ACTION_FILTER; 1026 node.key = strdup($5); 1027 node.value = strdup($3); 1028 if (node.key == NULL || node.value == NULL) 1029 fatal("out of memory"); 1030 free($5); 1031 free($3); 1032 proto->lateconnect++; 1033 } 1034 | nodetype FILTER STRING nodeopts { 1035 node.action = NODE_ACTION_FILTER; 1036 node.key = strdup($3); 1037 node.value = strdup("*"); 1038 if (node.key == NULL || node.value == NULL) 1039 fatal("out of memory"); 1040 free($3); 1041 proto->lateconnect++; 1042 } 1043 | nodetype FILTER { 1044 node.action = NODE_ACTION_FILTER; 1045 node.key = NULL; 1046 node.value = "*"; 1047 proto->lateconnect++; 1048 } nodefile 1049 | nodetype FILTER digest nodeopts { 1050 if (node.type != NODE_TYPE_URL) { 1051 yyerror("digest not supported for this type"); 1052 free($3.digest); 1053 YYERROR; 1054 } 1055 node.action = NODE_ACTION_FILTER; 1056 node.key = strdup($3.digest); 1057 node.flags |= PNFLAG_LOOKUP_DIGEST($3.type); 1058 node.value = strdup("*"); 1059 if (node.key == NULL || node.value == NULL) 1060 fatal("out of memory"); 1061 free($3.digest); 1062 proto->lateconnect++; 1063 } 1064 | nodetype HASH STRING nodeopts { 1065 node.action = NODE_ACTION_HASH; 1066 node.key = strdup($3); 1067 node.value = NULL; 1068 if (node.key == NULL) 1069 fatal("out of memory"); 1070 free($3); 1071 proto->lateconnect++; 1072 } 1073 | nodetype LOG STRING nodeopts { 1074 node.action = NODE_ACTION_LOG; 1075 node.key = strdup($3); 1076 node.value = NULL; 1077 node.flags |= PNFLAG_LOG; 1078 if (node.key == NULL) 1079 fatal("out of memory"); 1080 free($3); 1081 } 1082 | nodetype LOG { 1083 node.action = NODE_ACTION_LOG; 1084 node.key = NULL; 1085 node.value = NULL; 1086 node.flags |= PNFLAG_LOG; 1087 } nodefile 1088 | nodetype MARK STRING FROM STRING WITH mark log { 1089 node.action = NODE_ACTION_MARK; 1090 node.key = strdup($5); 1091 node.value = strdup($3); 1092 node.mark = $7; 1093 if (node.key == NULL || node.value == NULL) 1094 fatal("out of memory"); 1095 free($3); 1096 free($5); 1097 } 1098 | nodetype MARK STRING WITH mark nodeopts { 1099 node.action = NODE_ACTION_MARK; 1100 node.key = strdup($3); 1101 node.value = strdup("*"); 1102 node.mark = $5; /* overwrite */ 1103 if (node.key == NULL || node.value == NULL) 1104 fatal("out of memory"); 1105 free($3); 1106 } 1107 ; 1108 1109 nodefile : FILENAME STRING nodeopts { 1110 if (protonode_load(nodedirection, 1111 proto, &node, $2) == -1) { 1112 yyerror("failed to load from file: %s", $2); 1113 free($2); 1114 YYERROR; 1115 } 1116 free($2); 1117 nodedirection = -1; /* don't add template node */ 1118 } 1119 ; 1120 1121 nodeopts : marked log 1122 ; 1123 1124 marked : /* empty */ 1125 | MARKED mark { node.mark = $2; } 1126 ; 1127 1128 log : /* empty */ 1129 | LOG { node.flags |= PNFLAG_LOG; } 1130 ; 1131 1132 mark : NUMBER { 1133 if ($1 <= 0 || $1 >= (int)USHRT_MAX) { 1134 yyerror("invalid mark: %d", $1); 1135 YYERROR; 1136 } 1137 $$ = $1; 1138 } 1139 ; 1140 1141 nodetype : HEADER { 1142 node.type = NODE_TYPE_HEADER; 1143 } 1144 | QUERYSTR { node.type = NODE_TYPE_QUERY; } 1145 | COOKIE { 1146 node.type = NODE_TYPE_COOKIE; 1147 } 1148 | PATH { 1149 proto->flags |= F_LOOKUP_PATH; 1150 node.type = NODE_TYPE_PATH; 1151 } 1152 | URL { node.type = NODE_TYPE_URL; } 1153 ; 1154 1155 sslcache : NUMBER { 1156 if ($1 < 0) { 1157 yyerror("invalid sslcache value: %d", $1); 1158 YYERROR; 1159 } 1160 $$ = $1; 1161 } 1162 | DISABLE { $$ = -2; } 1163 ; 1164 1165 relay : RELAY STRING { 1166 struct relay *r; 1167 1168 TAILQ_FOREACH(r, conf->sc_relays, rl_entry) 1169 if (!strcmp(r->rl_conf.name, $2)) 1170 break; 1171 if (r != NULL) { 1172 yyerror("relay %s defined twice", $2); 1173 free($2); 1174 YYERROR; 1175 } 1176 TAILQ_INIT(&relays); 1177 1178 if ((r = calloc(1, sizeof (*r))) == NULL) 1179 fatal("out of memory"); 1180 1181 if (strlcpy(r->rl_conf.name, $2, sizeof(r->rl_conf.name)) >= 1182 sizeof(r->rl_conf.name)) { 1183 yyerror("relay name truncated"); 1184 free(r); 1185 YYERROR; 1186 } 1187 free($2); 1188 r->rl_conf.id = ++last_relay_id; 1189 r->rl_conf.timeout.tv_sec = RELAY_TIMEOUT; 1190 r->rl_proto = NULL; 1191 r->rl_conf.proto = EMPTY_ID; 1192 r->rl_conf.dsttable = EMPTY_ID; 1193 r->rl_conf.dstmode = RELAY_DSTMODE_DEFAULT; 1194 r->rl_conf.dstretry = 0; 1195 if (last_relay_id == INT_MAX) { 1196 yyerror("too many relays defined"); 1197 free(r); 1198 YYERROR; 1199 } 1200 rlay = r; 1201 } '{' optnl relayopts_l '}' { 1202 struct relay *r; 1203 1204 if (rlay->rl_conf.ss.ss_family == AF_UNSPEC) { 1205 yyerror("relay %s has no listener", 1206 rlay->rl_conf.name); 1207 YYERROR; 1208 } 1209 if ((rlay->rl_conf.flags & F_NATLOOK) == 0 && 1210 rlay->rl_conf.dstss.ss_family == AF_UNSPEC && 1211 rlay->rl_conf.dsttable == EMPTY_ID) { 1212 yyerror("relay %s has no target, rdr, " 1213 "or table", rlay->rl_conf.name); 1214 YYERROR; 1215 } 1216 if (rlay->rl_conf.proto == EMPTY_ID) { 1217 rlay->rl_proto = &conf->sc_proto_default; 1218 rlay->rl_conf.proto = conf->sc_proto_default.id; 1219 } 1220 if (relay_load_certfiles(rlay) == -1) { 1221 yyerror("cannot load certificates for relay %s", 1222 rlay->rl_conf.name); 1223 YYERROR; 1224 } 1225 conf->sc_relaycount++; 1226 SPLAY_INIT(&rlay->rl_sessions); 1227 TAILQ_INSERT_TAIL(conf->sc_relays, rlay, rl_entry); 1228 tableport = 0; 1229 1230 while ((r = TAILQ_FIRST(&relays)) != NULL) { 1231 TAILQ_REMOVE(&relays, r, rl_entry); 1232 if (relay_inherit(rlay, r) == NULL) { 1233 YYERROR; 1234 } 1235 } 1236 rlay = NULL; 1237 } 1238 ; 1239 1240 relayopts_l : relayopts_l relayoptsl nl 1241 | relayoptsl optnl 1242 ; 1243 1244 relayoptsl : LISTEN ON STRING port optssl { 1245 struct addresslist al; 1246 struct address *h; 1247 struct relay *r; 1248 1249 if (rlay->rl_conf.ss.ss_family != AF_UNSPEC) { 1250 if ((r = calloc(1, sizeof (*r))) == NULL) 1251 fatal("out of memory"); 1252 TAILQ_INSERT_TAIL(&relays, r, rl_entry); 1253 } else 1254 r = rlay; 1255 if ($4.op != PF_OP_EQ) { 1256 yyerror("invalid port"); 1257 free($3); 1258 YYERROR; 1259 } 1260 1261 TAILQ_INIT(&al); 1262 if (host($3, &al, 1, &$4, NULL, -1) <= 0) { 1263 yyerror("invalid listen ip: %s", $3); 1264 free($3); 1265 YYERROR; 1266 } 1267 free($3); 1268 h = TAILQ_FIRST(&al); 1269 bcopy(&h->ss, &r->rl_conf.ss, sizeof(r->rl_conf.ss)); 1270 r->rl_conf.port = h->port.val[0]; 1271 if ($5) { 1272 r->rl_conf.flags |= F_SSL; 1273 conf->sc_flags |= F_SSL; 1274 } 1275 tableport = h->port.val[0]; 1276 } 1277 | forwardmode optsslclient TO forwardspec interface dstaf { 1278 rlay->rl_conf.fwdmode = $1; 1279 switch ($1) { 1280 case FWD_NORMAL: 1281 if ($5 == NULL) 1282 break; 1283 yyerror("superfluous interface"); 1284 YYERROR; 1285 case FWD_ROUTE: 1286 yyerror("no route for redirections"); 1287 YYERROR; 1288 case FWD_TRANS: 1289 if ($5 != NULL) 1290 break; 1291 yyerror("missing interface"); 1292 YYERROR; 1293 } 1294 if ($5 != NULL) { 1295 strlcpy(rlay->rl_conf.ifname, $5, 1296 sizeof(rlay->rl_conf.ifname)); 1297 free($5); 1298 } 1299 if ($2) { 1300 rlay->rl_conf.flags |= F_SSLCLIENT; 1301 conf->sc_flags |= F_SSLCLIENT; 1302 } 1303 } 1304 | SESSION TIMEOUT NUMBER { 1305 if ((rlay->rl_conf.timeout.tv_sec = $3) < 0) { 1306 yyerror("invalid timeout: %d", $3); 1307 YYERROR; 1308 } 1309 } 1310 | PROTO STRING { 1311 struct protocol *p; 1312 1313 TAILQ_FOREACH(p, conf->sc_protos, entry) 1314 if (!strcmp(p->name, $2)) 1315 break; 1316 if (p == NULL) { 1317 yyerror("no such protocol: %s", $2); 1318 free($2); 1319 YYERROR; 1320 } 1321 p->flags |= F_USED; 1322 rlay->rl_conf.proto = p->id; 1323 rlay->rl_proto = p; 1324 free($2); 1325 } 1326 | DISABLE { rlay->rl_conf.flags |= F_DISABLE; } 1327 | include 1328 ; 1329 1330 forwardspec : STRING port retry { 1331 struct addresslist al; 1332 struct address *h; 1333 1334 if (rlay->rl_conf.dstss.ss_family != AF_UNSPEC) { 1335 yyerror("relay %s target or redirection already " 1336 "specified", rlay->rl_conf.name); 1337 free($1); 1338 YYERROR; 1339 } 1340 if ($2.op != PF_OP_EQ) { 1341 yyerror("invalid port"); 1342 free($1); 1343 YYERROR; 1344 } 1345 1346 TAILQ_INIT(&al); 1347 if (host($1, &al, 1, &$2, NULL, -1) <= 0) { 1348 yyerror("invalid listen ip: %s", $1); 1349 free($1); 1350 YYERROR; 1351 } 1352 free($1); 1353 h = TAILQ_FIRST(&al); 1354 bcopy(&h->ss, &rlay->rl_conf.dstss, 1355 sizeof(rlay->rl_conf.dstss)); 1356 rlay->rl_conf.dstport = h->port.val[0]; 1357 rlay->rl_conf.dstretry = $3; 1358 } 1359 | NAT LOOKUP retry { 1360 conf->sc_flags |= F_NEEDPF; 1361 rlay->rl_conf.flags |= F_NATLOOK; 1362 rlay->rl_conf.dstretry = $3; 1363 } 1364 | tablespec { 1365 if (rlay->rl_dsttable) { 1366 yyerror("table already specified"); 1367 purge_table(conf->sc_tables, $1); 1368 YYERROR; 1369 } 1370 1371 rlay->rl_dsttable = $1; 1372 rlay->rl_dsttable->conf.flags |= F_USED; 1373 rlay->rl_conf.dsttable = $1->conf.id; 1374 rlay->rl_conf.dstport = $1->conf.port; 1375 } 1376 ; 1377 1378 dstmode : /* empty */ { $$ = RELAY_DSTMODE_DEFAULT; } 1379 | LOADBALANCE { $$ = RELAY_DSTMODE_LOADBALANCE; } 1380 | ROUNDROBIN { $$ = RELAY_DSTMODE_ROUNDROBIN; } 1381 | HASH { $$ = RELAY_DSTMODE_HASH; } 1382 ; 1383 1384 router : ROUTER STRING { 1385 struct router *rt = NULL; 1386 1387 conf->sc_flags |= F_NEEDRT; 1388 TAILQ_FOREACH(rt, conf->sc_rts, rt_entry) 1389 if (!strcmp(rt->rt_conf.name, $2)) 1390 break; 1391 if (rt != NULL) { 1392 yyerror("router %s defined twice", $2); 1393 free($2); 1394 YYERROR; 1395 } 1396 1397 if ((rt = calloc(1, sizeof (*rt))) == NULL) 1398 fatal("out of memory"); 1399 1400 if (strlcpy(rt->rt_conf.name, $2, 1401 sizeof(rt->rt_conf.name)) >= 1402 sizeof(rt->rt_conf.name)) { 1403 yyerror("router name truncated"); 1404 free(rt); 1405 YYERROR; 1406 } 1407 free($2); 1408 rt->rt_conf.id = ++last_rt_id; 1409 if (last_rt_id == INT_MAX) { 1410 yyerror("too many routers defined"); 1411 free(rt); 1412 YYERROR; 1413 } 1414 TAILQ_INIT(&rt->rt_netroutes); 1415 router = rt; 1416 1417 tableport = -1; 1418 } '{' optnl routeopts_l '}' { 1419 if (!router->rt_conf.nroutes) { 1420 yyerror("router %s without routes", 1421 router->rt_conf.name); 1422 free(router); 1423 router = NULL; 1424 YYERROR; 1425 } 1426 1427 conf->sc_routercount++; 1428 TAILQ_INSERT_TAIL(conf->sc_rts, router, rt_entry); 1429 router = NULL; 1430 1431 tableport = 0; 1432 } 1433 ; 1434 1435 routeopts_l : routeopts_l routeoptsl nl 1436 | routeoptsl optnl 1437 ; 1438 1439 routeoptsl : ROUTE address '/' NUMBER { 1440 struct netroute *nr; 1441 1442 if (router->rt_af == AF_UNSPEC) 1443 router->rt_af = $2.ss.ss_family; 1444 else if (router->rt_af != $2.ss.ss_family) { 1445 yyerror("router %s address family mismatch", 1446 router->rt_conf.name); 1447 YYERROR; 1448 } 1449 1450 if ((router->rt_af == AF_INET && ($4 > 32 || $4 < 0)) || 1451 (router->rt_af == AF_INET6 && ($4 > 128 || $4 < 0))) { 1452 yyerror("invalid prefixlen %d", $4); 1453 YYERROR; 1454 } 1455 1456 if ((nr = calloc(1, sizeof(*nr))) == NULL) 1457 fatal("out of memory"); 1458 1459 nr->nr_conf.id = ++last_nr_id; 1460 if (last_nr_id == INT_MAX) { 1461 yyerror("too many routes defined"); 1462 free(nr); 1463 YYERROR; 1464 } 1465 nr->nr_conf.prefixlen = $4; 1466 nr->nr_conf.routerid = router->rt_conf.id; 1467 nr->nr_router = router; 1468 bcopy(&$2.ss, &nr->nr_conf.ss, sizeof($2.ss)); 1469 1470 router->rt_conf.nroutes++; 1471 conf->sc_routecount++; 1472 TAILQ_INSERT_TAIL(&router->rt_netroutes, nr, nr_entry); 1473 TAILQ_INSERT_TAIL(conf->sc_routes, nr, nr_route); 1474 } 1475 | FORWARD TO tablespec { 1476 if (router->rt_gwtable) { 1477 yyerror("router %s table already specified", 1478 router->rt_conf.name); 1479 purge_table(conf->sc_tables, $3); 1480 YYERROR; 1481 } 1482 router->rt_gwtable = $3; 1483 router->rt_gwtable->conf.flags |= F_USED; 1484 router->rt_conf.gwtable = $3->conf.id; 1485 router->rt_conf.gwport = $3->conf.port; 1486 } 1487 | RTABLE NUMBER { 1488 if (router->rt_conf.rtable) { 1489 yyerror("router %s rtable already specified", 1490 router->rt_conf.name); 1491 YYERROR; 1492 } 1493 if ($2 < 0 || $2 > RT_TABLEID_MAX) { 1494 yyerror("invalid rtable id %d", $2); 1495 YYERROR; 1496 } 1497 router->rt_conf.rtable = $2; 1498 } 1499 | RTLABEL STRING { 1500 if (strlcpy(router->rt_conf.label, $2, 1501 sizeof(router->rt_conf.label)) >= 1502 sizeof(router->rt_conf.label)) { 1503 yyerror("route label truncated"); 1504 free($2); 1505 YYERROR; 1506 } 1507 free($2); 1508 } 1509 | DISABLE { rlay->rl_conf.flags |= F_DISABLE; } 1510 | include 1511 ; 1512 1513 dstaf : /* empty */ { 1514 rlay->rl_conf.dstaf.ss_family = AF_UNSPEC; 1515 } 1516 | INET { 1517 rlay->rl_conf.dstaf.ss_family = AF_INET; 1518 } 1519 | INET6 STRING { 1520 struct sockaddr_in6 *sin6; 1521 1522 sin6 = (struct sockaddr_in6 *)&rlay->rl_conf.dstaf; 1523 if (inet_pton(AF_INET6, $2, &sin6->sin6_addr) == -1) { 1524 yyerror("invalid ipv6 address %s", $2); 1525 free($2); 1526 YYERROR; 1527 } 1528 free($2); 1529 1530 sin6->sin6_family = AF_INET6; 1531 sin6->sin6_len = sizeof(*sin6); 1532 } 1533 ; 1534 1535 interface : /*empty*/ { $$ = NULL; } 1536 | INTERFACE STRING { $$ = $2; } 1537 ; 1538 1539 host : address { 1540 if ((hst = calloc(1, sizeof(*(hst)))) == NULL) 1541 fatal("out of memory"); 1542 1543 if (strlcpy(hst->conf.name, $1.name, 1544 sizeof(hst->conf.name)) >= sizeof(hst->conf.name)) { 1545 yyerror("host name truncated"); 1546 free(hst); 1547 YYERROR; 1548 } 1549 bcopy(&$1.ss, &hst->conf.ss, sizeof($1.ss)); 1550 hst->conf.id = 0; /* will be set later */ 1551 SLIST_INIT(&hst->children); 1552 } opthostflags { 1553 $$ = hst; 1554 hst = NULL; 1555 } 1556 ; 1557 1558 opthostflags : /* empty */ 1559 | hostflags_l 1560 ; 1561 1562 hostflags_l : hostflags hostflags_l 1563 | hostflags 1564 ; 1565 1566 hostflags : RETRY NUMBER { 1567 if (hst->conf.retry) { 1568 yyerror("retry value already set"); 1569 YYERROR; 1570 } 1571 if ($2 < 0) { 1572 yyerror("invalid retry value: %d\n", $2); 1573 YYERROR; 1574 } 1575 hst->conf.retry = $2; 1576 } 1577 | PARENT NUMBER { 1578 if (hst->conf.parentid) { 1579 yyerror("parent value already set"); 1580 YYERROR; 1581 } 1582 if ($2 < 0) { 1583 yyerror("invalid parent value: %d\n", $2); 1584 YYERROR; 1585 } 1586 hst->conf.parentid = $2; 1587 } 1588 | IP TTL NUMBER { 1589 if (hst->conf.ttl) { 1590 yyerror("ttl value already set"); 1591 YYERROR; 1592 } 1593 if ($3 < 0) { 1594 yyerror("invalid ttl value: %d\n", $3); 1595 YYERROR; 1596 } 1597 hst->conf.ttl = $3; 1598 } 1599 ; 1600 1601 address : STRING { 1602 struct address *a; 1603 struct addresslist al; 1604 1605 if (strlcpy($$.name, $1, 1606 sizeof($$.name)) >= sizeof($$.name)) { 1607 yyerror("host name truncated"); 1608 free($1); 1609 YYERROR; 1610 } 1611 1612 TAILQ_INIT(&al); 1613 if (host($1, &al, 1, NULL, NULL, -1) <= 0) { 1614 yyerror("invalid host %s", $1); 1615 free($1); 1616 YYERROR; 1617 } 1618 free($1); 1619 a = TAILQ_FIRST(&al); 1620 memcpy(&$$.ss, &a->ss, sizeof($$.ss)); 1621 free(a); 1622 } 1623 ; 1624 1625 retry : /* empty */ { $$ = 0; } 1626 | RETRY NUMBER { 1627 if (($$ = $2) < 0) { 1628 yyerror("invalid retry value: %d\n", $2); 1629 YYERROR; 1630 } 1631 } 1632 ; 1633 1634 timeout : NUMBER 1635 { 1636 if ($1 < 0) { 1637 yyerror("invalid timeout: %d\n", $1); 1638 YYERROR; 1639 } 1640 $$.tv_sec = $1 / 1000; 1641 $$.tv_usec = ($1 % 1000) * 1000; 1642 } 1643 ; 1644 1645 comma : ',' 1646 | nl 1647 | /* empty */ 1648 ; 1649 1650 optnl : '\n' optnl 1651 | 1652 ; 1653 1654 nl : '\n' optnl 1655 ; 1656 1657 %% 1658 1659 struct keywords { 1660 const char *k_name; 1661 int k_val; 1662 }; 1663 1664 int 1665 yyerror(const char *fmt, ...) 1666 { 1667 va_list ap; 1668 1669 file->errors++; 1670 va_start(ap, fmt); 1671 fprintf(stderr, "%s:%d: ", file->name, yylval.lineno); 1672 vfprintf(stderr, fmt, ap); 1673 fprintf(stderr, "\n"); 1674 va_end(ap); 1675 return (0); 1676 } 1677 1678 int 1679 kw_cmp(const void *k, const void *e) 1680 { 1681 return (strcmp(k, ((const struct keywords *)e)->k_name)); 1682 } 1683 1684 int 1685 lookup(char *s) 1686 { 1687 /* this has to be sorted always */ 1688 static const struct keywords keywords[] = { 1689 { "all", ALL }, 1690 { "append", APPEND }, 1691 { "backlog", BACKLOG }, 1692 { "backup", BACKUP }, 1693 { "buffer", BUFFER }, 1694 { "ca", CA }, 1695 { "cache", CACHE }, 1696 { "change", CHANGE }, 1697 { "check", CHECK }, 1698 { "ciphers", CIPHERS }, 1699 { "code", CODE }, 1700 { "cookie", COOKIE }, 1701 { "demote", DEMOTE }, 1702 { "digest", DIGEST }, 1703 { "disable", DISABLE }, 1704 { "error", ERROR }, 1705 { "expect", EXPECT }, 1706 { "external", EXTERNAL }, 1707 { "file", FILENAME }, 1708 { "filter", FILTER }, 1709 { "forward", FORWARD }, 1710 { "from", FROM }, 1711 { "hash", HASH }, 1712 { "header", HEADER }, 1713 { "host", HOST }, 1714 { "icmp", ICMP }, 1715 { "include", INCLUDE }, 1716 { "inet", INET }, 1717 { "inet6", INET6 }, 1718 { "interface", INTERFACE }, 1719 { "interval", INTERVAL }, 1720 { "ip", IP }, 1721 { "label", LABEL }, 1722 { "listen", LISTEN }, 1723 { "loadbalance", LOADBALANCE }, 1724 { "log", LOG }, 1725 { "lookup", LOOKUP }, 1726 { "mark", MARK }, 1727 { "marked", MARKED }, 1728 { "mode", MODE }, 1729 { "nat", NAT }, 1730 { "no", NO }, 1731 { "nodelay", NODELAY }, 1732 { "nothing", NOTHING }, 1733 { "on", ON }, 1734 { "parent", PARENT }, 1735 { "path", PATH }, 1736 { "port", PORT }, 1737 { "prefork", PREFORK }, 1738 { "protocol", PROTO }, 1739 { "query", QUERYSTR }, 1740 { "real", REAL }, 1741 { "redirect", REDIRECT }, 1742 { "relay", RELAY }, 1743 { "remove", REMOVE }, 1744 { "request", REQUEST }, 1745 { "response", RESPONSE }, 1746 { "retry", RETRY }, 1747 { "return", RETURN }, 1748 { "roundrobin", ROUNDROBIN }, 1749 { "route", ROUTE }, 1750 { "router", ROUTER }, 1751 { "rtable", RTABLE }, 1752 { "rtlabel", RTLABEL }, 1753 { "sack", SACK }, 1754 { "script", SCRIPT }, 1755 { "send", SEND }, 1756 { "session", SESSION }, 1757 { "socket", SOCKET }, 1758 { "ssl", SSL }, 1759 { "sticky-address", STICKYADDR }, 1760 { "style", STYLE }, 1761 { "table", TABLE }, 1762 { "tag", TAG }, 1763 { "tcp", TCP }, 1764 { "timeout", TIMEOUT }, 1765 { "to", TO }, 1766 { "transparent", TRANSPARENT }, 1767 { "trap", TRAP }, 1768 { "ttl", TTL }, 1769 { "updates", UPDATES }, 1770 { "url", URL }, 1771 { "virtual", VIRTUAL }, 1772 { "with", WITH } 1773 }; 1774 const struct keywords *p; 1775 1776 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 1777 sizeof(keywords[0]), kw_cmp); 1778 1779 if (p) 1780 return (p->k_val); 1781 else 1782 return (STRING); 1783 } 1784 1785 #define MAXPUSHBACK 128 1786 1787 char *parsebuf; 1788 int parseindex; 1789 char pushback_buffer[MAXPUSHBACK]; 1790 int pushback_index = 0; 1791 1792 int 1793 lgetc(int quotec) 1794 { 1795 int c, next; 1796 1797 if (parsebuf) { 1798 /* Read character from the parsebuffer instead of input. */ 1799 if (parseindex >= 0) { 1800 c = parsebuf[parseindex++]; 1801 if (c != '\0') 1802 return (c); 1803 parsebuf = NULL; 1804 } else 1805 parseindex++; 1806 } 1807 1808 if (pushback_index) 1809 return (pushback_buffer[--pushback_index]); 1810 1811 if (quotec) { 1812 if ((c = getc(file->stream)) == EOF) { 1813 yyerror("reached end of file while parsing " 1814 "quoted string"); 1815 if (file == topfile || popfile() == EOF) 1816 return (EOF); 1817 return (quotec); 1818 } 1819 return (c); 1820 } 1821 1822 while ((c = getc(file->stream)) == '\\') { 1823 next = getc(file->stream); 1824 if (next != '\n') { 1825 c = next; 1826 break; 1827 } 1828 yylval.lineno = file->lineno; 1829 file->lineno++; 1830 } 1831 1832 while (c == EOF) { 1833 if (file == topfile || popfile() == EOF) 1834 return (EOF); 1835 c = getc(file->stream); 1836 } 1837 return (c); 1838 } 1839 1840 int 1841 lungetc(int c) 1842 { 1843 if (c == EOF) 1844 return (EOF); 1845 if (parsebuf) { 1846 parseindex--; 1847 if (parseindex >= 0) 1848 return (c); 1849 } 1850 if (pushback_index < MAXPUSHBACK-1) 1851 return (pushback_buffer[pushback_index++] = c); 1852 else 1853 return (EOF); 1854 } 1855 1856 int 1857 findeol(void) 1858 { 1859 int c; 1860 1861 parsebuf = NULL; 1862 1863 /* skip to either EOF or the first real EOL */ 1864 while (1) { 1865 if (pushback_index) 1866 c = pushback_buffer[--pushback_index]; 1867 else 1868 c = lgetc(0); 1869 if (c == '\n') { 1870 file->lineno++; 1871 break; 1872 } 1873 if (c == EOF) 1874 break; 1875 } 1876 return (ERROR); 1877 } 1878 1879 int 1880 yylex(void) 1881 { 1882 char buf[8096]; 1883 char *p, *val; 1884 int quotec, next, c; 1885 int token; 1886 1887 top: 1888 p = buf; 1889 while ((c = lgetc(0)) == ' ' || c == '\t') 1890 ; /* nothing */ 1891 1892 yylval.lineno = file->lineno; 1893 if (c == '#') 1894 while ((c = lgetc(0)) != '\n' && c != EOF) 1895 ; /* nothing */ 1896 if (c == '$' && parsebuf == NULL) { 1897 while (1) { 1898 if ((c = lgetc(0)) == EOF) 1899 return (0); 1900 1901 if (p + 1 >= buf + sizeof(buf) - 1) { 1902 yyerror("string too long"); 1903 return (findeol()); 1904 } 1905 if (isalnum(c) || c == '_') { 1906 *p++ = (char)c; 1907 continue; 1908 } 1909 *p = '\0'; 1910 lungetc(c); 1911 break; 1912 } 1913 val = symget(buf); 1914 if (val == NULL) { 1915 yyerror("macro '%s' not defined", buf); 1916 return (findeol()); 1917 } 1918 parsebuf = val; 1919 parseindex = 0; 1920 goto top; 1921 } 1922 1923 switch (c) { 1924 case '\'': 1925 case '"': 1926 quotec = c; 1927 while (1) { 1928 if ((c = lgetc(quotec)) == EOF) 1929 return (0); 1930 if (c == '\n') { 1931 file->lineno++; 1932 continue; 1933 } else if (c == '\\') { 1934 if ((next = lgetc(quotec)) == EOF) 1935 return (0); 1936 if (next == quotec || c == ' ' || c == '\t') 1937 c = next; 1938 else if (next == '\n') 1939 continue; 1940 else 1941 lungetc(next); 1942 } else if (c == quotec) { 1943 *p = '\0'; 1944 break; 1945 } 1946 if (p + 1 >= buf + sizeof(buf) - 1) { 1947 yyerror("string too long"); 1948 return (findeol()); 1949 } 1950 *p++ = (char)c; 1951 } 1952 yylval.v.string = strdup(buf); 1953 if (yylval.v.string == NULL) 1954 err(1, "yylex: strdup"); 1955 return (STRING); 1956 } 1957 1958 #define allowed_to_end_number(x) \ 1959 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 1960 1961 if (c == '-' || isdigit(c)) { 1962 do { 1963 *p++ = c; 1964 if ((unsigned)(p-buf) >= sizeof(buf)) { 1965 yyerror("string too long"); 1966 return (findeol()); 1967 } 1968 } while ((c = lgetc(0)) != EOF && isdigit(c)); 1969 lungetc(c); 1970 if (p == buf + 1 && buf[0] == '-') 1971 goto nodigits; 1972 if (c == EOF || allowed_to_end_number(c)) { 1973 const char *errstr = NULL; 1974 1975 *p = '\0'; 1976 yylval.v.number = strtonum(buf, LLONG_MIN, 1977 LLONG_MAX, &errstr); 1978 if (errstr) { 1979 yyerror("\"%s\" invalid number: %s", 1980 buf, errstr); 1981 return (findeol()); 1982 } 1983 return (NUMBER); 1984 } else { 1985 nodigits: 1986 while (p > buf + 1) 1987 lungetc(*--p); 1988 c = *--p; 1989 if (c == '-') 1990 return (c); 1991 } 1992 } 1993 1994 #define allowed_in_string(x) \ 1995 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 1996 x != '{' && x != '}' && x != '<' && x != '>' && \ 1997 x != '!' && x != '=' && x != '#' && \ 1998 x != ',' && x != '/')) 1999 2000 if (isalnum(c) || c == ':' || c == '_') { 2001 do { 2002 *p++ = c; 2003 if ((unsigned)(p-buf) >= sizeof(buf)) { 2004 yyerror("string too long"); 2005 return (findeol()); 2006 } 2007 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 2008 lungetc(c); 2009 *p = '\0'; 2010 if ((token = lookup(buf)) == STRING) 2011 if ((yylval.v.string = strdup(buf)) == NULL) 2012 err(1, "yylex: strdup"); 2013 return (token); 2014 } 2015 if (c == '\n') { 2016 yylval.lineno = file->lineno; 2017 file->lineno++; 2018 } 2019 if (c == EOF) 2020 return (0); 2021 return (c); 2022 } 2023 2024 int 2025 check_file_secrecy(int fd, const char *fname) 2026 { 2027 struct stat st; 2028 2029 if (fstat(fd, &st)) { 2030 log_warn("cannot stat %s", fname); 2031 return (-1); 2032 } 2033 if (st.st_uid != 0 && st.st_uid != getuid()) { 2034 log_warnx("%s: owner not root or current user", fname); 2035 return (-1); 2036 } 2037 if (st.st_mode & (S_IRWXG | S_IRWXO)) { 2038 log_warnx("%s: group/world readable/writeable", fname); 2039 return (-1); 2040 } 2041 return (0); 2042 } 2043 2044 struct file * 2045 pushfile(const char *name, int secret) 2046 { 2047 struct file *nfile; 2048 2049 if ((nfile = calloc(1, sizeof(struct file))) == NULL) { 2050 log_warn("malloc"); 2051 return (NULL); 2052 } 2053 if ((nfile->name = strdup(name)) == NULL) { 2054 log_warn("malloc"); 2055 free(nfile); 2056 return (NULL); 2057 } 2058 if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 2059 log_warn("%s", nfile->name); 2060 free(nfile->name); 2061 free(nfile); 2062 return (NULL); 2063 } else if (secret && 2064 check_file_secrecy(fileno(nfile->stream), nfile->name)) { 2065 fclose(nfile->stream); 2066 free(nfile->name); 2067 free(nfile); 2068 return (NULL); 2069 } 2070 nfile->lineno = 1; 2071 TAILQ_INSERT_TAIL(&files, nfile, entry); 2072 return (nfile); 2073 } 2074 2075 int 2076 popfile(void) 2077 { 2078 struct file *prev; 2079 2080 if ((prev = TAILQ_PREV(file, files, entry)) != NULL) 2081 prev->errors += file->errors; 2082 2083 TAILQ_REMOVE(&files, file, entry); 2084 fclose(file->stream); 2085 free(file->name); 2086 free(file); 2087 file = prev; 2088 return (file ? 0 : EOF); 2089 } 2090 2091 struct relayd * 2092 parse_config(const char *filename, int opts) 2093 { 2094 struct sym *sym, *next; 2095 struct table *nexttb; 2096 struct host *h, *ph; 2097 2098 if ((conf = calloc(1, sizeof(*conf))) == NULL || 2099 (conf->sc_tables = calloc(1, sizeof(*conf->sc_tables))) == NULL || 2100 (conf->sc_relays = calloc(1, sizeof(*conf->sc_relays))) == NULL || 2101 (conf->sc_protos = calloc(1, sizeof(*conf->sc_protos))) == NULL || 2102 (conf->sc_routes = calloc(1, sizeof(*conf->sc_routes))) == NULL || 2103 (conf->sc_rts = calloc(1, sizeof(*conf->sc_rts))) == NULL || 2104 (conf->sc_rdrs = calloc(1, sizeof(*conf->sc_rdrs))) == NULL) { 2105 if (conf != NULL) { 2106 if (conf->sc_tables != NULL) 2107 free(conf->sc_tables); 2108 if (conf->sc_relays != NULL) 2109 free(conf->sc_relays); 2110 if (conf->sc_protos != NULL) 2111 free(conf->sc_protos); 2112 if (conf->sc_rdrs != NULL) 2113 free(conf->sc_rdrs); 2114 if (conf->sc_rts != NULL) 2115 free(conf->sc_rts); 2116 free(conf); 2117 } 2118 log_warn("cannot allocate memory"); 2119 return (NULL); 2120 } 2121 2122 errors = 0; 2123 last_host_id = last_table_id = last_rdr_id = last_proto_id = 2124 last_relay_id = last_rt_id = last_nr_id = 0; 2125 2126 rdr = NULL; 2127 table = NULL; 2128 rlay = NULL; 2129 proto = NULL; 2130 router = NULL; 2131 2132 TAILQ_INIT(conf->sc_rdrs); 2133 TAILQ_INIT(conf->sc_tables); 2134 TAILQ_INIT(conf->sc_protos); 2135 TAILQ_INIT(conf->sc_relays); 2136 TAILQ_INIT(conf->sc_rts); 2137 TAILQ_INIT(conf->sc_routes); 2138 2139 memset(&conf->sc_empty_table, 0, sizeof(conf->sc_empty_table)); 2140 conf->sc_empty_table.conf.id = EMPTY_TABLE; 2141 conf->sc_empty_table.conf.flags |= F_DISABLE; 2142 (void)strlcpy(conf->sc_empty_table.conf.name, "empty", 2143 sizeof(conf->sc_empty_table.conf.name)); 2144 2145 bzero(&conf->sc_proto_default, sizeof(conf->sc_proto_default)); 2146 conf->sc_proto_default.flags = F_USED; 2147 conf->sc_proto_default.cache = RELAY_CACHESIZE; 2148 conf->sc_proto_default.type = RELAY_PROTO_TCP; 2149 (void)strlcpy(conf->sc_proto_default.name, "default", 2150 sizeof(conf->sc_proto_default.name)); 2151 RB_INIT(&conf->sc_proto_default.request_tree); 2152 RB_INIT(&conf->sc_proto_default.response_tree); 2153 2154 conf->sc_timeout.tv_sec = CHECK_TIMEOUT / 1000; 2155 conf->sc_timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000; 2156 conf->sc_interval.tv_sec = CHECK_INTERVAL; 2157 conf->sc_interval.tv_usec = 0; 2158 conf->sc_prefork_relay = RELAY_NUMPROC; 2159 conf->sc_statinterval.tv_sec = RELAY_STATINTERVAL; 2160 conf->sc_opts = opts; 2161 conf->sc_confpath = filename; 2162 2163 if ((file = pushfile(filename, 0)) == NULL) { 2164 free(conf); 2165 return (NULL); 2166 } 2167 topfile = file; 2168 setservent(1); 2169 2170 yyparse(); 2171 errors = file->errors; 2172 popfile(); 2173 2174 endservent(); 2175 endprotoent(); 2176 2177 /* Free macros and check which have not been used. */ 2178 for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) { 2179 next = TAILQ_NEXT(sym, entry); 2180 if ((conf->sc_opts & RELAYD_OPT_VERBOSE) && !sym->used) 2181 fprintf(stderr, "warning: macro '%s' not " 2182 "used\n", sym->nam); 2183 if (!sym->persist) { 2184 free(sym->nam); 2185 free(sym->val); 2186 TAILQ_REMOVE(&symhead, sym, entry); 2187 free(sym); 2188 } 2189 } 2190 2191 if (TAILQ_EMPTY(conf->sc_rdrs) && 2192 TAILQ_EMPTY(conf->sc_relays) && 2193 TAILQ_EMPTY(conf->sc_rts)) { 2194 log_warnx("no actions, nothing to do"); 2195 errors++; 2196 } 2197 2198 if (TAILQ_EMPTY(conf->sc_relays)) 2199 conf->sc_prefork_relay = 0; 2200 2201 /* Cleanup relay list to inherit */ 2202 while ((rlay = TAILQ_FIRST(&relays)) != NULL) { 2203 TAILQ_REMOVE(&relays, rlay, rl_entry); 2204 free(rlay); 2205 } 2206 2207 if (timercmp(&conf->sc_timeout, &conf->sc_interval, >=)) { 2208 log_warnx("global timeout exceeds interval"); 2209 errors++; 2210 } 2211 2212 /* Verify that every table is used */ 2213 for (table = TAILQ_FIRST(conf->sc_tables); table != NULL; 2214 table = nexttb) { 2215 nexttb = TAILQ_NEXT(table, entry); 2216 if (table->conf.port == 0) { 2217 TAILQ_REMOVE(conf->sc_tables, table, entry); 2218 while ((h = TAILQ_FIRST(&table->hosts)) != NULL) { 2219 TAILQ_REMOVE(&table->hosts, h, entry); 2220 free(h); 2221 } 2222 if (table->sendbuf != NULL) 2223 free(table->sendbuf); 2224 free(table); 2225 continue; 2226 } 2227 2228 TAILQ_FOREACH(h, &table->hosts, entry) { 2229 if (h->conf.parentid) { 2230 ph = host_find(conf, h->conf.parentid); 2231 2232 /* Validate the parent id */ 2233 if (h->conf.id == h->conf.parentid || 2234 ph == NULL || ph->conf.parentid) 2235 ph = NULL; 2236 2237 if (ph == NULL) { 2238 log_warnx("host parent id %d invalid", 2239 h->conf.parentid); 2240 errors++; 2241 } else 2242 SLIST_INSERT_HEAD(&ph->children, 2243 h, child); 2244 } 2245 } 2246 2247 if (!(table->conf.flags & F_USED)) { 2248 log_warnx("unused table: %s", table->conf.name); 2249 errors++; 2250 } 2251 if (timercmp(&table->conf.timeout, &conf->sc_interval, >=)) { 2252 log_warnx("table timeout exceeds interval: %s", 2253 table->conf.name); 2254 errors++; 2255 } 2256 } 2257 2258 /* Verify that every non-default protocol is used */ 2259 TAILQ_FOREACH(proto, conf->sc_protos, entry) { 2260 if (!(proto->flags & F_USED)) { 2261 log_warnx("unused protocol: %s", proto->name); 2262 } 2263 } 2264 2265 if (errors) { 2266 free(conf); 2267 return (NULL); 2268 } 2269 2270 return (conf); 2271 } 2272 2273 int 2274 symset(const char *nam, const char *val, int persist) 2275 { 2276 struct sym *sym; 2277 2278 for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); 2279 sym = TAILQ_NEXT(sym, entry)) 2280 ; /* nothing */ 2281 2282 if (sym != NULL) { 2283 if (sym->persist == 1) 2284 return (0); 2285 else { 2286 free(sym->nam); 2287 free(sym->val); 2288 TAILQ_REMOVE(&symhead, sym, entry); 2289 free(sym); 2290 } 2291 } 2292 if ((sym = calloc(1, sizeof(*sym))) == NULL) 2293 return (-1); 2294 2295 sym->nam = strdup(nam); 2296 if (sym->nam == NULL) { 2297 free(sym); 2298 return (-1); 2299 } 2300 sym->val = strdup(val); 2301 if (sym->val == NULL) { 2302 free(sym->nam); 2303 free(sym); 2304 return (-1); 2305 } 2306 sym->used = 0; 2307 sym->persist = persist; 2308 TAILQ_INSERT_TAIL(&symhead, sym, entry); 2309 return (0); 2310 } 2311 2312 int 2313 cmdline_symset(char *s) 2314 { 2315 char *sym, *val; 2316 int ret; 2317 size_t len; 2318 2319 if ((val = strrchr(s, '=')) == NULL) 2320 return (-1); 2321 2322 len = strlen(s) - strlen(val) + 1; 2323 if ((sym = malloc(len)) == NULL) 2324 errx(1, "cmdline_symset: malloc"); 2325 2326 (void)strlcpy(sym, s, len); 2327 2328 ret = symset(sym, val + 1, 1); 2329 free(sym); 2330 2331 return (ret); 2332 } 2333 2334 char * 2335 symget(const char *nam) 2336 { 2337 struct sym *sym; 2338 2339 TAILQ_FOREACH(sym, &symhead, entry) 2340 if (strcmp(nam, sym->nam) == 0) { 2341 sym->used = 1; 2342 return (sym->val); 2343 } 2344 return (NULL); 2345 } 2346 2347 struct address * 2348 host_v4(const char *s) 2349 { 2350 struct in_addr ina; 2351 struct sockaddr_in *sain; 2352 struct address *h; 2353 2354 bzero(&ina, sizeof(ina)); 2355 if (inet_pton(AF_INET, s, &ina) != 1) 2356 return (NULL); 2357 2358 if ((h = calloc(1, sizeof(*h))) == NULL) 2359 fatal(NULL); 2360 sain = (struct sockaddr_in *)&h->ss; 2361 sain->sin_len = sizeof(struct sockaddr_in); 2362 sain->sin_family = AF_INET; 2363 sain->sin_addr.s_addr = ina.s_addr; 2364 2365 return (h); 2366 } 2367 2368 struct address * 2369 host_v6(const char *s) 2370 { 2371 struct addrinfo hints, *res; 2372 struct sockaddr_in6 *sa_in6; 2373 struct address *h = NULL; 2374 2375 bzero(&hints, sizeof(hints)); 2376 hints.ai_family = AF_INET6; 2377 hints.ai_socktype = SOCK_DGRAM; /* dummy */ 2378 hints.ai_flags = AI_NUMERICHOST; 2379 if (getaddrinfo(s, "0", &hints, &res) == 0) { 2380 if ((h = calloc(1, sizeof(*h))) == NULL) 2381 fatal(NULL); 2382 sa_in6 = (struct sockaddr_in6 *)&h->ss; 2383 sa_in6->sin6_len = sizeof(struct sockaddr_in6); 2384 sa_in6->sin6_family = AF_INET6; 2385 memcpy(&sa_in6->sin6_addr, 2386 &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 2387 sizeof(sa_in6->sin6_addr)); 2388 sa_in6->sin6_scope_id = 2389 ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 2390 2391 freeaddrinfo(res); 2392 } 2393 2394 return (h); 2395 } 2396 2397 int 2398 host_dns(const char *s, struct addresslist *al, int max, 2399 struct portrange *port, const char *ifname, int ipproto) 2400 { 2401 struct addrinfo hints, *res0, *res; 2402 int error, cnt = 0; 2403 struct sockaddr_in *sain; 2404 struct sockaddr_in6 *sin6; 2405 struct address *h; 2406 2407 if ((cnt = host_if(s, al, max, port, ifname, ipproto)) != 0) 2408 return (cnt); 2409 2410 bzero(&hints, sizeof(hints)); 2411 hints.ai_family = PF_UNSPEC; 2412 hints.ai_socktype = SOCK_DGRAM; /* DUMMY */ 2413 error = getaddrinfo(s, NULL, &hints, &res0); 2414 if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME) 2415 return (0); 2416 if (error) { 2417 log_warnx("host_dns: could not parse \"%s\": %s", s, 2418 gai_strerror(error)); 2419 return (-1); 2420 } 2421 2422 for (res = res0; res && cnt < max; res = res->ai_next) { 2423 if (res->ai_family != AF_INET && 2424 res->ai_family != AF_INET6) 2425 continue; 2426 if ((h = calloc(1, sizeof(*h))) == NULL) 2427 fatal(NULL); 2428 2429 if (port != NULL) 2430 bcopy(port, &h->port, sizeof(h->port)); 2431 if (ifname != NULL) { 2432 if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >= 2433 sizeof(h->ifname)) 2434 log_warnx("host_dns: interface name truncated"); 2435 freeaddrinfo(res0); 2436 return (-1); 2437 } 2438 if (ipproto != -1) 2439 h->ipproto = ipproto; 2440 h->ss.ss_family = res->ai_family; 2441 2442 if (res->ai_family == AF_INET) { 2443 sain = (struct sockaddr_in *)&h->ss; 2444 sain->sin_len = sizeof(struct sockaddr_in); 2445 sain->sin_addr.s_addr = ((struct sockaddr_in *) 2446 res->ai_addr)->sin_addr.s_addr; 2447 } else { 2448 sin6 = (struct sockaddr_in6 *)&h->ss; 2449 sin6->sin6_len = sizeof(struct sockaddr_in6); 2450 memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *) 2451 res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); 2452 } 2453 2454 TAILQ_INSERT_HEAD(al, h, entry); 2455 cnt++; 2456 } 2457 if (cnt == max && res) { 2458 log_warnx("host_dns: %s resolves to more than %d hosts", 2459 s, max); 2460 } 2461 freeaddrinfo(res0); 2462 return (cnt); 2463 } 2464 2465 int 2466 host_if(const char *s, struct addresslist *al, int max, 2467 struct portrange *port, const char *ifname, int ipproto) 2468 { 2469 struct ifaddrs *ifap, *p; 2470 struct sockaddr_in *sain; 2471 struct sockaddr_in6 *sin6; 2472 struct address *h; 2473 int cnt = 0, af; 2474 2475 if (if_nametoindex(s) == 0) 2476 return (0); 2477 2478 if (getifaddrs(&ifap) == -1) 2479 fatal("getifaddrs"); 2480 2481 /* First search for IPv4 addresses */ 2482 af = AF_INET; 2483 2484 nextaf: 2485 for (p = ifap; p != NULL && cnt < max; p = p->ifa_next) { 2486 if (p->ifa_addr->sa_family != af || 2487 strcmp(s, p->ifa_name) != 0) 2488 continue; 2489 if ((h = calloc(1, sizeof(*h))) == NULL) 2490 fatal("calloc"); 2491 2492 if (port != NULL) 2493 bcopy(port, &h->port, sizeof(h->port)); 2494 if (ifname != NULL) { 2495 if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >= 2496 sizeof(h->ifname)) 2497 log_warnx("host_if: interface name truncated"); 2498 freeifaddrs(ifap); 2499 return (-1); 2500 } 2501 if (ipproto != -1) 2502 h->ipproto = ipproto; 2503 h->ss.ss_family = af; 2504 2505 if (af == AF_INET) { 2506 sain = (struct sockaddr_in *)&h->ss; 2507 sain->sin_len = sizeof(struct sockaddr_in); 2508 sain->sin_addr.s_addr = ((struct sockaddr_in *) 2509 p->ifa_addr)->sin_addr.s_addr; 2510 } else { 2511 sin6 = (struct sockaddr_in6 *)&h->ss; 2512 sin6->sin6_len = sizeof(struct sockaddr_in6); 2513 memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *) 2514 p->ifa_addr)->sin6_addr, sizeof(struct in6_addr)); 2515 sin6->sin6_scope_id = ((struct sockaddr_in6 *) 2516 p->ifa_addr)->sin6_scope_id; 2517 } 2518 2519 TAILQ_INSERT_HEAD(al, h, entry); 2520 cnt++; 2521 } 2522 if (af == AF_INET) { 2523 /* Next search for IPv6 addresses */ 2524 af = AF_INET6; 2525 goto nextaf; 2526 } 2527 2528 if (cnt > max) { 2529 log_warnx("host_if: %s resolves to more than %d hosts", 2530 s, max); 2531 } 2532 freeifaddrs(ifap); 2533 return (cnt); 2534 } 2535 2536 int 2537 host(const char *s, struct addresslist *al, int max, 2538 struct portrange *port, const char *ifname, int ipproto) 2539 { 2540 struct address *h; 2541 2542 h = host_v4(s); 2543 2544 /* IPv6 address? */ 2545 if (h == NULL) 2546 h = host_v6(s); 2547 2548 if (h != NULL) { 2549 if (port != NULL) 2550 bcopy(port, &h->port, sizeof(h->port)); 2551 if (ifname != NULL) { 2552 if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >= 2553 sizeof(h->ifname)) { 2554 log_warnx("host: interface name truncated"); 2555 return (-1); 2556 } 2557 } 2558 if (ipproto != -1) 2559 h->ipproto = ipproto; 2560 2561 TAILQ_INSERT_HEAD(al, h, entry); 2562 return (1); 2563 } 2564 2565 return (host_dns(s, al, max, port, ifname, ipproto)); 2566 } 2567 2568 struct table * 2569 table_inherit(struct table *tb) 2570 { 2571 char pname[TABLE_NAME_SIZE + 6]; 2572 struct host *h, *dsth; 2573 struct table *dsttb, *oldtb; 2574 2575 /* Get the table or table template */ 2576 if ((dsttb = table_findbyname(conf, tb->conf.name)) == NULL) { 2577 yyerror("unknown table %s", tb->conf.name); 2578 purge_table(NULL, tb); 2579 return (NULL); 2580 } 2581 if (dsttb->conf.port != 0) 2582 fatal("invalid table"); /* should not happen */ 2583 2584 if (tb->conf.port == 0) { 2585 yyerror("invalid port"); 2586 purge_table(NULL, tb); 2587 return (NULL); 2588 } 2589 2590 /* Check if a matching table already exists */ 2591 if (snprintf(pname, sizeof(pname), "%s:%u", 2592 tb->conf.name, ntohs(tb->conf.port)) >= (int)sizeof(pname)) { 2593 yyerror("invalid table name"); 2594 return (NULL); 2595 } 2596 (void)strlcpy(tb->conf.name, pname, sizeof(tb->conf.name)); 2597 if ((oldtb = table_findbyconf(conf, tb)) != NULL) 2598 return (oldtb); 2599 2600 /* Create a new table */ 2601 tb->conf.id = ++last_table_id; 2602 if (last_table_id == INT_MAX) { 2603 yyerror("too many tables defined"); 2604 purge_table(NULL, tb); 2605 return (NULL); 2606 } 2607 tb->conf.flags |= dsttb->conf.flags; 2608 2609 /* Inherit global table options */ 2610 bcopy(&dsttb->conf.timeout, &tb->conf.timeout, sizeof(struct timeval)); 2611 tb->conf.skip_cnt = dsttb->conf.skip_cnt; 2612 strlcpy(tb->conf.demote_group, dsttb->conf.demote_group, 2613 sizeof(tb->conf.demote_group)); 2614 2615 /* Copy the associated hosts */ 2616 TAILQ_INIT(&tb->hosts); 2617 TAILQ_FOREACH(dsth, &dsttb->hosts, entry) { 2618 if ((h = (struct host *) 2619 calloc(1, sizeof (*h))) == NULL) 2620 fatal("out of memory"); 2621 bcopy(dsth, h, sizeof(*h)); 2622 h->conf.id = ++last_host_id; 2623 if (last_host_id == INT_MAX) { 2624 yyerror("too many hosts defined"); 2625 purge_table(NULL, tb); 2626 return (NULL); 2627 } 2628 h->conf.tableid = tb->conf.id; 2629 h->tablename = tb->conf.name; 2630 SLIST_INIT(&h->children); 2631 TAILQ_INSERT_TAIL(&tb->hosts, h, entry); 2632 } 2633 2634 conf->sc_tablecount++; 2635 TAILQ_INSERT_TAIL(conf->sc_tables, tb, entry); 2636 2637 return (tb); 2638 } 2639 2640 struct relay * 2641 relay_inherit(struct relay *ra, struct relay *rb) 2642 { 2643 struct relay_config rc; 2644 2645 bcopy(&rb->rl_conf, &rc, sizeof(rc)); 2646 bcopy(ra, rb, sizeof(*rb)); 2647 2648 bcopy(&rc.ss, &rb->rl_conf.ss, sizeof(rb->rl_conf.ss)); 2649 rb->rl_conf.port = rc.port; 2650 rb->rl_conf.flags = 2651 (ra->rl_conf.flags & ~F_SSL) | (rc.flags & F_SSL); 2652 2653 rb->rl_conf.id = ++last_relay_id; 2654 if (last_relay_id == INT_MAX) { 2655 yyerror("too many relays defined"); 2656 goto err; 2657 } 2658 2659 if (snprintf(rb->rl_conf.name, sizeof(rb->rl_conf.name), "%s%u:%u", 2660 ra->rl_conf.name, rb->rl_conf.id, ntohs(rc.port)) >= 2661 (int)sizeof(rb->rl_conf.name)) { 2662 yyerror("invalid relay name"); 2663 goto err; 2664 } 2665 2666 if (relay_findbyname(conf, rb->rl_conf.name) != NULL || 2667 relay_findbyaddr(conf, &rb->rl_conf) != NULL) { 2668 yyerror("relay %s defined twice", rb->rl_conf.name); 2669 goto err; 2670 } 2671 if (relay_load_certfiles(rb) == -1) { 2672 yyerror("cannot load certificates for relay %s", 2673 rb->rl_conf.name); 2674 goto err; 2675 } 2676 2677 conf->sc_relaycount++; 2678 SPLAY_INIT(&rlay->rl_sessions); 2679 TAILQ_INSERT_TAIL(conf->sc_relays, rb, rl_entry); 2680 2681 return (rb); 2682 2683 err: 2684 free(rb); 2685 return (NULL); 2686 } 2687 2688 int 2689 getservice(char *n) 2690 { 2691 struct servent *s; 2692 const char *errstr; 2693 long long llval; 2694 2695 llval = strtonum(n, 0, UINT16_MAX, &errstr); 2696 if (errstr) { 2697 s = getservbyname(n, "tcp"); 2698 if (s == NULL) 2699 s = getservbyname(n, "udp"); 2700 if (s == NULL) { 2701 yyerror("unknown port %s", n); 2702 return (-1); 2703 } 2704 return (s->s_port); 2705 } 2706 2707 return (htons((u_short)llval)); 2708 } 2709