parse.y revision 1.82
1/* $OpenBSD: parse.y,v 1.82 2007/11/19 14:48:19 reyk Exp $ */ 2 3/* 4 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> 5 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 6 * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org> 7 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> 8 * Copyright (c) 2001 Markus Friedl. All rights reserved. 9 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 10 * Copyright (c) 2001 Theo de Raadt. All rights reserved. 11 * 12 * Permission to use, copy, modify, and distribute this software for any 13 * purpose with or without fee is hereby granted, provided that the above 14 * copyright notice and this permission notice appear in all copies. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 17 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 19 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 21 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 22 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 23 */ 24 25%{ 26#include <sys/types.h> 27#include <sys/socket.h> 28#include <sys/stat.h> 29#include <sys/queue.h> 30#include <netinet/in.h> 31#include <net/if.h> 32#include <arpa/inet.h> 33#include <arpa/nameser.h> 34 35#include <ctype.h> 36#include <unistd.h> 37#include <err.h> 38#include <errno.h> 39#include <event.h> 40#include <limits.h> 41#include <stdint.h> 42#include <stdarg.h> 43#include <stdio.h> 44#include <netdb.h> 45#include <string.h> 46 47#include <openssl/ssl.h> 48 49#include "hoststated.h" 50 51TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); 52static struct file { 53 TAILQ_ENTRY(file) entry; 54 FILE *stream; 55 char *name; 56 int lineno; 57 int errors; 58} *file; 59struct file *pushfile(const char *, int); 60int popfile(void); 61int check_file_secrecy(int, const char *); 62int yyparse(void); 63int yylex(void); 64int yyerror(const char *, ...); 65int kw_cmp(const void *, const void *); 66int lookup(char *); 67int lgetc(int); 68int lungetc(int); 69int findeol(void); 70 71TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 72struct sym { 73 TAILQ_ENTRY(sym) entry; 74 int used; 75 int persist; 76 char *nam; 77 char *val; 78}; 79int symset(const char *, const char *, int); 80char *symget(const char *); 81 82struct hoststated *conf = NULL; 83static int errors = 0; 84objid_t last_service_id = 0; 85objid_t last_table_id = 0; 86objid_t last_host_id = 0; 87objid_t last_relay_id = 0; 88objid_t last_proto_id = 0; 89 90static struct service *service = NULL; 91static struct table *table = NULL; 92static struct relay *rlay = NULL; 93static struct protocol *proto = NULL; 94static struct protonode node; 95 96struct address *host_v4(const char *); 97struct address *host_v6(const char *); 98int host_dns(const char *, struct addresslist *, 99 int, in_port_t, const char *); 100int host(const char *, struct addresslist *, 101 int, in_port_t, const char *); 102 103struct table *table_inherit(const char *, in_port_t); 104 105typedef struct { 106 union { 107 int64_t number; 108 char *string; 109 struct host *host; 110 struct timeval tv; 111 } v; 112 int lineno; 113} YYSTYPE; 114 115%} 116 117%token SERVICE TABLE BACKUP HOST REAL INCLUDE 118%token CHECK TCP ICMP EXTERNAL REQUEST RESPONSE 119%token TIMEOUT CODE DIGEST PORT TAG INTERFACE 120%token VIRTUAL INTERVAL DISABLE STICKYADDR BACKLOG PATH SCRIPT 121%token SEND EXPECT NOTHING SSL LOADBALANCE ROUNDROBIN CIPHERS COOKIE 122%token RELAY LISTEN ON FORWARD TO NAT LOOKUP PREFORK NO MARK MARKED 123%token PROTO SESSION CACHE APPEND CHANGE REMOVE FROM FILTER HASH HEADER 124%token LOG UPDATES ALL DEMOTE NODELAY SACK SOCKET BUFFER URL RETRY IP 125%token ERROR 126%token <v.string> STRING 127%token <v.number> NUMBER 128%type <v.string> interface hostname 129%type <v.number> port http_type loglevel sslcache optssl dstport 130%type <v.number> proto_type dstmode docheck retry log flag direction 131%type <v.host> host 132%type <v.tv> timeout 133 134%% 135 136grammar : /* empty */ 137 | grammar include '\n' 138 | grammar '\n' 139 | grammar varset '\n' 140 | grammar main '\n' 141 | grammar service '\n' 142 | grammar table '\n' 143 | grammar relay '\n' 144 | grammar proto '\n' 145 | grammar error '\n' { file->errors++; } 146 ; 147 148include : INCLUDE STRING { 149 struct file *nfile; 150 151 if ((nfile = pushfile($2, 0)) == NULL) { 152 yyerror("failed to include file %s", $2); 153 free($2); 154 YYERROR; 155 } 156 free($2); 157 158 file = nfile; 159 lungetc('\n'); 160 } 161 162optssl : /*empty*/ { $$ = 0; } 163 | SSL { $$ = 1; } 164 ; 165 166http_type : STRING { 167 if (strcmp("https", $1) == 0) { 168 $$ = 1; 169 } else if (strcmp("http", $1) == 0) { 170 $$ = 0; 171 } else { 172 yyerror("invalid check type: %s", $1); 173 free($1); 174 YYERROR; 175 } 176 free($1); 177 } 178 ; 179 180hostname : /* empty */ { 181 $$ = strdup(""); 182 if ($$ == NULL) 183 fatal("calloc"); 184 } 185 | HOST STRING { 186 if (asprintf(&$$, "Host: %s\r\n", $2) == -1) 187 fatal("asprintf"); 188 } 189 ; 190 191proto_type : TCP { $$ = RELAY_PROTO_TCP; } 192 | STRING { 193 if (strcmp("http", $1) == 0) { 194 $$ = RELAY_PROTO_HTTP; 195 } else if (strcmp("dns", $1) == 0) { 196 $$ = RELAY_PROTO_DNS; 197 } else { 198 yyerror("invalid protocol type: %s", $1); 199 free($1); 200 YYERROR; 201 } 202 free($1); 203 } 204 ; 205 206port : PORT STRING { 207 struct servent *servent; 208 209 servent = getservbyname($2, "tcp"); 210 if (servent == NULL) { 211 yyerror("port %s is invalid", $2); 212 free($2); 213 YYERROR; 214 } 215 $$ = servent->s_port; 216 free($2); 217 } 218 | PORT NUMBER { 219 if ($2 <= 0 || $2 >= (int)USHRT_MAX) { 220 yyerror("invalid port: %d", $2); 221 YYERROR; 222 } 223 $$ = htons($2); 224 } 225 ; 226 227varset : STRING '=' STRING { 228 if (symset($1, $3, 0) == -1) 229 fatal("cannot store variable"); 230 free($1); 231 free($3); 232 } 233 ; 234 235sendbuf : NOTHING { 236 table->sendbuf = NULL; 237 table->sendbuf_len = 0; 238 } 239 | STRING { 240 table->sendbuf = strdup($1); 241 if (table->sendbuf == NULL) 242 fatal("out of memory"); 243 table->sendbuf_len = strlen(table->sendbuf); 244 free($1); 245 } 246 ; 247 248main : INTERVAL NUMBER { 249 if ((conf->interval.tv_sec = $2) < 0) { 250 yyerror("invalid interval: %d", $2); 251 YYERROR; 252 } 253 } 254 | LOG loglevel { conf->opts |= $2; } 255 | TIMEOUT timeout { 256 bcopy(&$2, &conf->timeout, sizeof(struct timeval)); 257 } 258 | PREFORK NUMBER { 259 if ($2 <= 0 || $2 > RELAY_MAXPROC) { 260 yyerror("invalid number of preforked " 261 "relays: %d", $2); 262 YYERROR; 263 } 264 conf->prefork_relay = $2; 265 } 266 | DEMOTE STRING { 267 conf->flags |= F_DEMOTE; 268 if (strlcpy(conf->demote_group, $2, 269 sizeof(conf->demote_group)) 270 >= sizeof(conf->demote_group)) { 271 yyerror("yyparse: demote group name too long"); 272 free($2); 273 YYERROR; 274 } 275 free($2); 276 if (carp_demote_init(conf->demote_group, 1) == -1) { 277 yyerror("yyparse: error initializing group %s", 278 conf->demote_group); 279 YYERROR; 280 } 281 } 282 ; 283 284loglevel : UPDATES { $$ = HOSTSTATED_OPT_LOGUPDATE; } 285 | ALL { $$ = HOSTSTATED_OPT_LOGALL; } 286 ; 287 288service : SERVICE STRING { 289 struct service *srv; 290 291 TAILQ_FOREACH(srv, conf->services, entry) 292 if (!strcmp(srv->conf.name, $2)) 293 break; 294 if (srv != NULL) { 295 yyerror("service %s defined twice", $2); 296 free($2); 297 YYERROR; 298 } 299 if ((srv = calloc(1, sizeof (*srv))) == NULL) 300 fatal("out of memory"); 301 302 if (strlcpy(srv->conf.name, $2, 303 sizeof(srv->conf.name)) >= 304 sizeof(srv->conf.name)) { 305 yyerror("service name truncated"); 306 YYERROR; 307 } 308 free($2); 309 srv->conf.id = last_service_id++; 310 if (last_service_id == INT_MAX) { 311 yyerror("too many services defined"); 312 YYERROR; 313 } 314 service = srv; 315 } '{' optnl serviceopts_l '}' { 316 if (service->table == NULL) { 317 yyerror("service %s has no table", 318 service->conf.name); 319 YYERROR; 320 } 321 if (TAILQ_EMPTY(&service->virts)) { 322 yyerror("service %s has no virtual ip", 323 service->conf.name); 324 YYERROR; 325 } 326 conf->servicecount++; 327 if (service->backup == NULL) { 328 service->conf.backup_id = 329 conf->empty_table.conf.id; 330 service->backup = &conf->empty_table; 331 } else if (service->backup->conf.port != 332 service->table->conf.port) { 333 yyerror("service %s uses two different ports " 334 "for its table and backup table", 335 service->conf.name); 336 YYERROR; 337 } 338 339 if (!(service->conf.flags & F_DISABLE)) 340 service->conf.flags |= F_ADD; 341 TAILQ_INSERT_HEAD(conf->services, service, entry); 342 } 343 ; 344 345serviceopts_l : serviceopts_l serviceoptsl nl 346 | serviceoptsl optnl 347 ; 348 349serviceoptsl : TABLE STRING dstport { 350 struct table *tb; 351 in_port_t port; 352 353 port = $3; 354 if (port == 0) 355 port = service->conf.port; 356 if ((tb = table_inherit($2, port)) == NULL) { 357 free($2); 358 YYERROR; 359 } 360 free($2); 361 362 service->table = tb; 363 service->conf.table_id = tb->conf.id; 364 service->table->conf.serviceid = service->conf.id; 365 service->table->conf.flags |= F_USED; 366 } 367 | BACKUP TABLE STRING dstport { 368 struct table *tb; 369 in_port_t port; 370 371 if (service->backup) { 372 yyerror("backup already specified"); 373 free($3); 374 YYERROR; 375 } 376 377 port = $4; 378 if (port == 0) 379 port = service->conf.port; 380 if ((tb = table_inherit($3, port)) == NULL) { 381 free($3); 382 YYERROR; 383 } 384 free($3); 385 386 service->backup = tb; 387 service->conf.backup_id = tb->conf.id; 388 service->backup->conf.serviceid = service->conf.id; 389 service->backup->conf.flags |= (F_USED|F_BACKUP); 390 } 391 | VIRTUAL HOST STRING port interface { 392 if (host($3, &service->virts, 393 SRV_MAX_VIRTS, $4, $5) <= 0) { 394 yyerror("invalid virtual ip: %s", $3); 395 free($3); 396 free($5); 397 YYERROR; 398 } 399 free($3); 400 free($5); 401 if (service->conf.port == 0) 402 service->conf.port = $4; 403 } 404 | DISABLE { service->conf.flags |= F_DISABLE; } 405 | STICKYADDR { service->conf.flags |= F_STICKY; } 406 | TAG STRING { 407 if (strlcpy(service->conf.tag, $2, 408 sizeof(service->conf.tag)) >= 409 sizeof(service->conf.tag)) { 410 yyerror("service tag name truncated"); 411 free($2); 412 YYERROR; 413 } 414 free($2); 415 } 416 ; 417 418table : TABLE STRING { 419 struct table *tb; 420 421 TAILQ_FOREACH(tb, conf->tables, entry) 422 if (!strcmp(tb->conf.name, $2)) 423 break; 424 if (tb != NULL) { 425 yyerror("table %s defined twice", $2); 426 free($2); 427 YYERROR; 428 } 429 430 if ((tb = calloc(1, sizeof (*tb))) == NULL) 431 fatal("out of memory"); 432 433 if (strlcpy(tb->conf.name, $2, sizeof(tb->conf.name)) >= 434 sizeof(tb->conf.name)) { 435 yyerror("table name truncated"); 436 YYERROR; 437 } 438 tb->conf.id = last_table_id++; 439 bcopy(&conf->timeout, &tb->conf.timeout, 440 sizeof(struct timeval)); 441 if (last_table_id == INT_MAX) { 442 yyerror("too many tables defined"); 443 YYERROR; 444 } 445 free($2); 446 table = tb; 447 } '{' optnl tableopts_l '}' { 448 if (TAILQ_EMPTY(&table->hosts)) { 449 yyerror("table %s has no hosts", 450 table->conf.name); 451 YYERROR; 452 } 453 if (table->conf.check == CHECK_NOCHECK) { 454 yyerror("table %s has no check", 455 table->conf.name); 456 YYERROR; 457 } 458 conf->tablecount++; 459 TAILQ_INSERT_HEAD(conf->tables, table, entry); 460 } 461 ; 462 463tableopts_l : tableopts_l tableoptsl nl 464 | tableoptsl optnl 465 ; 466 467tableoptsl : host { 468 $1->conf.tableid = table->conf.id; 469 $1->tablename = table->conf.name; 470 TAILQ_INSERT_HEAD(&table->hosts, $1, entry); 471 } 472 | TIMEOUT timeout { 473 bcopy(&$2, &table->conf.timeout, 474 sizeof(struct timeval)); 475 } 476 | CHECK ICMP { 477 table->conf.check = CHECK_ICMP; 478 } 479 | CHECK TCP { 480 table->conf.check = CHECK_TCP; 481 } 482 | CHECK SSL { 483 table->conf.check = CHECK_TCP; 484 conf->flags |= F_SSL; 485 table->conf.flags |= F_SSL; 486 } 487 | CHECK http_type STRING hostname CODE NUMBER { 488 if ($2) { 489 conf->flags |= F_SSL; 490 table->conf.flags |= F_SSL; 491 } 492 table->conf.check = CHECK_HTTP_CODE; 493 if ((table->conf.retcode = $6) <= 0) { 494 yyerror("invalid HTTP code: %d", $6); 495 free($3); 496 free($4); 497 YYERROR; 498 } 499 if (asprintf(&table->sendbuf, 500 "HEAD %s HTTP/1.0\r\n%s\r\n", $3, $4) == -1) 501 fatal("asprintf"); 502 free($3); 503 free($4); 504 if (table->sendbuf == NULL) 505 fatal("out of memory"); 506 table->sendbuf_len = strlen(table->sendbuf); 507 } 508 | CHECK http_type STRING hostname DIGEST STRING { 509 if ($2) { 510 conf->flags |= F_SSL; 511 table->conf.flags |= F_SSL; 512 } 513 table->conf.check = CHECK_HTTP_DIGEST; 514 if (asprintf(&table->sendbuf, 515 "GET %s HTTP/1.0\r\n%s\r\n", $3, $4) == -1) 516 fatal("asprintf"); 517 free($3); 518 free($4); 519 if (table->sendbuf == NULL) 520 fatal("out of memory"); 521 table->sendbuf_len = strlen(table->sendbuf); 522 if (strlcpy(table->conf.digest, $6, 523 sizeof(table->conf.digest)) >= 524 sizeof(table->conf.digest)) { 525 yyerror("http digest truncated"); 526 free($6); 527 YYERROR; 528 } 529 free($6); 530 } 531 | CHECK SEND sendbuf EXPECT STRING optssl { 532 table->conf.check = CHECK_SEND_EXPECT; 533 if ($6) { 534 conf->flags |= F_SSL; 535 table->conf.flags |= F_SSL; 536 } 537 if (strlcpy(table->conf.exbuf, $5, 538 sizeof(table->conf.exbuf)) 539 >= sizeof(table->conf.exbuf)) { 540 yyerror("yyparse: expect buffer truncated"); 541 free($5); 542 YYERROR; 543 } 544 translate_string(table->conf.exbuf); 545 free($5); 546 } 547 | CHECK SCRIPT STRING { 548 table->conf.check = CHECK_SCRIPT; 549 if (strlcpy(table->conf.path, $3, 550 sizeof(table->conf.path)) >= 551 sizeof(table->conf.path)) { 552 yyerror("script path truncated"); 553 free($3); 554 YYERROR; 555 } 556 free($3); 557 } 558 | REAL port { 559 table->conf.port = $2; 560 } 561 | DEMOTE STRING { 562 table->conf.flags |= F_DEMOTE; 563 if (strlcpy(table->conf.demote_group, $2, 564 sizeof(table->conf.demote_group)) 565 >= sizeof(table->conf.demote_group)) { 566 yyerror("yyparse: demote group name too long"); 567 free($2); 568 YYERROR; 569 } 570 free($2); 571 if (carp_demote_init(table->conf.demote_group, 1) 572 == -1) { 573 yyerror("yyparse: error initializing group " 574 "'%s'", table->conf.demote_group); 575 YYERROR; 576 } 577 } 578 | DISABLE { 579 table->conf.flags |= F_DISABLE; 580 } 581 ; 582 583proto : PROTO STRING { 584 struct protocol *p; 585 586 if (strcmp($2, "default") == 0) { 587 p = &conf->proto_default; 588 } else { 589 TAILQ_FOREACH(p, conf->protos, entry) 590 if (!strcmp(p->name, $2)) 591 break; 592 } 593 if (p != NULL) { 594 yyerror("protocol %s defined twice", $2); 595 free($2); 596 YYERROR; 597 } 598 if ((p = calloc(1, sizeof (*p))) == NULL) 599 fatal("out of memory"); 600 601 if (strlcpy(p->name, $2, sizeof(p->name)) >= 602 sizeof(p->name)) { 603 yyerror("protocol name truncated"); 604 YYERROR; 605 } 606 free($2); 607 p->id = last_proto_id++; 608 p->cache = RELAY_CACHESIZE; 609 p->type = RELAY_PROTO_TCP; 610 p->tcpflags = TCPFLAG_DEFAULT; 611 p->sslflags = SSLFLAG_DEFAULT; 612 p->tcpbacklog = RELAY_BACKLOG; 613 (void)strlcpy(p->sslciphers, SSLCIPHERS_DEFAULT, 614 sizeof(p->sslciphers)); 615 if (last_proto_id == INT_MAX) { 616 yyerror("too many protocols defined"); 617 YYERROR; 618 } 619 RB_INIT(&p->request_tree); 620 RB_INIT(&p->response_tree); 621 proto = p; 622 } '{' optnl protopts_l '}' { 623 conf->protocount++; 624 625 if ((proto->sslflags & SSLFLAG_VERSION) == 0) { 626 yyerror("invalid SSL protocol"); 627 YYERROR; 628 } 629 630 TAILQ_INSERT_HEAD(conf->protos, proto, entry); 631 } 632 ; 633 634protopts_l : protopts_l protoptsl nl 635 | protoptsl optnl 636 ; 637 638protoptsl : SSL sslflags 639 | SSL '{' sslflags_l '}' 640 | TCP tcpflags 641 | TCP '{' tcpflags_l '}' 642 | PROTO proto_type { proto->type = $2; } 643 | direction protonode log { 644 struct protonode *pn, *proot, pk; 645 struct proto_tree *tree; 646 647 if ($1 == RELAY_DIR_RESPONSE) 648 tree = &proto->response_tree; 649 else 650 tree = &proto->request_tree; 651 if ((pn = calloc(1, sizeof (*pn))) == NULL) 652 fatal("out of memory"); 653 654 bcopy(&node, pn, sizeof(*pn)); 655 pn->key = node.key; 656 pn->value = node.value; 657 pn->type = node.type; 658 SIMPLEQ_INIT(&pn->head); 659 if ($1 == RELAY_DIR_RESPONSE) 660 pn->id = proto->response_nodes++; 661 else 662 pn->id = proto->request_nodes++; 663 if ($3) 664 pn->flags |= PNFLAG_LOG; 665 if (pn->id == INT_MAX) { 666 yyerror("too many protocol nodes defined"); 667 YYERROR; 668 } 669 if ((proot = 670 RB_INSERT(proto_tree, tree, pn)) != NULL) { 671 /* 672 * A protocol node with the same key already 673 * exists, append it to a queue behind the 674 * existing node. 675 */ 676 if (SIMPLEQ_EMPTY(&proot->head)) 677 SIMPLEQ_NEXT(proot, entry) = pn; 678 SIMPLEQ_INSERT_TAIL(&proot->head, pn, entry); 679 } 680 681 if (node.type == NODE_TYPE_COOKIE) 682 pk.key = "Cookie"; 683 else 684 pk.key = "GET"; 685 if (node.type != NODE_TYPE_HEADER) { 686 pk.type = NODE_TYPE_HEADER; 687 pn = RB_FIND(proto_tree, tree, &pk); 688 if (pn == NULL) { 689 if ((pn = (struct protonode *) 690 calloc(1, sizeof(*pn))) == NULL) 691 fatal("out of memory"); 692 pn->key = strdup(pk.key); 693 if (pn->key == NULL) 694 fatal("out of memory"); 695 pn->value = NULL; 696 pn->action = NODE_ACTION_NONE; 697 pn->type = pk.type; 698 if ($1 == RELAY_DIR_RESPONSE) 699 pn->id = 700 proto->response_nodes++; 701 else 702 pn->id = proto->request_nodes++; 703 if (pn->id == INT_MAX) { 704 yyerror("too many protocol " 705 "nodes defined"); 706 YYERROR; 707 } 708 RB_INSERT(proto_tree, tree, pn); 709 } 710 switch (node.type) { 711 case NODE_TYPE_URL: 712 pn->flags |= PNFLAG_LOOKUP_URL; 713 break; 714 case NODE_TYPE_COOKIE: 715 pn->flags |= PNFLAG_LOOKUP_COOKIE; 716 break; 717 default: 718 break; 719 } 720 } 721 722 bzero(&node, sizeof(node)); 723 } 724 ; 725 726direction : /* empty */ { $$ = RELAY_DIR_REQUEST; } 727 | REQUEST { $$ = RELAY_DIR_REQUEST; } 728 | RESPONSE { $$ = RELAY_DIR_RESPONSE; } 729 ; 730 731tcpflags_l : tcpflags comma tcpflags_l 732 | tcpflags 733 ; 734 735tcpflags : SACK { proto->tcpflags |= TCPFLAG_SACK; } 736 | NO SACK { proto->tcpflags |= TCPFLAG_NSACK; } 737 | NODELAY { proto->tcpflags |= TCPFLAG_NODELAY; } 738 | NO NODELAY { proto->tcpflags |= TCPFLAG_NNODELAY; } 739 | BACKLOG NUMBER { 740 if ($2 < 0 || $2 > RELAY_MAX_SESSIONS) { 741 yyerror("invalid backlog: %d", $2); 742 YYERROR; 743 } 744 proto->tcpbacklog = $2; 745 } 746 | SOCKET BUFFER NUMBER { 747 proto->tcpflags |= TCPFLAG_BUFSIZ; 748 if ((proto->tcpbufsiz = $3) < 0) { 749 yyerror("invalid socket buffer size: %d", $3); 750 YYERROR; 751 } 752 } 753 | IP STRING NUMBER { 754 if ($3 < 0) { 755 yyerror("invalid ttl: %d", $3); 756 free($2); 757 YYERROR; 758 } 759 if (strcasecmp("ttl", $2) == 0) { 760 proto->tcpflags |= TCPFLAG_IPTTL; 761 proto->tcpipttl = $3; 762 } else if (strcasecmp("minttl", $2) == 0) { 763 proto->tcpflags |= TCPFLAG_IPMINTTL; 764 proto->tcpipminttl = $3; 765 } else { 766 yyerror("invalid TCP/IP flag: %s", $2); 767 free($2); 768 YYERROR; 769 } 770 free($2); 771 } 772 ; 773 774sslflags_l : sslflags comma sslflags_l 775 | sslflags 776 ; 777 778sslflags : SESSION CACHE sslcache { proto->cache = $3; } 779 | CIPHERS STRING { 780 if (strlcpy(proto->sslciphers, $2, 781 sizeof(proto->sslciphers)) >= 782 sizeof(proto->sslciphers)) { 783 yyerror("sslciphers truncated"); 784 free($2); 785 YYERROR; 786 } 787 free($2); 788 } 789 | NO flag { proto->sslflags &= ~($2); } 790 | flag { proto->sslflags |= $1; } 791 ; 792 793flag : STRING { 794 if (strcmp("sslv2", $1) == 0) 795 $$ = SSLFLAG_SSLV2; 796 else if (strcmp("sslv3", $1) == 0) 797 $$ = SSLFLAG_SSLV3; 798 else if (strcmp("tlsv1", $1) == 0) 799 $$ = SSLFLAG_TLSV1; 800 else { 801 yyerror("invalid SSL flag: %s", $1); 802 free($1); 803 YYERROR; 804 } 805 free($1); 806 } 807 ; 808 809protonode : nodetype APPEND STRING TO STRING marked { 810 node.action = NODE_ACTION_APPEND; 811 node.key = strdup($5); 812 node.value = strdup($3); 813 if (node.key == NULL || node.value == NULL) 814 fatal("out of memory"); 815 if (strchr(node.value, '$') != NULL) 816 node.flags |= PNFLAG_MACRO; 817 free($5); 818 free($3); 819 } 820 | nodetype CHANGE STRING TO STRING marked { 821 node.action = NODE_ACTION_CHANGE; 822 node.key = strdup($3); 823 node.value = strdup($5); 824 if (node.key == NULL || node.value == NULL) 825 fatal("out of memory"); 826 if (strchr(node.value, '$') != NULL) 827 node.flags |= PNFLAG_MACRO; 828 free($5); 829 free($3); 830 } 831 | nodetype REMOVE STRING marked { 832 node.action = NODE_ACTION_REMOVE; 833 node.key = strdup($3); 834 node.value = NULL; 835 if (node.key == NULL) 836 fatal("out of memory"); 837 free($3); 838 } 839 | nodetype EXPECT STRING FROM STRING mark { 840 node.action = NODE_ACTION_EXPECT; 841 node.key = strdup($5); 842 node.value = strdup($3);; 843 if (node.key == NULL || node.value == NULL) 844 fatal("out of memory"); 845 free($5); 846 free($3); 847 proto->lateconnect++; 848 } 849 | nodetype FILTER STRING FROM STRING mark { 850 node.action = NODE_ACTION_FILTER; 851 node.key = strdup($5); 852 node.value = strdup($3);; 853 if (node.key == NULL || node.value == NULL) 854 fatal("out of memory"); 855 free($5); 856 free($3); 857 proto->lateconnect++; 858 } 859 | nodetype HASH STRING marked { 860 node.action = NODE_ACTION_HASH; 861 node.key = strdup($3); 862 node.value = NULL; 863 if (node.key == NULL) 864 fatal("out of memory"); 865 free($3); 866 proto->lateconnect++; 867 } 868 | nodetype LOG STRING marked { 869 node.action = NODE_ACTION_LOG; 870 node.key = strdup($3); 871 node.value = NULL; 872 node.flags |= PNFLAG_LOG; 873 if (node.key == NULL) 874 fatal("out of memory"); 875 free($3); 876 } 877 ; 878 879mark : /* empty */ 880 | MARK { node.flags |= PNFLAG_MARK; } 881 ; 882 883marked : /* empty */ 884 | MARKED { node.flags |= PNFLAG_MARK; } 885 ; 886 887nodetype : HEADER { 888 node.type = NODE_TYPE_HEADER; 889 } 890 | URL { node.type = NODE_TYPE_URL; } 891 | COOKIE { 892 node.type = NODE_TYPE_COOKIE; 893 } 894 | PATH { 895 proto->flags |= F_LOOKUP_PATH; 896 node.type = NODE_TYPE_PATH; 897 } 898 ; 899 900sslcache : NUMBER { 901 if ($1 < 0) { 902 yyerror("invalid sslcache value: %d", $1); 903 YYERROR; 904 } 905 $$ = $1; 906 } 907 | DISABLE { $$ = -2; } 908 ; 909 910relay : RELAY STRING { 911 struct relay *r; 912 913 TAILQ_FOREACH(r, conf->relays, entry) 914 if (!strcmp(r->conf.name, $2)) 915 break; 916 if (r != NULL) { 917 yyerror("relay %s defined twice", $2); 918 free($2); 919 YYERROR; 920 } 921 if ((r = calloc(1, sizeof (*r))) == NULL) 922 fatal("out of memory"); 923 924 if (strlcpy(r->conf.name, $2, sizeof(r->conf.name)) >= 925 sizeof(r->conf.name)) { 926 yyerror("relay name truncated"); 927 YYERROR; 928 } 929 free($2); 930 r->conf.id = last_relay_id++; 931 r->conf.timeout.tv_sec = RELAY_TIMEOUT; 932 r->proto = NULL; 933 r->conf.proto = EMPTY_ID; 934 r->conf.dsttable = EMPTY_ID; 935 r->conf.dstretry = 0; 936 if (last_relay_id == INT_MAX) { 937 yyerror("too many relays defined"); 938 YYERROR; 939 } 940 rlay = r; 941 } '{' optnl relayopts_l '}' { 942 if (rlay->conf.ss.ss_family == AF_UNSPEC) { 943 yyerror("relay %s has no listener", 944 rlay->conf.name); 945 YYERROR; 946 } 947 if ((rlay->conf.flags & F_NATLOOK) == 0 && 948 rlay->conf.dstss.ss_family == AF_UNSPEC && 949 rlay->conf.dsttable == EMPTY_ID) { 950 yyerror("relay %s has no target, service, " 951 "or table", rlay->conf.name); 952 YYERROR; 953 } 954 if (rlay->conf.proto == EMPTY_ID) { 955 rlay->proto = &conf->proto_default; 956 rlay->conf.proto = conf->proto_default.id; 957 } 958 if (relay_load_certfiles(rlay) == -1) { 959 yyerror("cannot load certificates for relay %s", 960 rlay->conf.name); 961 YYERROR; 962 } 963 conf->relaycount++; 964 SPLAY_INIT(&rlay->sessions); 965 TAILQ_INSERT_HEAD(conf->relays, rlay, entry); 966 } 967 ; 968 969relayopts_l : relayopts_l relayoptsl nl 970 | relayoptsl optnl 971 ; 972 973relayoptsl : LISTEN ON STRING port optssl { 974 struct addresslist al; 975 struct address *h; 976 977 if (rlay->conf.ss.ss_family != AF_UNSPEC) { 978 yyerror("relay %s listener already specified", 979 rlay->conf.name); 980 YYERROR; 981 } 982 983 TAILQ_INIT(&al); 984 if (host($3, &al, 1, $4, NULL) <= 0) { 985 yyerror("invalid listen ip: %s", $3); 986 free($3); 987 YYERROR; 988 } 989 free($3); 990 h = TAILQ_FIRST(&al); 991 bcopy(&h->ss, &rlay->conf.ss, sizeof(rlay->conf.ss)); 992 rlay->conf.port = h->port; 993 if ($5) { 994 rlay->conf.flags |= F_SSL; 995 conf->flags |= F_SSL; 996 } 997 } 998 | FORWARD TO STRING port retry { 999 struct addresslist al; 1000 struct address *h; 1001 1002 if (rlay->conf.dstss.ss_family != AF_UNSPEC) { 1003 yyerror("relay %s target or service already " 1004 "specified", rlay->conf.name); 1005 free($3); 1006 YYERROR; 1007 } 1008 1009 TAILQ_INIT(&al); 1010 if (host($3, &al, 1, $4, NULL) <= 0) { 1011 yyerror("invalid listen ip: %s", $3); 1012 free($3); 1013 YYERROR; 1014 } 1015 free($3); 1016 h = TAILQ_FIRST(&al); 1017 bcopy(&h->ss, &rlay->conf.dstss, 1018 sizeof(rlay->conf.dstss)); 1019 rlay->conf.dstport = h->port; 1020 rlay->conf.dstretry = $5; 1021 } 1022 | SERVICE STRING retry { 1023 struct service *svc; 1024 struct address *h; 1025 1026 if (rlay->conf.dstss.ss_family != AF_UNSPEC) { 1027 yyerror("relay %s target or service already " 1028 "specified", rlay->conf.name); 1029 free($2); 1030 YYERROR; 1031 } 1032 1033 if ((svc = service_findbyname(conf, $2)) == NULL) { 1034 yyerror("relay %s for unknown service %s", 1035 rlay->conf.name, $2); 1036 free($2); 1037 YYERROR; 1038 } 1039 free($2); 1040 h = TAILQ_FIRST(&svc->virts); 1041 bcopy(&h->ss, &rlay->conf.dstss, 1042 sizeof(rlay->conf.dstss)); 1043 rlay->conf.dstport = h->port; 1044 rlay->conf.dstretry = $3; 1045 } 1046 | TABLE STRING dstport dstmode docheck { 1047 struct table *tb; 1048 1049 rlay->conf.dstport = $3; 1050 if (rlay->conf.dstport == 0) 1051 rlay->conf.dstport = rlay->conf.port; 1052 1053 if ((tb = table_inherit($2, rlay->conf.dstport)) == 1054 NULL) { 1055 free($2); 1056 YYERROR; 1057 } 1058 free($2); 1059 rlay->conf.dsttable = tb->conf.id; 1060 rlay->dsttable = tb; 1061 rlay->conf.dstport = tb->conf.port; 1062 rlay->conf.dstmode = $4; 1063 rlay->conf.dstcheck = $5; 1064 rlay->dsttable->conf.flags |= F_USED; 1065 } 1066 | PROTO STRING { 1067 struct protocol *p; 1068 1069 TAILQ_FOREACH(p, conf->protos, entry) 1070 if (!strcmp(p->name, $2)) 1071 break; 1072 if (p == NULL) { 1073 yyerror("no such protocol: %s", $2); 1074 free($2); 1075 YYERROR; 1076 } 1077 p->flags |= F_USED; 1078 rlay->conf.proto = p->id; 1079 rlay->proto = p; 1080 free($2); 1081 } 1082 | NAT LOOKUP retry { 1083 rlay->conf.flags |= F_NATLOOK; 1084 rlay->conf.dstretry = $3; 1085 } 1086 | TIMEOUT NUMBER { 1087 if ((rlay->conf.timeout.tv_sec = $2) < 0) { 1088 yyerror("invalid timeout: %d", $2); 1089 YYERROR; 1090 } 1091 } 1092 | DISABLE { rlay->conf.flags |= F_DISABLE; } 1093 ; 1094 1095dstmode : /* empty */ { $$ = RELAY_DSTMODE_DEFAULT; } 1096 | LOADBALANCE { $$ = RELAY_DSTMODE_LOADBALANCE; } 1097 | ROUNDROBIN { $$ = RELAY_DSTMODE_ROUNDROBIN; } 1098 | HASH { $$ = RELAY_DSTMODE_HASH; } 1099 ; 1100 1101docheck : /* empty */ { $$ = 1; } 1102 | NO CHECK { $$ = 0; } 1103 ; 1104 1105interface : /*empty*/ { $$ = NULL; } 1106 | INTERFACE STRING { $$ = $2; } 1107 ; 1108 1109dstport : /* empty */ { $$ = 0; } 1110 | port { $$ = $1; } 1111 ; 1112 1113host : HOST STRING retry { 1114 struct address *a; 1115 struct addresslist al; 1116 1117 if (($$ = calloc(1, sizeof(*($$)))) == NULL) 1118 fatal("out of memory"); 1119 1120 TAILQ_INIT(&al); 1121 if (host($2, &al, 1, 0, NULL) <= 0) { 1122 yyerror("invalid host %s", $2); 1123 free($2); 1124 free($$); 1125 YYERROR; 1126 } 1127 a = TAILQ_FIRST(&al); 1128 memcpy(&$$->conf.ss, &a->ss, sizeof($$->conf.ss)); 1129 free(a); 1130 1131 if (strlcpy($$->conf.name, $2, sizeof($$->conf.name)) >= 1132 sizeof($$->conf.name)) { 1133 yyerror("host name truncated"); 1134 free($2); 1135 free($$); 1136 YYERROR; 1137 } 1138 free($2); 1139 $$->conf.id = last_host_id++; 1140 $$->conf.retry = $3; 1141 if (last_host_id == INT_MAX) { 1142 yyerror("too many hosts defined"); 1143 free($$); 1144 YYERROR; 1145 } 1146 } 1147 ; 1148 1149retry : /* nothing */ { $$ = 0; } 1150 | RETRY NUMBER { 1151 if (($$ = $2) < 0) { 1152 yyerror("invalid retry value: %d\n", $2); 1153 YYERROR; 1154 } 1155 } 1156 ; 1157 1158timeout : NUMBER 1159 { 1160 if ($1 < 0) { 1161 yyerror("invalid timeout: %d\n", $1); 1162 YYERROR; 1163 } 1164 $$.tv_sec = $1 / 1000; 1165 $$.tv_usec = ($1 % 1000) * 1000; 1166 } 1167 ; 1168 1169log : /* empty */ { $$ = 0; } 1170 | LOG { $$ = 1; } 1171 ; 1172 1173comma : ',' 1174 | /* empty */ 1175 ; 1176 1177optnl : '\n' optnl 1178 | 1179 ; 1180 1181nl : '\n' optnl 1182 ; 1183 1184%% 1185 1186struct keywords { 1187 const char *k_name; 1188 int k_val; 1189}; 1190 1191int 1192yyerror(const char *fmt, ...) 1193{ 1194 va_list ap; 1195 1196 file->errors++; 1197 va_start(ap, fmt); 1198 fprintf(stderr, "%s:%d: ", file->name, yylval.lineno); 1199 vfprintf(stderr, fmt, ap); 1200 fprintf(stderr, "\n"); 1201 va_end(ap); 1202 return (0); 1203} 1204 1205int 1206kw_cmp(const void *k, const void *e) 1207{ 1208 return (strcmp(k, ((const struct keywords *)e)->k_name)); 1209} 1210 1211int 1212lookup(char *s) 1213{ 1214 /* this has to be sorted always */ 1215 static const struct keywords keywords[] = { 1216 { "all", ALL }, 1217 { "append", APPEND }, 1218 { "backlog", BACKLOG }, 1219 { "backup", BACKUP }, 1220 { "buffer", BUFFER }, 1221 { "cache", CACHE }, 1222 { "change", CHANGE }, 1223 { "check", CHECK }, 1224 { "ciphers", CIPHERS }, 1225 { "code", CODE }, 1226 { "cookie", COOKIE }, 1227 { "demote", DEMOTE }, 1228 { "digest", DIGEST }, 1229 { "disable", DISABLE }, 1230 { "expect", EXPECT }, 1231 { "external", EXTERNAL }, 1232 { "filter", FILTER }, 1233 { "forward", FORWARD }, 1234 { "from", FROM }, 1235 { "hash", HASH }, 1236 { "header", HEADER }, 1237 { "host", HOST }, 1238 { "icmp", ICMP }, 1239 { "include", INCLUDE }, 1240 { "interface", INTERFACE }, 1241 { "interval", INTERVAL }, 1242 { "ip", IP }, 1243 { "listen", LISTEN }, 1244 { "loadbalance", LOADBALANCE }, 1245 { "log", LOG }, 1246 { "lookup", LOOKUP }, 1247 { "mark", MARK }, 1248 { "marked", MARKED }, 1249 { "nat", NAT }, 1250 { "no", NO }, 1251 { "nodelay", NODELAY }, 1252 { "nothing", NOTHING }, 1253 { "on", ON }, 1254 { "path", PATH }, 1255 { "port", PORT }, 1256 { "prefork", PREFORK }, 1257 { "protocol", PROTO }, 1258 { "real", REAL }, 1259 { "relay", RELAY }, 1260 { "remove", REMOVE }, 1261 { "request", REQUEST }, 1262 { "response", RESPONSE }, 1263 { "retry", RETRY }, 1264 { "roundrobin", ROUNDROBIN }, 1265 { "sack", SACK }, 1266 { "script", SCRIPT }, 1267 { "send", SEND }, 1268 { "service", SERVICE }, 1269 { "session", SESSION }, 1270 { "socket", SOCKET }, 1271 { "ssl", SSL }, 1272 { "sticky-address", STICKYADDR }, 1273 { "table", TABLE }, 1274 { "tag", TAG }, 1275 { "tcp", TCP }, 1276 { "timeout", TIMEOUT }, 1277 { "to", TO }, 1278 { "updates", UPDATES }, 1279 { "url", URL }, 1280 { "virtual", VIRTUAL } 1281 }; 1282 const struct keywords *p; 1283 1284 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 1285 sizeof(keywords[0]), kw_cmp); 1286 1287 if (p) 1288 return (p->k_val); 1289 else 1290 return (STRING); 1291} 1292 1293#define MAXPUSHBACK 128 1294 1295char *parsebuf; 1296int parseindex; 1297char pushback_buffer[MAXPUSHBACK]; 1298int pushback_index = 0; 1299 1300int 1301lgetc(int quotec) 1302{ 1303 int c, next; 1304 1305 if (parsebuf) { 1306 /* Read character from the parsebuffer instead of input. */ 1307 if (parseindex >= 0) { 1308 c = parsebuf[parseindex++]; 1309 if (c != '\0') 1310 return (c); 1311 parsebuf = NULL; 1312 } else 1313 parseindex++; 1314 } 1315 1316 if (pushback_index) 1317 return (pushback_buffer[--pushback_index]); 1318 1319 if (quotec) { 1320 if ((c = getc(file->stream)) == EOF) { 1321 yyerror("reached end of file while parsing quoted string"); 1322 if (popfile() == EOF) 1323 return (EOF); 1324 return (quotec); 1325 } 1326 return (c); 1327 } 1328 1329 while ((c = getc(file->stream)) == '\\') { 1330 next = getc(file->stream); 1331 if (next != '\n') { 1332 c = next; 1333 break; 1334 } 1335 yylval.lineno = file->lineno; 1336 file->lineno++; 1337 } 1338 1339 while (c == EOF) { 1340 if (popfile() == EOF) 1341 return (EOF); 1342 c = getc(file->stream); 1343 } 1344 return (c); 1345} 1346 1347int 1348lungetc(int c) 1349{ 1350 if (c == EOF) 1351 return (EOF); 1352 if (parsebuf) { 1353 parseindex--; 1354 if (parseindex >= 0) 1355 return (c); 1356 } 1357 if (pushback_index < MAXPUSHBACK-1) 1358 return (pushback_buffer[pushback_index++] = c); 1359 else 1360 return (EOF); 1361} 1362 1363int 1364findeol(void) 1365{ 1366 int c; 1367 1368 parsebuf = NULL; 1369 pushback_index = 0; 1370 1371 /* skip to either EOF or the first real EOL */ 1372 while (1) { 1373 c = lgetc(0); 1374 if (c == '\n') { 1375 file->lineno++; 1376 break; 1377 } 1378 if (c == EOF) 1379 break; 1380 } 1381 return (ERROR); 1382} 1383 1384int 1385yylex(void) 1386{ 1387 char buf[8096]; 1388 char *p, *val; 1389 int quotec, next, c; 1390 int token; 1391 1392top: 1393 p = buf; 1394 while ((c = lgetc(0)) == ' ' || c == '\t') 1395 ; /* nothing */ 1396 1397 yylval.lineno = file->lineno; 1398 if (c == '#') 1399 while ((c = lgetc(0)) != '\n' && c != EOF) 1400 ; /* nothing */ 1401 if (c == '$' && parsebuf == NULL) { 1402 while (1) { 1403 if ((c = lgetc(0)) == EOF) 1404 return (0); 1405 1406 if (p + 1 >= buf + sizeof(buf) - 1) { 1407 yyerror("string too long"); 1408 return (findeol()); 1409 } 1410 if (isalnum(c) || c == '_') { 1411 *p++ = (char)c; 1412 continue; 1413 } 1414 *p = '\0'; 1415 lungetc(c); 1416 break; 1417 } 1418 val = symget(buf); 1419 if (val == NULL) { 1420 yyerror("macro '%s' not defined", buf); 1421 return (findeol()); 1422 } 1423 parsebuf = val; 1424 parseindex = 0; 1425 goto top; 1426 } 1427 1428 switch (c) { 1429 case '\'': 1430 case '"': 1431 quotec = c; 1432 while (1) { 1433 if ((c = lgetc(quotec)) == EOF) 1434 return (0); 1435 if (c == '\n') { 1436 file->lineno++; 1437 continue; 1438 } else if (c == '\\') { 1439 if ((next = lgetc(quotec)) == EOF) 1440 return (0); 1441 if (next == quotec || c == ' ' || c == '\t') 1442 c = next; 1443 else if (next == '\n') 1444 continue; 1445 else 1446 lungetc(next); 1447 } else if (c == quotec) { 1448 *p = '\0'; 1449 break; 1450 } 1451 if (p + 1 >= buf + sizeof(buf) - 1) { 1452 yyerror("string too long"); 1453 return (findeol()); 1454 } 1455 *p++ = (char)c; 1456 } 1457 yylval.v.string = strdup(buf); 1458 if (yylval.v.string == NULL) 1459 err(1, "yylex: strdup"); 1460 return (STRING); 1461 } 1462 1463#define allowed_to_end_number(x) \ 1464 (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 1465 1466 if (c == '-' || isdigit(c)) { 1467 do { 1468 *p++ = c; 1469 if ((unsigned)(p-buf) >= sizeof(buf)) { 1470 yyerror("string too long"); 1471 return (findeol()); 1472 } 1473 } while ((c = lgetc(0)) != EOF && isdigit(c)); 1474 lungetc(c); 1475 if (p == buf + 1 && buf[0] == '-') 1476 goto nodigits; 1477 if (c == EOF || allowed_to_end_number(c)) { 1478 const char *errstr = NULL; 1479 1480 *p = '\0'; 1481 yylval.v.number = strtonum(buf, LLONG_MIN, 1482 LLONG_MAX, &errstr); 1483 if (errstr) { 1484 yyerror("\"%s\" invalid number: %s", 1485 buf, errstr); 1486 return (findeol()); 1487 } 1488 return (NUMBER); 1489 } else { 1490nodigits: 1491 while (p > buf + 1) 1492 lungetc(*--p); 1493 c = *--p; 1494 if (c == '-') 1495 return (c); 1496 } 1497 } 1498 1499#define allowed_in_string(x) \ 1500 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 1501 x != '{' && x != '}' && \ 1502 x != '!' && x != '=' && x != '#' && \ 1503 x != ',')) 1504 1505 if (isalnum(c) || c == ':' || c == '_') { 1506 do { 1507 *p++ = c; 1508 if ((unsigned)(p-buf) >= sizeof(buf)) { 1509 yyerror("string too long"); 1510 return (findeol()); 1511 } 1512 } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 1513 lungetc(c); 1514 *p = '\0'; 1515 if ((token = lookup(buf)) == STRING) 1516 if ((yylval.v.string = strdup(buf)) == NULL) 1517 err(1, "yylex: strdup"); 1518 return (token); 1519 } 1520 if (c == '\n') { 1521 yylval.lineno = file->lineno; 1522 file->lineno++; 1523 } 1524 if (c == EOF) 1525 return (0); 1526 return (c); 1527} 1528 1529int 1530check_file_secrecy(int fd, const char *fname) 1531{ 1532 struct stat st; 1533 1534 if (fstat(fd, &st)) { 1535 log_warn("cannot stat %s", fname); 1536 return (-1); 1537 } 1538 if (st.st_uid != 0 && st.st_uid != getuid()) { 1539 log_warnx("%s: owner not root or current user", fname); 1540 return (-1); 1541 } 1542 if (st.st_mode & (S_IRWXG | S_IRWXO)) { 1543 log_warnx("%s: group/world readable/writeable", fname); 1544 return (-1); 1545 } 1546 return (0); 1547} 1548 1549struct file * 1550pushfile(const char *name, int secret) 1551{ 1552 struct file *nfile; 1553 1554 if ((nfile = calloc(1, sizeof(struct file))) == NULL || 1555 (nfile->name = strdup(name)) == NULL) { 1556 log_warn("malloc"); 1557 return (NULL); 1558 } 1559 if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 1560 log_warn("%s", nfile->name); 1561 free(nfile->name); 1562 free(nfile); 1563 return (NULL); 1564 } else if (secret && 1565 check_file_secrecy(fileno(nfile->stream), nfile->name)) { 1566 fclose(nfile->stream); 1567 free(nfile->name); 1568 free(nfile); 1569 return (NULL); 1570 } 1571 nfile->lineno = 1; 1572 TAILQ_INSERT_TAIL(&files, nfile, entry); 1573 return (nfile); 1574} 1575 1576int 1577popfile(void) 1578{ 1579 struct file *prev; 1580 1581 if ((prev = TAILQ_PREV(file, files, entry)) != NULL) { 1582 prev->errors += file->errors; 1583 TAILQ_REMOVE(&files, file, entry); 1584 fclose(file->stream); 1585 free(file->name); 1586 free(file); 1587 file = prev; 1588 return (0); 1589 } 1590 return (EOF); 1591} 1592 1593struct hoststated * 1594parse_config(const char *filename, int opts) 1595{ 1596 struct sym *sym, *next; 1597 struct table *nexttb; 1598 struct host *h; 1599 1600 if ((conf = calloc(1, sizeof(*conf))) == NULL || 1601 (conf->tables = calloc(1, sizeof(*conf->tables))) == NULL || 1602 (conf->relays = calloc(1, sizeof(*conf->relays))) == NULL || 1603 (conf->protos = calloc(1, sizeof(*conf->protos))) == NULL || 1604 (conf->services = calloc(1, sizeof(*conf->services))) == NULL) { 1605 log_warn("cannot allocate memory"); 1606 return (NULL); 1607 } 1608 1609 errors = 0; 1610 last_host_id = last_table_id = last_service_id = last_proto_id = 1611 last_relay_id = 0; 1612 1613 service = NULL; 1614 table = NULL; 1615 rlay = NULL; 1616 proto = NULL; 1617 1618 TAILQ_INIT(conf->services); 1619 TAILQ_INIT(conf->tables); 1620 TAILQ_INIT(conf->protos); 1621 TAILQ_INIT(conf->relays); 1622 1623 memset(&conf->empty_table, 0, sizeof(conf->empty_table)); 1624 conf->empty_table.conf.id = EMPTY_TABLE; 1625 conf->empty_table.conf.flags |= F_DISABLE; 1626 (void)strlcpy(conf->empty_table.conf.name, "empty", 1627 sizeof(conf->empty_table.conf.name)); 1628 1629 bzero(&conf->proto_default, sizeof(conf->proto_default)); 1630 conf->proto_default.flags = F_USED; 1631 conf->proto_default.cache = RELAY_CACHESIZE; 1632 conf->proto_default.type = RELAY_PROTO_TCP; 1633 (void)strlcpy(conf->proto_default.name, "default", 1634 sizeof(conf->proto_default.name)); 1635 RB_INIT(&conf->proto_default.request_tree); 1636 RB_INIT(&conf->proto_default.response_tree); 1637 1638 conf->timeout.tv_sec = CHECK_TIMEOUT / 1000; 1639 conf->timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000; 1640 conf->interval.tv_sec = CHECK_INTERVAL; 1641 conf->interval.tv_usec = 0; 1642 conf->prefork_relay = RELAY_NUMPROC; 1643 conf->statinterval.tv_sec = RELAY_STATINTERVAL; 1644 conf->opts = opts; 1645 conf->confpath = filename; 1646 1647 if ((file = pushfile(filename, 0)) == NULL) { 1648 free(conf); 1649 return (NULL); 1650 } 1651 setservent(1); 1652 1653 yyparse(); 1654 errors = file->errors; 1655 popfile(); 1656 1657 endservent(); 1658 1659 /* Free macros and check which have not been used. */ 1660 for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) { 1661 next = TAILQ_NEXT(sym, entry); 1662 if ((conf->opts & HOSTSTATED_OPT_VERBOSE) && !sym->used) 1663 fprintf(stderr, "warning: macro '%s' not " 1664 "used\n", sym->nam); 1665 if (!sym->persist) { 1666 free(sym->nam); 1667 free(sym->val); 1668 TAILQ_REMOVE(&symhead, sym, entry); 1669 free(sym); 1670 } 1671 } 1672 1673 if (TAILQ_EMPTY(conf->services) && TAILQ_EMPTY(conf->relays)) { 1674 log_warnx("no services, nothing to do"); 1675 errors++; 1676 } 1677 1678 if (TAILQ_EMPTY(conf->relays)) 1679 conf->prefork_relay = 0; 1680 1681 if (timercmp(&conf->timeout, &conf->interval, >=)) { 1682 log_warnx("global timeout exceeds interval"); 1683 errors++; 1684 } 1685 1686 /* Verify that every table is used */ 1687 for (table = TAILQ_FIRST(conf->tables); table != NULL; 1688 table = nexttb) { 1689 nexttb = TAILQ_NEXT(table, entry); 1690 if (table->conf.port == 0) { 1691 TAILQ_REMOVE(conf->tables, table, entry); 1692 while ((h = TAILQ_FIRST(&table->hosts)) != NULL) { 1693 TAILQ_REMOVE(&table->hosts, h, entry); 1694 free(h); 1695 } 1696 if (table->sendbuf != NULL) 1697 free(table->sendbuf); 1698 free(table); 1699 continue; 1700 } 1701 if (!(table->conf.flags & F_USED)) { 1702 log_warnx("unused table: %s", table->conf.name); 1703 errors++; 1704 } 1705 if (timercmp(&table->conf.timeout, &conf->interval, >=)) { 1706 log_warnx("table timeout exceeds interval: %s", 1707 table->conf.name); 1708 errors++; 1709 } 1710 } 1711 1712 /* Verify that every non-default protocol is used */ 1713 TAILQ_FOREACH(proto, conf->protos, entry) { 1714 if (!(proto->flags & F_USED)) { 1715 log_warnx("unused protocol: %s", proto->name); 1716 } 1717 } 1718 1719 if (errors) { 1720 free(conf); 1721 return (NULL); 1722 } 1723 1724 return (conf); 1725} 1726 1727int 1728symset(const char *nam, const char *val, int persist) 1729{ 1730 struct sym *sym; 1731 1732 for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); 1733 sym = TAILQ_NEXT(sym, entry)) 1734 ; /* nothing */ 1735 1736 if (sym != NULL) { 1737 if (sym->persist == 1) 1738 return (0); 1739 else { 1740 free(sym->nam); 1741 free(sym->val); 1742 TAILQ_REMOVE(&symhead, sym, entry); 1743 free(sym); 1744 } 1745 } 1746 if ((sym = calloc(1, sizeof(*sym))) == NULL) 1747 return (-1); 1748 1749 sym->nam = strdup(nam); 1750 if (sym->nam == NULL) { 1751 free(sym); 1752 return (-1); 1753 } 1754 sym->val = strdup(val); 1755 if (sym->val == NULL) { 1756 free(sym->nam); 1757 free(sym); 1758 return (-1); 1759 } 1760 sym->used = 0; 1761 sym->persist = persist; 1762 TAILQ_INSERT_TAIL(&symhead, sym, entry); 1763 return (0); 1764} 1765 1766int 1767cmdline_symset(char *s) 1768{ 1769 char *sym, *val; 1770 int ret; 1771 size_t len; 1772 1773 if ((val = strrchr(s, '=')) == NULL) 1774 return (-1); 1775 1776 len = strlen(s) - strlen(val) + 1; 1777 if ((sym = malloc(len)) == NULL) 1778 errx(1, "cmdline_symset: malloc"); 1779 1780 (void)strlcpy(sym, s, len); 1781 1782 ret = symset(sym, val + 1, 1); 1783 free(sym); 1784 1785 return (ret); 1786} 1787 1788char * 1789symget(const char *nam) 1790{ 1791 struct sym *sym; 1792 1793 TAILQ_FOREACH(sym, &symhead, entry) 1794 if (strcmp(nam, sym->nam) == 0) { 1795 sym->used = 1; 1796 return (sym->val); 1797 } 1798 return (NULL); 1799} 1800 1801struct address * 1802host_v4(const char *s) 1803{ 1804 struct in_addr ina; 1805 struct sockaddr_in *sain; 1806 struct address *h; 1807 1808 bzero(&ina, sizeof(ina)); 1809 if (inet_pton(AF_INET, s, &ina) != 1) 1810 return (NULL); 1811 1812 if ((h = calloc(1, sizeof(*h))) == NULL) 1813 fatal(NULL); 1814 sain = (struct sockaddr_in *)&h->ss; 1815 sain->sin_len = sizeof(struct sockaddr_in); 1816 sain->sin_family = AF_INET; 1817 sain->sin_addr.s_addr = ina.s_addr; 1818 1819 return (h); 1820} 1821 1822struct address * 1823host_v6(const char *s) 1824{ 1825 struct in6_addr ina6; 1826 struct sockaddr_in6 *sin6; 1827 struct address *h; 1828 1829 bzero(&ina6, sizeof(ina6)); 1830 if (inet_pton(AF_INET6, s, &ina6) != 1) 1831 return (NULL); 1832 1833 if ((h = calloc(1, sizeof(*h))) == NULL) 1834 fatal(NULL); 1835 sin6 = (struct sockaddr_in6 *)&h->ss; 1836 sin6->sin6_len = sizeof(struct sockaddr_in6); 1837 sin6->sin6_family = AF_INET6; 1838 memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6)); 1839 1840 return (h); 1841} 1842 1843int 1844host_dns(const char *s, struct addresslist *al, int max, 1845 in_port_t port, const char *ifname) 1846{ 1847 struct addrinfo hints, *res0, *res; 1848 int error, cnt = 0; 1849 struct sockaddr_in *sain; 1850 struct sockaddr_in6 *sin6; 1851 struct address *h; 1852 1853 bzero(&hints, sizeof(hints)); 1854 hints.ai_family = PF_UNSPEC; 1855 hints.ai_socktype = SOCK_DGRAM; /* DUMMY */ 1856 error = getaddrinfo(s, NULL, &hints, &res0); 1857 if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME) 1858 return (0); 1859 if (error) { 1860 log_warnx("host_dns: could not parse \"%s\": %s", s, 1861 gai_strerror(error)); 1862 return (-1); 1863 } 1864 1865 for (res = res0; res && cnt < max; res = res->ai_next) { 1866 if (res->ai_family != AF_INET && 1867 res->ai_family != AF_INET6) 1868 continue; 1869 if ((h = calloc(1, sizeof(*h))) == NULL) 1870 fatal(NULL); 1871 1872 h->port = port; 1873 if (ifname != NULL) { 1874 if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >= 1875 sizeof(h->ifname)) 1876 log_warnx("host_dns: interface name truncated"); 1877 return (-1); 1878 } 1879 h->ss.ss_family = res->ai_family; 1880 if (res->ai_family == AF_INET) { 1881 sain = (struct sockaddr_in *)&h->ss; 1882 sain->sin_len = sizeof(struct sockaddr_in); 1883 sain->sin_addr.s_addr = ((struct sockaddr_in *) 1884 res->ai_addr)->sin_addr.s_addr; 1885 } else { 1886 sin6 = (struct sockaddr_in6 *)&h->ss; 1887 sin6->sin6_len = sizeof(struct sockaddr_in6); 1888 memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *) 1889 res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); 1890 } 1891 1892 TAILQ_INSERT_HEAD(al, h, entry); 1893 cnt++; 1894 } 1895 if (cnt == max && res) { 1896 log_warnx("host_dns: %s resolves to more than %d hosts", 1897 s, max); 1898 } 1899 freeaddrinfo(res0); 1900 return (cnt); 1901} 1902 1903int 1904host(const char *s, struct addresslist *al, int max, 1905 in_port_t port, const char *ifname) 1906{ 1907 struct address *h; 1908 1909 h = host_v4(s); 1910 1911 /* IPv6 address? */ 1912 if (h == NULL) 1913 h = host_v6(s); 1914 1915 if (h != NULL) { 1916 h->port = port; 1917 if (ifname != NULL) { 1918 if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >= 1919 sizeof(h->ifname)) { 1920 log_warnx("host: interface name truncated"); 1921 return (-1); 1922 } 1923 } 1924 1925 TAILQ_INSERT_HEAD(al, h, entry); 1926 return (1); 1927 } 1928 1929 return (host_dns(s, al, max, port, ifname)); 1930} 1931 1932struct table * 1933table_inherit(const char *name, in_port_t port) 1934{ 1935 char pname[TABLE_NAME_SIZE + 6]; 1936 struct host *h, *dsth; 1937 struct table *dsttb, *tb; 1938 1939 /* Get the table or table template */ 1940 if ((dsttb = table_findbyname(conf, name)) == NULL) { 1941 yyerror("unknown table or template %s", name); 1942 return (NULL); 1943 } 1944 if (dsttb->conf.port != 0) 1945 return (dsttb); 1946 1947 if (port == 0) { 1948 yyerror("invalid port"); 1949 return (NULL); 1950 } 1951 1952 /* Check if a matching table already exists */ 1953 snprintf(pname, sizeof(pname), "%s:%u", name, ntohs(port)); 1954 if ((tb = table_findbyname(conf, pname)) != NULL) { 1955 if (tb->conf.port == 0) { 1956 yyerror("invalid table"); 1957 return (NULL); 1958 } 1959 return (tb); 1960 } 1961 1962 /* Create a new table */ 1963 if ((tb = calloc(1, sizeof (*tb))) == NULL) 1964 fatal("out of memory"); 1965 bcopy(dsttb, tb, sizeof(*tb)); 1966 if (strlcpy(tb->conf.name, pname, sizeof(tb->conf.name)) 1967 >= sizeof(tb->conf.name)) { 1968 yyerror("table name truncated"); 1969 return (NULL); 1970 } 1971 if (dsttb->sendbuf != NULL && 1972 (tb->sendbuf = strdup(dsttb->sendbuf)) == NULL) 1973 fatal("out of memory"); 1974 tb->conf.port = port; 1975 tb->conf.id = last_table_id++; 1976 if (last_table_id == INT_MAX) { 1977 yyerror("too many tables defined"); 1978 return (NULL); 1979 } 1980 1981 /* Copy the associated hosts */ 1982 bzero(&tb->hosts, sizeof(tb->hosts)); 1983 TAILQ_FOREACH(dsth, &dsttb->hosts, entry) { 1984 if ((h = (struct host *) 1985 calloc(1, sizeof (*h))) == NULL) 1986 fatal("out of memory"); 1987 bcopy(dsth, h, sizeof(*h)); 1988 h->conf.id = last_host_id++; 1989 if (last_host_id == INT_MAX) { 1990 yyerror("too many hosts defined"); 1991 return (NULL); 1992 } 1993 h->conf.tableid = tb->conf.id; 1994 h->tablename = tb->conf.name; 1995 TAILQ_INSERT_HEAD(&tb->hosts, h, entry); 1996 } 1997 1998 conf->tablecount++; 1999 TAILQ_INSERT_HEAD(conf->tables, tb, entry); 2000 2001 return (tb); 2002} 2003