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