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