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