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