1 /* $OpenBSD: relay.c,v 1.259 2024/01/17 10:01:24 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/queue.h> 21 #include <sys/time.h> 22 #include <sys/socket.h> 23 #include <sys/tree.h> 24 25 #include <netinet/in.h> 26 #include <netinet/tcp.h> 27 #include <arpa/inet.h> 28 29 #include <limits.h> 30 #include <netdb.h> 31 #include <poll.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <string.h> 37 #include <unistd.h> 38 #include <event.h> 39 #include <siphash.h> 40 #include <imsg.h> 41 42 #include <tls.h> 43 44 #include "relayd.h" 45 46 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) 47 48 void relay_statistics(int, short, void *); 49 int relay_dispatch_parent(int, struct privsep_proc *, 50 struct imsg *); 51 int relay_dispatch_pfe(int, struct privsep_proc *, 52 struct imsg *); 53 int relay_dispatch_ca(int, struct privsep_proc *, 54 struct imsg *); 55 int relay_dispatch_hce(int, struct privsep_proc *, 56 struct imsg *); 57 void relay_shutdown(void); 58 59 void relay_protodebug(struct relay *); 60 void relay_ruledebug(struct relay_rule *); 61 void relay_init(struct privsep *, struct privsep_proc *p, void *); 62 void relay_launch(void); 63 int relay_socket(struct sockaddr_storage *, in_port_t, 64 struct protocol *, int, int); 65 int relay_socket_listen(struct sockaddr_storage *, in_port_t, 66 struct protocol *); 67 int relay_socket_connect(struct sockaddr_storage *, in_port_t, 68 struct protocol *, int); 69 70 void relay_accept(int, short, void *); 71 void relay_input(struct rsession *); 72 73 void relay_hash_addr(SIPHASH_CTX *, struct sockaddr_storage *, int); 74 75 int relay_tls_ctx_create(struct relay *); 76 void relay_tls_transaction(struct rsession *, 77 struct ctl_relay_event *); 78 void relay_tls_handshake(int, short, void *); 79 void relay_tls_connected(struct ctl_relay_event *); 80 void relay_tls_readcb(int, short, void *); 81 void relay_tls_writecb(int, short, void *); 82 83 void relay_connect_retry(int, short, void *); 84 void relay_connect_state(struct rsession *, 85 struct ctl_relay_event *, enum relay_state); 86 87 extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t, 88 size_t, void *); 89 90 volatile int relay_sessions; 91 volatile int relay_inflight = 0; 92 objid_t relay_conid; 93 94 static struct relayd *env = NULL; 95 96 static struct privsep_proc procs[] = { 97 { "parent", PROC_PARENT, relay_dispatch_parent }, 98 { "pfe", PROC_PFE, relay_dispatch_pfe }, 99 { "ca", PROC_CA, relay_dispatch_ca }, 100 { "hce", PROC_HCE, relay_dispatch_hce }, 101 }; 102 103 void 104 relay(struct privsep *ps, struct privsep_proc *p) 105 { 106 env = ps->ps_env; 107 proc_run(ps, p, procs, nitems(procs), relay_init, NULL); 108 relay_http(env); 109 } 110 111 void 112 relay_shutdown(void) 113 { 114 config_purge(env, CONFIG_ALL); 115 usleep(200); /* XXX relay needs to shutdown last */ 116 } 117 118 void 119 relay_ruledebug(struct relay_rule *rule) 120 { 121 struct kv *kv = NULL; 122 u_int i; 123 char buf[NI_MAXHOST]; 124 125 fprintf(stderr, "\t\t"); 126 127 switch (rule->rule_action) { 128 case RULE_ACTION_MATCH: 129 fprintf(stderr, "match "); 130 break; 131 case RULE_ACTION_BLOCK: 132 fprintf(stderr, "block "); 133 break; 134 case RULE_ACTION_PASS: 135 fprintf(stderr, "pass "); 136 break; 137 } 138 139 switch (rule->rule_dir) { 140 case RELAY_DIR_ANY: 141 break; 142 case RELAY_DIR_REQUEST: 143 fprintf(stderr, "request "); 144 break; 145 case RELAY_DIR_RESPONSE: 146 fprintf(stderr, "response "); 147 break; 148 default: 149 return; 150 /* NOTREACHED */ 151 break; 152 } 153 154 if (rule->rule_flags & RULE_FLAG_QUICK) 155 fprintf(stderr, "quick "); 156 157 switch (rule->rule_af) { 158 case AF_INET: 159 fprintf(stderr, "inet "); 160 break; 161 case AF_INET6: 162 fprintf(stderr, "inet6 "); 163 break; 164 } 165 166 if (rule->rule_src.addr.ss_family != AF_UNSPEC) 167 fprintf(stderr, "from %s/%d ", 168 print_host(&rule->rule_src.addr, buf, sizeof(buf)), 169 rule->rule_src.addr_mask); 170 171 if (rule->rule_dst.addr.ss_family != AF_UNSPEC) 172 fprintf(stderr, "to %s/%d ", 173 print_host(&rule->rule_dst.addr, buf, sizeof(buf)), 174 rule->rule_dst.addr_mask); 175 176 for (i = 1; i < KEY_TYPE_MAX; i++) { 177 kv = &rule->rule_kv[i]; 178 if (kv->kv_type != i) 179 continue; 180 181 switch (kv->kv_type) { 182 case KEY_TYPE_COOKIE: 183 fprintf(stderr, "cookie "); 184 break; 185 case KEY_TYPE_HEADER: 186 fprintf(stderr, "header "); 187 break; 188 case KEY_TYPE_PATH: 189 fprintf(stderr, "path "); 190 break; 191 case KEY_TYPE_QUERY: 192 fprintf(stderr, "query "); 193 break; 194 case KEY_TYPE_URL: 195 fprintf(stderr, "url "); 196 break; 197 default: 198 continue; 199 } 200 201 switch (kv->kv_option) { 202 case KEY_OPTION_APPEND: 203 fprintf(stderr, "append "); 204 break; 205 case KEY_OPTION_SET: 206 fprintf(stderr, "set "); 207 break; 208 case KEY_OPTION_REMOVE: 209 fprintf(stderr, "remove "); 210 break; 211 case KEY_OPTION_HASH: 212 fprintf(stderr, "hash "); 213 break; 214 case KEY_OPTION_LOG: 215 fprintf(stderr, "log "); 216 break; 217 case KEY_OPTION_STRIP: 218 fprintf(stderr, "strip "); 219 break; 220 case KEY_OPTION_NONE: 221 break; 222 } 223 224 switch (kv->kv_digest) { 225 case DIGEST_SHA1: 226 case DIGEST_MD5: 227 fprintf(stderr, "digest "); 228 break; 229 default: 230 break; 231 } 232 233 int kvv = (kv->kv_option == KEY_OPTION_STRIP || 234 kv->kv_value == NULL); 235 fprintf(stderr, "%s%s%s%s%s%s ", 236 kv->kv_key == NULL ? "" : "\"", 237 kv->kv_key == NULL ? "" : kv->kv_key, 238 kv->kv_key == NULL ? "" : "\"", 239 kvv ? "" : " value \"", 240 kv->kv_value == NULL ? "" : kv->kv_value, 241 kvv ? "" : "\""); 242 } 243 244 if (rule->rule_tablename[0]) 245 fprintf(stderr, "forward to <%s> ", rule->rule_tablename); 246 247 if (rule->rule_tag == -1) 248 fprintf(stderr, "no tag "); 249 else if (rule->rule_tag && rule->rule_tagname[0]) 250 fprintf(stderr, "tag \"%s\" ", 251 rule->rule_tagname); 252 253 if (rule->rule_tagged && rule->rule_taggedname[0]) 254 fprintf(stderr, "tagged \"%s\" ", 255 rule->rule_taggedname); 256 257 if (rule->rule_label == -1) 258 fprintf(stderr, "no label "); 259 else if (rule->rule_label && rule->rule_labelname[0]) 260 fprintf(stderr, "label \"%s\" ", 261 rule->rule_labelname); 262 263 fprintf(stderr, "\n"); 264 } 265 266 void 267 relay_protodebug(struct relay *rlay) 268 { 269 struct protocol *proto = rlay->rl_proto; 270 struct relay_rule *rule = NULL; 271 272 fprintf(stderr, "protocol %d: name %s\n", 273 proto->id, proto->name); 274 fprintf(stderr, "\tflags: %s, relay flags: %s\n", 275 printb_flags(proto->flags, F_BITS), 276 printb_flags(rlay->rl_conf.flags, F_BITS)); 277 if (proto->tcpflags) 278 fprintf(stderr, "\ttcp flags: %s\n", 279 printb_flags(proto->tcpflags, TCPFLAG_BITS)); 280 if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) && proto->tlsflags) 281 fprintf(stderr, "\ttls flags: %s\n", 282 printb_flags(proto->tlsflags, TLSFLAG_BITS)); 283 fprintf(stderr, "\ttls session tickets: %s\n", 284 (proto->tickets == 1) ? "enabled" : "disabled"); 285 fprintf(stderr, "\ttype: "); 286 switch (proto->type) { 287 case RELAY_PROTO_TCP: 288 fprintf(stderr, "tcp\n"); 289 break; 290 case RELAY_PROTO_HTTP: 291 fprintf(stderr, "http\n"); 292 break; 293 case RELAY_PROTO_DNS: 294 fprintf(stderr, "dns\n"); 295 break; 296 } 297 298 rule = TAILQ_FIRST(&proto->rules); 299 while (rule != NULL) { 300 relay_ruledebug(rule); 301 rule = TAILQ_NEXT(rule, rule_entry); 302 } 303 } 304 305 int 306 relay_privinit(struct relay *rlay) 307 { 308 log_debug("%s: adding relay %s", __func__, rlay->rl_conf.name); 309 310 if (log_getverbose() > 1) 311 relay_protodebug(rlay); 312 313 switch (rlay->rl_proto->type) { 314 case RELAY_PROTO_DNS: 315 relay_udp_privinit(rlay); 316 break; 317 case RELAY_PROTO_TCP: 318 break; 319 case RELAY_PROTO_HTTP: 320 break; 321 } 322 323 if (rlay->rl_conf.flags & F_UDP) 324 rlay->rl_s = relay_udp_bind(&rlay->rl_conf.ss, 325 rlay->rl_conf.port, rlay->rl_proto); 326 else 327 rlay->rl_s = relay_socket_listen(&rlay->rl_conf.ss, 328 rlay->rl_conf.port, rlay->rl_proto); 329 if (rlay->rl_s == -1) 330 return (-1); 331 332 return (0); 333 } 334 335 void 336 relay_init(struct privsep *ps, struct privsep_proc *p, void *arg) 337 { 338 struct timeval tv; 339 340 if (config_init(ps->ps_env) == -1) 341 fatal("failed to initialize configuration"); 342 343 /* We use a custom shutdown callback */ 344 p->p_shutdown = relay_shutdown; 345 346 /* Unlimited file descriptors (use system limits) */ 347 socket_rlimit(-1); 348 349 if (pledge("stdio recvfd inet", NULL) == -1) 350 fatal("pledge"); 351 352 /* Schedule statistics timer */ 353 evtimer_set(&env->sc_statev, relay_statistics, ps); 354 bcopy(&env->sc_conf.statinterval, &tv, sizeof(tv)); 355 evtimer_add(&env->sc_statev, &tv); 356 } 357 358 void 359 relay_session_publish(struct rsession *s) 360 { 361 proc_compose(env->sc_ps, PROC_PFE, IMSG_SESS_PUBLISH, s, sizeof(*s)); 362 } 363 364 void 365 relay_session_unpublish(struct rsession *s) 366 { 367 proc_compose(env->sc_ps, PROC_PFE, IMSG_SESS_UNPUBLISH, 368 &s->se_id, sizeof(s->se_id)); 369 } 370 371 void 372 relay_statistics(int fd, short events, void *arg) 373 { 374 struct privsep *ps = arg; 375 struct relay *rlay; 376 struct ctl_stats crs, *cur; 377 struct timeval tv, tv_now; 378 int resethour = 0, resetday = 0; 379 struct rsession *con, *next_con; 380 381 /* 382 * This is a hack to calculate some average statistics. 383 * It doesn't try to be very accurate, but could be improved... 384 */ 385 386 timerclear(&tv); 387 getmonotime(&tv_now); 388 389 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) { 390 bzero(&crs, sizeof(crs)); 391 resethour = resetday = 0; 392 393 cur = &rlay->rl_stats[ps->ps_instance]; 394 cur->cnt += cur->last; 395 cur->tick++; 396 cur->avg = (cur->last + cur->avg) / 2; 397 cur->last_hour += cur->last; 398 if ((cur->tick % 399 (3600 / env->sc_conf.statinterval.tv_sec)) == 0) { 400 cur->avg_hour = (cur->last_hour + cur->avg_hour) / 2; 401 resethour++; 402 } 403 cur->last_day += cur->last; 404 if ((cur->tick % 405 (86400 / env->sc_conf.statinterval.tv_sec)) == 0) { 406 cur->avg_day = (cur->last_day + cur->avg_day) / 2; 407 resethour++; 408 } 409 bcopy(cur, &crs, sizeof(crs)); 410 411 cur->last = 0; 412 if (resethour) 413 cur->last_hour = 0; 414 if (resetday) 415 cur->last_day = 0; 416 417 crs.id = rlay->rl_conf.id; 418 crs.proc = ps->ps_instance; 419 proc_compose(env->sc_ps, PROC_PFE, IMSG_STATISTICS, 420 &crs, sizeof(crs)); 421 422 for (con = SPLAY_ROOT(&rlay->rl_sessions); 423 con != NULL; con = next_con) { 424 next_con = SPLAY_NEXT(session_tree, 425 &rlay->rl_sessions, con); 426 timersub(&tv_now, &con->se_tv_last, &tv); 427 if (timercmp(&tv, &rlay->rl_conf.timeout, >=)) 428 relay_close(con, "hard timeout", 1); 429 } 430 } 431 432 /* Schedule statistics timer */ 433 evtimer_set(&env->sc_statev, relay_statistics, ps); 434 bcopy(&env->sc_conf.statinterval, &tv, sizeof(tv)); 435 evtimer_add(&env->sc_statev, &tv); 436 } 437 438 void 439 relay_launch(void) 440 { 441 void (*callback)(int, short, void *); 442 struct relay *rlay; 443 struct host *host; 444 struct relay_table *rlt; 445 446 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) { 447 if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) && 448 relay_tls_ctx_create(rlay) == -1) 449 fatalx("%s: failed to create TLS context", __func__); 450 451 TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) { 452 /* 453 * set rule->rule_table in advance and save time 454 * looking up for this later on rule/connection 455 * evalution 456 */ 457 rule_settable(&rlay->rl_proto->rules, rlt); 458 459 rlt->rlt_index = 0; 460 rlt->rlt_nhosts = 0; 461 TAILQ_FOREACH(host, &rlt->rlt_table->hosts, entry) { 462 if (rlt->rlt_nhosts >= RELAY_MAXHOSTS) 463 fatal("%s: too many hosts in table", 464 __func__); 465 host->idx = rlt->rlt_nhosts; 466 rlt->rlt_host[rlt->rlt_nhosts++] = host; 467 } 468 log_info("adding %d hosts from table %s%s", 469 rlt->rlt_nhosts, rlt->rlt_table->conf.name, 470 rlt->rlt_table->conf.check ? "" : " (no check)"); 471 } 472 473 switch (rlay->rl_proto->type) { 474 case RELAY_PROTO_DNS: 475 relay_udp_init(env, rlay); 476 break; 477 case RELAY_PROTO_TCP: 478 case RELAY_PROTO_HTTP: 479 relay_http_init(rlay); 480 /* Use defaults */ 481 break; 482 } 483 484 log_debug("%s: running relay %s", __func__, 485 rlay->rl_conf.name); 486 487 rlay->rl_up = HOST_UP; 488 489 if (rlay->rl_conf.flags & F_UDP) 490 callback = relay_udp_server; 491 else 492 callback = relay_accept; 493 494 event_set(&rlay->rl_ev, rlay->rl_s, EV_READ, 495 callback, rlay); 496 event_add(&rlay->rl_ev, NULL); 497 evtimer_set(&rlay->rl_evt, callback, rlay); 498 } 499 } 500 501 int 502 relay_socket_af(struct sockaddr_storage *ss, in_port_t port) 503 { 504 switch (ss->ss_family) { 505 case AF_INET: 506 ((struct sockaddr_in *)ss)->sin_port = port; 507 ((struct sockaddr_in *)ss)->sin_len = 508 sizeof(struct sockaddr_in); 509 break; 510 case AF_INET6: 511 ((struct sockaddr_in6 *)ss)->sin6_port = port; 512 ((struct sockaddr_in6 *)ss)->sin6_len = 513 sizeof(struct sockaddr_in6); 514 break; 515 default: 516 return (-1); 517 } 518 519 return (0); 520 } 521 522 in_port_t 523 relay_socket_getport(struct sockaddr_storage *ss) 524 { 525 switch (ss->ss_family) { 526 case AF_INET: 527 return (((struct sockaddr_in *)ss)->sin_port); 528 case AF_INET6: 529 return (((struct sockaddr_in6 *)ss)->sin6_port); 530 default: 531 return (0); 532 } 533 534 /* NOTREACHED */ 535 return (0); 536 } 537 538 int 539 relay_socket(struct sockaddr_storage *ss, in_port_t port, 540 struct protocol *proto, int fd, int reuseport) 541 { 542 struct linger lng; 543 int s = -1, val; 544 545 if (relay_socket_af(ss, port) == -1) 546 goto bad; 547 548 s = fd == -1 ? socket(ss->ss_family, 549 SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP) : fd; 550 if (s == -1) 551 goto bad; 552 553 /* 554 * Socket options 555 */ 556 bzero(&lng, sizeof(lng)); 557 if (setsockopt(s, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)) == -1) 558 goto bad; 559 if (reuseport) { 560 val = 1; 561 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val, 562 sizeof(int)) == -1) 563 goto bad; 564 } 565 if (proto->tcpflags & TCPFLAG_BUFSIZ) { 566 val = proto->tcpbufsiz; 567 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 568 &val, sizeof(val)) == -1) 569 goto bad; 570 val = proto->tcpbufsiz; 571 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 572 &val, sizeof(val)) == -1) 573 goto bad; 574 } 575 576 /* 577 * IP options 578 */ 579 if (proto->tcpflags & TCPFLAG_IPTTL) { 580 val = (int)proto->tcpipttl; 581 switch (ss->ss_family) { 582 case AF_INET: 583 if (setsockopt(s, IPPROTO_IP, IP_TTL, 584 &val, sizeof(val)) == -1) 585 goto bad; 586 break; 587 case AF_INET6: 588 if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 589 &val, sizeof(val)) == -1) 590 goto bad; 591 break; 592 } 593 } 594 if (proto->tcpflags & TCPFLAG_IPMINTTL) { 595 val = (int)proto->tcpipminttl; 596 switch (ss->ss_family) { 597 case AF_INET: 598 if (setsockopt(s, IPPROTO_IP, IP_MINTTL, 599 &val, sizeof(val)) == -1) 600 goto bad; 601 break; 602 case AF_INET6: 603 if (setsockopt(s, IPPROTO_IPV6, IPV6_MINHOPCOUNT, 604 &val, sizeof(val)) == -1) 605 goto bad; 606 break; 607 } 608 } 609 610 /* 611 * TCP options 612 */ 613 if (proto->tcpflags & (TCPFLAG_NODELAY|TCPFLAG_NNODELAY)) { 614 if (proto->tcpflags & TCPFLAG_NNODELAY) 615 val = 0; 616 else 617 val = 1; 618 if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, 619 &val, sizeof(val)) == -1) 620 goto bad; 621 } 622 if (proto->tcpflags & (TCPFLAG_SACK|TCPFLAG_NSACK)) { 623 if (proto->tcpflags & TCPFLAG_NSACK) 624 val = 0; 625 else 626 val = 1; 627 if (setsockopt(s, IPPROTO_TCP, TCP_SACK_ENABLE, 628 &val, sizeof(val)) == -1) 629 goto bad; 630 } 631 632 return (s); 633 634 bad: 635 if (s != -1) 636 close(s); 637 return (-1); 638 } 639 640 int 641 relay_socket_connect(struct sockaddr_storage *ss, in_port_t port, 642 struct protocol *proto, int fd) 643 { 644 int s; 645 646 if ((s = relay_socket(ss, port, proto, fd, 0)) == -1) 647 return (-1); 648 649 if (connect(s, (struct sockaddr *)ss, ss->ss_len) == -1) { 650 if (errno != EINPROGRESS) 651 goto bad; 652 } 653 654 return (s); 655 656 bad: 657 close(s); 658 return (-1); 659 } 660 661 int 662 relay_socket_listen(struct sockaddr_storage *ss, in_port_t port, 663 struct protocol *proto) 664 { 665 int s; 666 667 if ((s = relay_socket(ss, port, proto, -1, 1)) == -1) 668 return (-1); 669 670 if (bind(s, (struct sockaddr *)ss, ss->ss_len) == -1) 671 goto bad; 672 if (listen(s, proto->tcpbacklog) == -1) 673 goto bad; 674 675 return (s); 676 677 bad: 678 close(s); 679 return (-1); 680 } 681 682 void 683 relay_connected(int fd, short sig, void *arg) 684 { 685 char obuf[128]; 686 struct rsession *con = arg; 687 struct relay *rlay = con->se_relay; 688 struct protocol *proto = rlay->rl_proto; 689 evbuffercb outrd = relay_read; 690 evbuffercb outwr = relay_write; 691 struct bufferevent *bev; 692 struct ctl_relay_event *out = &con->se_out; 693 char *msg; 694 socklen_t len; 695 int error; 696 697 if (sig == EV_TIMEOUT) { 698 relay_abort_http(con, 504, "connect timeout", 0); 699 return; 700 } 701 702 len = sizeof(error); 703 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) == -1) { 704 relay_abort_http(con, 500, "getsockopt failed", 0); 705 return; 706 } 707 if (error) { 708 errno = error; 709 if (asprintf(&msg, "socket error: %s", 710 strerror(error)) >= 0) { 711 relay_abort_http(con, 500, msg, 0); 712 free(msg); 713 return; 714 } else { 715 relay_abort_http(con, 500, 716 "socket error and asprintf failed", 0); 717 return; 718 } 719 } 720 721 if ((rlay->rl_conf.flags & F_TLSCLIENT) && (out->tls == NULL)) { 722 relay_tls_transaction(con, out); 723 return; 724 } 725 726 DPRINTF("%s: session %d: successful", __func__, con->se_id); 727 728 /* Log destination if it was changed in a keep-alive connection */ 729 if ((con->se_table != con->se_table0) && 730 (env->sc_conf.opts & (RELAYD_OPT_LOGCON|RELAYD_OPT_LOGCONERR))) { 731 con->se_table0 = con->se_table; 732 memset(&obuf, 0, sizeof(obuf)); 733 (void)print_host(&con->se_out.ss, obuf, sizeof(obuf)); 734 if (asprintf(&msg, " -> %s:%d", 735 obuf, ntohs(con->se_out.port)) == -1) { 736 relay_abort_http(con, 500, 737 "connection changed and asprintf failed", 0); 738 return; 739 } 740 relay_log(con, msg); 741 free(msg); 742 } 743 744 switch (rlay->rl_proto->type) { 745 case RELAY_PROTO_HTTP: 746 if (relay_httpdesc_init(out) == -1) { 747 relay_close(con, 748 "failed to allocate http descriptor", 1); 749 return; 750 } 751 con->se_out.toread = TOREAD_HTTP_HEADER; 752 outrd = relay_read_http; 753 break; 754 case RELAY_PROTO_TCP: 755 /* Use defaults */ 756 break; 757 default: 758 fatalx("%s: unknown protocol", __func__); 759 } 760 761 /* 762 * Relay <-> Server 763 */ 764 bev = bufferevent_new(fd, outrd, outwr, relay_error, &con->se_out); 765 if (bev == NULL) { 766 relay_abort_http(con, 500, 767 "failed to allocate output buffer event", 0); 768 return; 769 } 770 /* write pending output buffer now */ 771 if (bufferevent_write_buffer(bev, con->se_out.output)) { 772 relay_abort_http(con, 500, strerror(errno), 0); 773 return; 774 } 775 con->se_out.bev = bev; 776 777 /* Initialize the TLS wrapper */ 778 if ((rlay->rl_conf.flags & F_TLSCLIENT) && (out->tls != NULL)) 779 relay_tls_connected(out); 780 781 bufferevent_settimeout(bev, 782 rlay->rl_conf.timeout.tv_sec, rlay->rl_conf.timeout.tv_sec); 783 bufferevent_setwatermark(bev, EV_WRITE, 784 RELAY_MIN_PREFETCHED * proto->tcpbufsiz, 0); 785 bufferevent_enable(bev, EV_READ|EV_WRITE); 786 if (con->se_in.bev) 787 bufferevent_enable(con->se_in.bev, EV_READ); 788 789 if (relay_splice(&con->se_out) == -1) 790 relay_close(con, strerror(errno), 1); 791 } 792 793 void 794 relay_input(struct rsession *con) 795 { 796 struct relay *rlay = con->se_relay; 797 struct protocol *proto = rlay->rl_proto; 798 evbuffercb inrd = relay_read; 799 evbuffercb inwr = relay_write; 800 801 switch (rlay->rl_proto->type) { 802 case RELAY_PROTO_HTTP: 803 if (relay_http_priv_init(con) == -1) { 804 relay_close(con, 805 "failed to allocate http descriptor", 1); 806 return; 807 } 808 con->se_in.toread = TOREAD_HTTP_HEADER; 809 inrd = relay_read_http; 810 break; 811 case RELAY_PROTO_TCP: 812 /* Use defaults */ 813 break; 814 default: 815 fatalx("%s: unknown protocol", __func__); 816 } 817 818 /* 819 * Client <-> Relay 820 */ 821 con->se_in.bev = bufferevent_new(con->se_in.s, inrd, inwr, 822 relay_error, &con->se_in); 823 if (con->se_in.bev == NULL) { 824 relay_close(con, "failed to allocate input buffer event", 1); 825 return; 826 } 827 828 /* Initialize the TLS wrapper */ 829 if ((rlay->rl_conf.flags & F_TLS) && con->se_in.tls != NULL) 830 relay_tls_connected(&con->se_in); 831 832 bufferevent_settimeout(con->se_in.bev, 833 rlay->rl_conf.timeout.tv_sec, rlay->rl_conf.timeout.tv_sec); 834 bufferevent_setwatermark(con->se_in.bev, EV_WRITE, 835 RELAY_MIN_PREFETCHED * proto->tcpbufsiz, 0); 836 bufferevent_enable(con->se_in.bev, EV_READ|EV_WRITE); 837 838 if (relay_splice(&con->se_in) == -1) 839 relay_close(con, strerror(errno), 1); 840 } 841 842 void 843 relay_write(struct bufferevent *bev, void *arg) 844 { 845 struct ctl_relay_event *cre = arg; 846 struct rsession *con = cre->con; 847 848 getmonotime(&con->se_tv_last); 849 850 if (con->se_done && EVBUFFER_LENGTH(EVBUFFER_OUTPUT(bev)) == 0) 851 goto done; 852 if (cre->dst->bev) 853 bufferevent_enable(cre->dst->bev, EV_READ); 854 if (relay_splice(cre->dst) == -1) 855 goto fail; 856 857 return; 858 done: 859 relay_close(con, "last write (done)", 0); 860 return; 861 fail: 862 relay_close(con, strerror(errno), 1); 863 } 864 865 void 866 relay_dump(struct ctl_relay_event *cre, const void *buf, size_t len) 867 { 868 if (!len) 869 return; 870 871 /* 872 * This function will dump the specified message directly 873 * to the underlying session, without waiting for success 874 * of non-blocking events etc. This is useful to print an 875 * error message before gracefully closing the session. 876 */ 877 if (cre->tls != NULL) 878 (void)tls_write(cre->tls, buf, len); 879 else 880 (void)write(cre->s, buf, len); 881 } 882 883 void 884 relay_read(struct bufferevent *bev, void *arg) 885 { 886 struct ctl_relay_event *cre = arg; 887 struct rsession *con = cre->con; 888 struct protocol *proto = con->se_relay->rl_proto; 889 struct evbuffer *src = EVBUFFER_INPUT(bev); 890 891 getmonotime(&con->se_tv_last); 892 cre->timedout = 0; 893 894 if (!EVBUFFER_LENGTH(src)) 895 return; 896 if (relay_bufferevent_write_buffer(cre->dst, src) == -1) 897 goto fail; 898 if (con->se_done) 899 goto done; 900 if (cre->dst->bev) 901 bufferevent_enable(cre->dst->bev, EV_READ); 902 if (cre->dst->bev && EVBUFFER_LENGTH(EVBUFFER_OUTPUT(cre->dst->bev)) > 903 (size_t)RELAY_MAX_PREFETCH * proto->tcpbufsiz) 904 bufferevent_disable(bev, EV_READ); 905 906 return; 907 done: 908 relay_close(con, "last read (done)", 0); 909 return; 910 fail: 911 relay_close(con, strerror(errno), 1); 912 } 913 914 /* 915 * Splice sockets from cre to cre->dst if applicable. Returns: 916 * -1 socket splicing has failed 917 * 0 socket splicing is currently not possible 918 * 1 socket splicing was successful 919 */ 920 int 921 relay_splice(struct ctl_relay_event *cre) 922 { 923 struct rsession *con = cre->con; 924 struct relay *rlay = con->se_relay; 925 struct protocol *proto = rlay->rl_proto; 926 struct splice sp; 927 928 if ((rlay->rl_conf.flags & (F_TLS|F_TLSCLIENT)) || 929 (proto->tcpflags & TCPFLAG_NSPLICE)) 930 return (0); 931 932 if (cre->splicelen >= 0) 933 return (0); 934 935 /* still not connected */ 936 if (cre->bev == NULL || cre->dst->bev == NULL) 937 return (0); 938 939 if (!(cre->toread == TOREAD_UNLIMITED || cre->toread > 0)) { 940 DPRINTF("%s: session %d: splice dir %d, nothing to read %lld", 941 __func__, con->se_id, cre->dir, cre->toread); 942 return (0); 943 } 944 945 /* do not splice before buffers have not been completely flushed */ 946 if (EVBUFFER_LENGTH(cre->bev->input) || 947 EVBUFFER_LENGTH(cre->dst->bev->output)) { 948 DPRINTF("%s: session %d: splice dir %d, dirty buffer", 949 __func__, con->se_id, cre->dir); 950 bufferevent_disable(cre->bev, EV_READ); 951 return (0); 952 } 953 954 bzero(&sp, sizeof(sp)); 955 sp.sp_fd = cre->dst->s; 956 sp.sp_max = cre->toread > 0 ? cre->toread : 0; 957 bcopy(&rlay->rl_conf.timeout, &sp.sp_idle, sizeof(sp.sp_idle)); 958 if (setsockopt(cre->s, SOL_SOCKET, SO_SPLICE, &sp, sizeof(sp)) == -1) { 959 log_debug("%s: session %d: splice dir %d failed: %s", 960 __func__, con->se_id, cre->dir, strerror(errno)); 961 return (-1); 962 } 963 cre->splicelen = 0; 964 bufferevent_enable(cre->bev, EV_READ); 965 966 DPRINTF("%s: session %d: splice dir %d, maximum %lld, successful", 967 __func__, con->se_id, cre->dir, cre->toread); 968 969 return (1); 970 } 971 972 int 973 relay_splicelen(struct ctl_relay_event *cre) 974 { 975 struct rsession *con = cre->con; 976 off_t len; 977 socklen_t optlen; 978 979 if (cre->splicelen < 0) 980 return (0); 981 982 optlen = sizeof(len); 983 if (getsockopt(cre->s, SOL_SOCKET, SO_SPLICE, &len, &optlen) == -1) { 984 log_debug("%s: session %d: splice dir %d get length failed: %s", 985 __func__, con->se_id, cre->dir, strerror(errno)); 986 return (-1); 987 } 988 989 DPRINTF("%s: session %d: splice dir %d, length %lld", 990 __func__, con->se_id, cre->dir, len); 991 992 if (len > cre->splicelen) { 993 getmonotime(&con->se_tv_last); 994 995 cre->splicelen = len; 996 return (1); 997 } 998 999 return (0); 1000 } 1001 1002 int 1003 relay_spliceadjust(struct ctl_relay_event *cre) 1004 { 1005 if (cre->splicelen < 0) 1006 return (0); 1007 if (relay_splicelen(cre) == -1) 1008 return (-1); 1009 if (cre->splicelen > 0 && cre->toread > 0) 1010 cre->toread -= cre->splicelen; 1011 cre->splicelen = -1; 1012 1013 return (0); 1014 } 1015 1016 void 1017 relay_error(struct bufferevent *bev, short error, void *arg) 1018 { 1019 struct ctl_relay_event *cre = arg; 1020 struct rsession *con = cre->con; 1021 struct evbuffer *dst; 1022 1023 DPRINTF("%s: session %d: dir %d state %d to read %lld event error %x", 1024 __func__, con->se_id, cre->dir, cre->state, cre->toread, error); 1025 if (error & EVBUFFER_TIMEOUT) { 1026 if (cre->splicelen >= 0) { 1027 bufferevent_enable(bev, EV_READ); 1028 } else if (cre->dst->splicelen >= 0) { 1029 switch (relay_splicelen(cre->dst)) { 1030 case -1: 1031 goto fail; 1032 case 0: 1033 relay_close(con, "buffer event timeout", 1); 1034 break; 1035 case 1: 1036 cre->timedout = 1; 1037 bufferevent_enable(bev, EV_READ); 1038 break; 1039 } 1040 } else { 1041 relay_close(con, "buffer event timeout", 1); 1042 } 1043 return; 1044 } 1045 if (error & EVBUFFER_ERROR && errno == ETIMEDOUT) { 1046 if (cre->dst->splicelen >= 0) { 1047 switch (relay_splicelen(cre->dst)) { 1048 case -1: 1049 goto fail; 1050 case 0: 1051 relay_close(con, "splice timeout", 1); 1052 return; 1053 case 1: 1054 bufferevent_enable(bev, EV_READ); 1055 break; 1056 } 1057 } else if (cre->dst->timedout) { 1058 relay_close(con, "splice timeout", 1); 1059 return; 1060 } 1061 if (relay_spliceadjust(cre) == -1) 1062 goto fail; 1063 if (relay_splice(cre) == -1) 1064 goto fail; 1065 return; 1066 } 1067 if (error & EVBUFFER_ERROR && errno == EFBIG) { 1068 if (relay_spliceadjust(cre) == -1) 1069 goto fail; 1070 bufferevent_enable(cre->bev, EV_READ); 1071 return; 1072 } 1073 if (error & (EVBUFFER_READ|EVBUFFER_WRITE|EVBUFFER_EOF)) { 1074 bufferevent_disable(bev, EV_READ|EV_WRITE); 1075 1076 con->se_done = 1; 1077 if (cre->dst->bev != NULL) { 1078 dst = EVBUFFER_OUTPUT(cre->dst->bev); 1079 if (EVBUFFER_LENGTH(dst)) 1080 return; 1081 } else if (cre->toread == TOREAD_UNLIMITED || cre->toread == 0) 1082 return; 1083 1084 relay_close(con, "done", 0); 1085 return; 1086 } 1087 relay_close(con, "buffer event error", 1); 1088 return; 1089 fail: 1090 relay_close(con, strerror(errno), 1); 1091 } 1092 1093 void 1094 relay_accept(int fd, short event, void *arg) 1095 { 1096 struct privsep *ps = env->sc_ps; 1097 struct relay *rlay = arg; 1098 struct rsession *con = NULL; 1099 struct ctl_natlook *cnl = NULL; 1100 socklen_t slen; 1101 struct timeval tv; 1102 struct sockaddr_storage ss; 1103 int s = -1; 1104 1105 event_add(&rlay->rl_ev, NULL); 1106 if ((event & EV_TIMEOUT)) 1107 return; 1108 1109 slen = sizeof(ss); 1110 if ((s = accept_reserve(fd, (struct sockaddr *)&ss, 1111 &slen, FD_RESERVE, &relay_inflight)) == -1) { 1112 /* 1113 * Pause accept if we are out of file descriptors, or 1114 * libevent will haunt us here too. 1115 */ 1116 if (errno == ENFILE || errno == EMFILE) { 1117 struct timeval evtpause = { 1, 0 }; 1118 1119 event_del(&rlay->rl_ev); 1120 evtimer_add(&rlay->rl_evt, &evtpause); 1121 log_debug("%s: deferring connections", __func__); 1122 } 1123 return; 1124 } 1125 if (rlay->rl_conf.flags & F_DISABLE) 1126 goto err; 1127 1128 if ((con = calloc(1, sizeof(*con))) == NULL) 1129 goto err; 1130 1131 /* Pre-allocate log buffer */ 1132 con->se_haslog = 0; 1133 con->se_log = evbuffer_new(); 1134 if (con->se_log == NULL) 1135 goto err; 1136 1137 con->se_in.s = s; 1138 con->se_in.tls = NULL; 1139 con->se_out.s = -1; 1140 con->se_out.tls = NULL; 1141 con->se_in.dst = &con->se_out; 1142 con->se_out.dst = &con->se_in; 1143 con->se_in.con = con; 1144 con->se_out.con = con; 1145 con->se_in.splicelen = -1; 1146 con->se_out.splicelen = -1; 1147 con->se_in.toread = TOREAD_UNLIMITED; 1148 con->se_out.toread = TOREAD_UNLIMITED; 1149 con->se_relay = rlay; 1150 con->se_id = ++relay_conid; 1151 con->se_relayid = rlay->rl_conf.id; 1152 con->se_pid = getpid(); 1153 con->se_in.dir = RELAY_DIR_REQUEST; 1154 con->se_out.dir = RELAY_DIR_RESPONSE; 1155 con->se_retry = rlay->rl_conf.dstretry; 1156 con->se_bnds = -1; 1157 con->se_out.port = rlay->rl_conf.dstport; 1158 switch (ss.ss_family) { 1159 case AF_INET: 1160 con->se_in.port = ((struct sockaddr_in *)&ss)->sin_port; 1161 break; 1162 case AF_INET6: 1163 con->se_in.port = ((struct sockaddr_in6 *)&ss)->sin6_port; 1164 break; 1165 } 1166 memcpy(&con->se_in.ss, &ss, sizeof(con->se_in.ss)); 1167 1168 slen = sizeof(con->se_sockname); 1169 if (getsockname(s, (struct sockaddr *)&con->se_sockname, &slen) == -1) { 1170 relay_close(con, "sockname lookup failed", 1); 1171 return; 1172 } 1173 1174 getmonotime(&con->se_tv_start); 1175 bcopy(&con->se_tv_start, &con->se_tv_last, sizeof(con->se_tv_last)); 1176 1177 if (rlay->rl_conf.flags & F_HASHKEY) { 1178 SipHash24_Init(&con->se_siphashctx, 1179 &rlay->rl_conf.hashkey.siphashkey); 1180 } 1181 1182 relay_sessions++; 1183 SPLAY_INSERT(session_tree, &rlay->rl_sessions, con); 1184 relay_session_publish(con); 1185 1186 /* Increment the per-relay session counter */ 1187 rlay->rl_stats[ps->ps_instance].last++; 1188 1189 /* Pre-allocate output buffer */ 1190 con->se_out.output = evbuffer_new(); 1191 if (con->se_out.output == NULL) { 1192 relay_close(con, "failed to allocate output buffer", 1); 1193 return; 1194 } 1195 1196 if (rlay->rl_conf.flags & F_DIVERT) { 1197 memcpy(&con->se_out.ss, &con->se_sockname, 1198 sizeof(con->se_out.ss)); 1199 con->se_out.port = relay_socket_getport(&con->se_out.ss); 1200 1201 /* Detect loop and fall back to the alternate forward target */ 1202 if (bcmp(&rlay->rl_conf.ss, &con->se_out.ss, 1203 sizeof(con->se_out.ss)) == 0 && 1204 con->se_out.port == rlay->rl_conf.port) 1205 con->se_out.ss.ss_family = AF_UNSPEC; 1206 } else if (rlay->rl_conf.flags & F_NATLOOK) { 1207 if ((cnl = calloc(1, sizeof(*cnl))) == NULL) { 1208 relay_close(con, "failed to allocate nat lookup", 1); 1209 return; 1210 } 1211 1212 con->se_cnl = cnl; 1213 bzero(cnl, sizeof(*cnl)); 1214 cnl->in = -1; 1215 cnl->id = con->se_id; 1216 cnl->proc = ps->ps_instance; 1217 cnl->proto = IPPROTO_TCP; 1218 1219 memcpy(&cnl->src, &con->se_in.ss, sizeof(cnl->src)); 1220 memcpy(&cnl->dst, &con->se_sockname, sizeof(cnl->dst)); 1221 1222 proc_compose(env->sc_ps, PROC_PFE, IMSG_NATLOOK, 1223 cnl, sizeof(*cnl)); 1224 1225 /* Schedule timeout */ 1226 evtimer_set(&con->se_ev, relay_natlook, con); 1227 bcopy(&rlay->rl_conf.timeout, &tv, sizeof(tv)); 1228 evtimer_add(&con->se_ev, &tv); 1229 return; 1230 } 1231 1232 if (rlay->rl_conf.flags & F_TLSINSPECT) { 1233 relay_preconnect(con); 1234 return; 1235 } 1236 1237 relay_session(con); 1238 return; 1239 err: 1240 if (s != -1) { 1241 close(s); 1242 free(con); 1243 /* 1244 * the session struct was not completely set up, but still 1245 * counted as an inflight session. account for this. 1246 */ 1247 relay_inflight--; 1248 log_debug("%s: inflight decremented, now %d", 1249 __func__, relay_inflight); 1250 } 1251 } 1252 1253 void 1254 relay_hash_addr(SIPHASH_CTX *ctx, struct sockaddr_storage *ss, int portset) 1255 { 1256 struct sockaddr_in *sin4; 1257 struct sockaddr_in6 *sin6; 1258 in_port_t port; 1259 1260 if (ss->ss_family == AF_INET) { 1261 sin4 = (struct sockaddr_in *)ss; 1262 SipHash24_Update(ctx, &sin4->sin_addr, 1263 sizeof(struct in_addr)); 1264 } else { 1265 sin6 = (struct sockaddr_in6 *)ss; 1266 SipHash24_Update(ctx, &sin6->sin6_addr, 1267 sizeof(struct in6_addr)); 1268 } 1269 1270 if (portset != -1) { 1271 port = (in_port_t)portset; 1272 SipHash24_Update(ctx, &port, sizeof(port)); 1273 } 1274 } 1275 1276 int 1277 relay_from_table(struct rsession *con) 1278 { 1279 struct relay *rlay = con->se_relay; 1280 struct host *host = NULL; 1281 struct relay_table *rlt = NULL; 1282 struct table *table = NULL; 1283 int idx = -1; 1284 int cnt = 0; 1285 int maxtries; 1286 u_int64_t p = 0; 1287 1288 /* the table is already selected */ 1289 if (con->se_table != NULL) { 1290 rlt = con->se_table; 1291 table = rlt->rlt_table; 1292 if (table->conf.check && !table->up) 1293 table = NULL; 1294 goto gottable; 1295 } 1296 1297 /* otherwise grep the first active table */ 1298 TAILQ_FOREACH(rlt, &rlay->rl_tables, rlt_entry) { 1299 table = rlt->rlt_table; 1300 if ((rlt->rlt_flags & F_USED) == 0 || 1301 (table->conf.check && !table->up)) 1302 table = NULL; 1303 else 1304 break; 1305 } 1306 1307 gottable: 1308 if (table == NULL) { 1309 log_debug("%s: session %d: no active hosts", 1310 __func__, con->se_id); 1311 return (-1); 1312 } 1313 1314 switch (rlt->rlt_mode) { 1315 case RELAY_DSTMODE_ROUNDROBIN: 1316 if ((int)rlt->rlt_index >= rlt->rlt_nhosts) 1317 rlt->rlt_index = 0; 1318 idx = (int)rlt->rlt_index; 1319 break; 1320 case RELAY_DSTMODE_RANDOM: 1321 idx = (int)arc4random_uniform(rlt->rlt_nhosts); 1322 break; 1323 case RELAY_DSTMODE_SRCHASH: 1324 /* Source IP address without port */ 1325 relay_hash_addr(&con->se_siphashctx, &con->se_in.ss, -1); 1326 break; 1327 case RELAY_DSTMODE_LOADBALANCE: 1328 /* Source IP address without port */ 1329 relay_hash_addr(&con->se_siphashctx, &con->se_in.ss, -1); 1330 /* FALLTHROUGH */ 1331 case RELAY_DSTMODE_HASH: 1332 /* Local "destination" IP address and port */ 1333 relay_hash_addr(&con->se_siphashctx, &rlay->rl_conf.ss, 1334 rlay->rl_conf.port); 1335 break; 1336 default: 1337 fatalx("%s: unsupported mode", __func__); 1338 /* NOTREACHED */ 1339 } 1340 if (idx == -1) { 1341 /* handle all hashing algorithms */ 1342 p = SipHash24_End(&con->se_siphashctx); 1343 1344 /* Reset hash context */ 1345 SipHash24_Init(&con->se_siphashctx, 1346 &rlay->rl_conf.hashkey.siphashkey); 1347 1348 maxtries = (rlt->rlt_nhosts < RELAY_MAX_HASH_RETRIES ? 1349 rlt->rlt_nhosts : RELAY_MAX_HASH_RETRIES); 1350 for (cnt = 0; cnt < maxtries; cnt++) { 1351 if ((idx = p % rlt->rlt_nhosts) >= RELAY_MAXHOSTS) 1352 return (-1); 1353 1354 host = rlt->rlt_host[idx]; 1355 1356 DPRINTF("%s: session %d: table %s host %s, " 1357 "p 0x%016llx, idx %d, cnt %d, max %d", 1358 __func__, con->se_id, table->conf.name, 1359 host->conf.name, p, idx, cnt, maxtries); 1360 1361 if (!table->conf.check || host->up == HOST_UP) 1362 goto found; 1363 p = p >> 1; 1364 } 1365 } else { 1366 /* handle all non-hashing algorithms */ 1367 host = rlt->rlt_host[idx]; 1368 DPRINTF("%s: session %d: table %s host %s, p 0x%016llx, idx %d", 1369 __func__, con->se_id, table->conf.name, host->conf.name, 1370 p, idx); 1371 } 1372 1373 while (host != NULL) { 1374 DPRINTF("%s: session %d: host %s", __func__, 1375 con->se_id, host->conf.name); 1376 if (!table->conf.check || host->up == HOST_UP) 1377 goto found; 1378 host = TAILQ_NEXT(host, entry); 1379 } 1380 TAILQ_FOREACH(host, &table->hosts, entry) { 1381 DPRINTF("%s: session %d: next host %s", 1382 __func__, con->se_id, host->conf.name); 1383 if (!table->conf.check || host->up == HOST_UP) 1384 goto found; 1385 } 1386 1387 /* Should not happen */ 1388 fatalx("%s: no active hosts, desynchronized", __func__); 1389 1390 found: 1391 if (rlt->rlt_mode == RELAY_DSTMODE_ROUNDROBIN) 1392 rlt->rlt_index = host->idx + 1; 1393 con->se_retry = host->conf.retry; 1394 con->se_out.port = table->conf.port; 1395 bcopy(&host->conf.ss, &con->se_out.ss, sizeof(con->se_out.ss)); 1396 1397 return (0); 1398 } 1399 1400 void 1401 relay_natlook(int fd, short event, void *arg) 1402 { 1403 struct rsession *con = arg; 1404 struct relay *rlay = con->se_relay; 1405 struct ctl_natlook *cnl = con->se_cnl; 1406 1407 if (cnl == NULL) 1408 fatalx("invalid NAT lookup"); 1409 1410 if (con->se_out.ss.ss_family == AF_UNSPEC && cnl->in == -1 && 1411 rlay->rl_conf.dstss.ss_family == AF_UNSPEC && 1412 TAILQ_EMPTY(&rlay->rl_tables)) { 1413 relay_close(con, "session NAT lookup failed", 1); 1414 return; 1415 } 1416 if (cnl->in != -1) { 1417 bcopy(&cnl->rdst, &con->se_out.ss, sizeof(con->se_out.ss)); 1418 con->se_out.port = cnl->rdport; 1419 } 1420 free(con->se_cnl); 1421 con->se_cnl = NULL; 1422 1423 relay_session(con); 1424 } 1425 1426 void 1427 relay_session(struct rsession *con) 1428 { 1429 struct relay *rlay = con->se_relay; 1430 struct ctl_relay_event *in = &con->se_in, *out = &con->se_out; 1431 1432 if (bcmp(&rlay->rl_conf.ss, &out->ss, sizeof(out->ss)) == 0 && 1433 out->port == rlay->rl_conf.port) { 1434 log_debug("%s: session %d: looping", __func__, con->se_id); 1435 relay_close(con, "session aborted", 1); 1436 return; 1437 } 1438 1439 if (rlay->rl_conf.flags & F_UDP) { 1440 /* 1441 * Call the UDP protocol-specific handler 1442 */ 1443 if (rlay->rl_proto->request == NULL) 1444 fatalx("invalid UDP session"); 1445 if ((*rlay->rl_proto->request)(con) == -1) 1446 relay_close(con, "session failed", 1); 1447 return; 1448 } 1449 1450 if ((rlay->rl_conf.flags & F_TLS) && (in->tls == NULL)) { 1451 relay_tls_transaction(con, in); 1452 return; 1453 } 1454 1455 if (rlay->rl_proto->type != RELAY_PROTO_HTTP) { 1456 if (rlay->rl_conf.fwdmode == FWD_TRANS) 1457 relay_bindanyreq(con, 0, IPPROTO_TCP); 1458 else if (relay_connect(con) == -1) { 1459 relay_close(con, "session failed", 1); 1460 return; 1461 } 1462 } 1463 1464 relay_input(con); 1465 } 1466 1467 void 1468 relay_bindanyreq(struct rsession *con, in_port_t port, int proto) 1469 { 1470 struct privsep *ps = env->sc_ps; 1471 struct relay *rlay = con->se_relay; 1472 struct ctl_bindany bnd; 1473 struct timeval tv; 1474 1475 bzero(&bnd, sizeof(bnd)); 1476 bnd.bnd_id = con->se_id; 1477 bnd.bnd_proc = ps->ps_instance; 1478 bnd.bnd_port = port; 1479 bnd.bnd_proto = proto; 1480 bcopy(&con->se_in.ss, &bnd.bnd_ss, sizeof(bnd.bnd_ss)); 1481 proc_compose(env->sc_ps, PROC_PARENT, IMSG_BINDANY, 1482 &bnd, sizeof(bnd)); 1483 1484 /* Schedule timeout */ 1485 evtimer_set(&con->se_ev, relay_bindany, con); 1486 bcopy(&rlay->rl_conf.timeout, &tv, sizeof(tv)); 1487 evtimer_add(&con->se_ev, &tv); 1488 } 1489 1490 void 1491 relay_bindany(int fd, short event, void *arg) 1492 { 1493 struct rsession *con = arg; 1494 1495 if (con->se_bnds == -1) { 1496 relay_close(con, "bindany failed, invalid socket", 1); 1497 return; 1498 } 1499 if (relay_connect(con) == -1) 1500 relay_close(con, "session failed", 1); 1501 } 1502 1503 void 1504 relay_connect_state(struct rsession *con, struct ctl_relay_event *cre, 1505 enum relay_state new) 1506 { 1507 DPRINTF("%s: session %d: %s state %s -> %s", 1508 __func__, con->se_id, 1509 cre->dir == RELAY_DIR_REQUEST ? "accept" : "connect", 1510 relay_state(cre->state), relay_state(new)); 1511 cre->state = new; 1512 } 1513 1514 void 1515 relay_connect_retry(int fd, short sig, void *arg) 1516 { 1517 struct timeval evtpause = { 1, 0 }; 1518 struct rsession *con = arg; 1519 struct relay *rlay = con->se_relay; 1520 int bnds = -1; 1521 1522 if (relay_inflight < 1) { 1523 log_warnx("%s: no connection in flight", __func__); 1524 relay_inflight = 1; 1525 } 1526 1527 DPRINTF("%s: retry %d of %d, inflight: %d",__func__, 1528 con->se_retrycount, con->se_retry, relay_inflight); 1529 1530 if (sig != EV_TIMEOUT) 1531 fatalx("%s: called without timeout", __func__); 1532 1533 evtimer_del(&con->se_inflightevt); 1534 1535 /* 1536 * XXX we might want to check if the inbound socket is still 1537 * available: client could have closed it while we were waiting? 1538 */ 1539 1540 DPRINTF("%s: got EV_TIMEOUT", __func__); 1541 1542 if (getdtablecount() + FD_RESERVE + 1543 relay_inflight > getdtablesize()) { 1544 if (con->se_retrycount < RELAY_OUTOF_FD_RETRIES) { 1545 evtimer_add(&con->se_inflightevt, &evtpause); 1546 return; 1547 } 1548 /* we waited for RELAY_OUTOF_FD_RETRIES seconds, give up */ 1549 event_add(&rlay->rl_ev, NULL); 1550 relay_abort_http(con, 504, "connection timed out", 0); 1551 return; 1552 } 1553 1554 if (rlay->rl_conf.fwdmode == FWD_TRANS) { 1555 /* con->se_bnds cannot be unset */ 1556 bnds = con->se_bnds; 1557 } 1558 1559 retry: 1560 if ((con->se_out.s = relay_socket_connect(&con->se_out.ss, 1561 con->se_out.port, rlay->rl_proto, bnds)) == -1) { 1562 log_debug("%s: session %d: " 1563 "forward failed: %s, %s", __func__, 1564 con->se_id, strerror(errno), 1565 con->se_retry ? "next retry" : "last retry"); 1566 1567 con->se_retrycount++; 1568 1569 if ((errno == ENFILE || errno == EMFILE) && 1570 (con->se_retrycount < con->se_retry)) { 1571 event_del(&rlay->rl_ev); 1572 evtimer_add(&con->se_inflightevt, &evtpause); 1573 evtimer_add(&rlay->rl_evt, &evtpause); 1574 return; 1575 } else if (con->se_retrycount < con->se_retry) 1576 goto retry; 1577 event_add(&rlay->rl_ev, NULL); 1578 relay_abort_http(con, 504, "connect failed", 0); 1579 return; 1580 } 1581 1582 if (rlay->rl_conf.flags & F_TLSINSPECT) 1583 relay_connect_state(con, &con->se_out, STATE_PRECONNECT); 1584 else 1585 relay_connect_state(con, &con->se_out, STATE_CONNECTED); 1586 relay_inflight--; 1587 DPRINTF("%s: inflight decremented, now %d",__func__, relay_inflight); 1588 1589 event_add(&rlay->rl_ev, NULL); 1590 1591 if (errno == EINPROGRESS) 1592 event_again(&con->se_ev, con->se_out.s, EV_WRITE|EV_TIMEOUT, 1593 relay_connected, &con->se_tv_start, &rlay->rl_conf.timeout, 1594 con); 1595 else 1596 relay_connected(con->se_out.s, EV_WRITE, con); 1597 1598 return; 1599 } 1600 1601 int 1602 relay_preconnect(struct rsession *con) 1603 { 1604 int rv; 1605 1606 log_debug("%s: session %d: process %d", __func__, 1607 con->se_id, privsep_process); 1608 rv = relay_connect(con); 1609 if (con->se_out.state == STATE_CONNECTED) 1610 relay_connect_state(con, &con->se_out, STATE_PRECONNECT); 1611 return (rv); 1612 } 1613 1614 int 1615 relay_connect(struct rsession *con) 1616 { 1617 struct relay *rlay = con->se_relay; 1618 struct timeval evtpause = { 1, 0 }; 1619 int bnds = -1, ret; 1620 1621 /* relay_connect should only be called once per relay */ 1622 if (con->se_out.state == STATE_CONNECTED) { 1623 log_debug("%s: connect already called once", __func__); 1624 return (0); 1625 } 1626 1627 /* Connection is already established but session not active */ 1628 if ((rlay->rl_conf.flags & F_TLSINSPECT) && 1629 con->se_out.state == STATE_PRECONNECT) { 1630 if (con->se_out.tls == NULL) { 1631 log_debug("%s: tls connect failed", __func__); 1632 return (-1); 1633 } 1634 relay_connected(con->se_out.s, EV_WRITE, con); 1635 relay_connect_state(con, &con->se_out, STATE_CONNECTED); 1636 return (0); 1637 } 1638 1639 if (relay_inflight < 1) { 1640 log_warnx("relay_connect: no connection in flight"); 1641 relay_inflight = 1; 1642 } 1643 1644 getmonotime(&con->se_tv_start); 1645 1646 if (con->se_out.ss.ss_family == AF_UNSPEC && 1647 !TAILQ_EMPTY(&rlay->rl_tables)) { 1648 if (relay_from_table(con) != 0) 1649 return (-1); 1650 } else if (con->se_out.ss.ss_family == AF_UNSPEC) { 1651 bcopy(&rlay->rl_conf.dstss, &con->se_out.ss, 1652 sizeof(con->se_out.ss)); 1653 con->se_out.port = rlay->rl_conf.dstport; 1654 } 1655 1656 if (rlay->rl_conf.fwdmode == FWD_TRANS) { 1657 if (con->se_bnds == -1) { 1658 log_debug("%s: could not bind any sock", __func__); 1659 return (-1); 1660 } 1661 bnds = con->se_bnds; 1662 } 1663 1664 /* Do the IPv4-to-IPv6 or IPv6-to-IPv4 translation if requested */ 1665 if (rlay->rl_conf.dstaf.ss_family != AF_UNSPEC) { 1666 if (con->se_out.ss.ss_family == AF_INET && 1667 rlay->rl_conf.dstaf.ss_family == AF_INET6) 1668 ret = map4to6(&con->se_out.ss, &rlay->rl_conf.dstaf); 1669 else if (con->se_out.ss.ss_family == AF_INET6 && 1670 rlay->rl_conf.dstaf.ss_family == AF_INET) 1671 ret = map6to4(&con->se_out.ss); 1672 else 1673 ret = 0; 1674 if (ret != 0) { 1675 log_debug("%s: mapped to invalid address", __func__); 1676 return (-1); 1677 } 1678 } 1679 1680 retry: 1681 if ((con->se_out.s = relay_socket_connect(&con->se_out.ss, 1682 con->se_out.port, rlay->rl_proto, bnds)) == -1) { 1683 if (errno == ENFILE || errno == EMFILE) { 1684 log_debug("%s: session %d: forward failed: %s", 1685 __func__, con->se_id, strerror(errno)); 1686 evtimer_set(&con->se_inflightevt, relay_connect_retry, 1687 con); 1688 event_del(&rlay->rl_ev); 1689 evtimer_add(&con->se_inflightevt, &evtpause); 1690 evtimer_add(&rlay->rl_evt, &evtpause); 1691 1692 /* this connect is pending */ 1693 relay_connect_state(con, &con->se_out, STATE_PENDING); 1694 return (0); 1695 } else { 1696 if (con->se_retry) { 1697 con->se_retry--; 1698 log_debug("%s: session %d: " 1699 "forward failed: %s, %s", __func__, 1700 con->se_id, strerror(errno), 1701 con->se_retry ? 1702 "next retry" : "last retry"); 1703 goto retry; 1704 } 1705 log_debug("%s: session %d: forward failed: %s", 1706 __func__, con->se_id, strerror(errno)); 1707 return (-1); 1708 } 1709 } 1710 1711 relay_connect_state(con, &con->se_out, STATE_CONNECTED); 1712 relay_inflight--; 1713 DPRINTF("%s: inflight decremented, now %d",__func__, 1714 relay_inflight); 1715 1716 if (errno == EINPROGRESS) 1717 event_again(&con->se_ev, con->se_out.s, EV_WRITE|EV_TIMEOUT, 1718 relay_connected, &con->se_tv_start, &rlay->rl_conf.timeout, 1719 con); 1720 else 1721 relay_connected(con->se_out.s, EV_WRITE, con); 1722 1723 return (0); 1724 } 1725 1726 void 1727 relay_close(struct rsession *con, const char *msg, int err) 1728 { 1729 char ibuf[128], obuf[128], *ptr = NULL; 1730 struct relay *rlay = con->se_relay; 1731 struct protocol *proto = rlay->rl_proto; 1732 1733 SPLAY_REMOVE(session_tree, &rlay->rl_sessions, con); 1734 relay_session_unpublish(con); 1735 1736 event_del(&con->se_ev); 1737 1738 if ((env->sc_conf.opts & (RELAYD_OPT_LOGCON|RELAYD_OPT_LOGCONERR)) && 1739 msg != NULL) { 1740 bzero(&ibuf, sizeof(ibuf)); 1741 bzero(&obuf, sizeof(obuf)); 1742 (void)print_host(&con->se_in.ss, ibuf, sizeof(ibuf)); 1743 (void)print_host(&con->se_out.ss, obuf, sizeof(obuf)); 1744 if (EVBUFFER_LENGTH(con->se_log) && 1745 evbuffer_add_printf(con->se_log, "\r\n") != -1) { 1746 ptr = evbuffer_readln(con->se_log, NULL, 1747 EVBUFFER_EOL_CRLF); 1748 } 1749 if (err == 0 && (env->sc_conf.opts & RELAYD_OPT_LOGCON)) 1750 log_info("relay %s, " 1751 "session %d (%d active), %s, %s -> %s:%d, " 1752 "%s%s%s", rlay->rl_conf.name, con->se_id, 1753 relay_sessions, con->se_tag != 0 ? 1754 tag_id2name(con->se_tag) : "0", ibuf, obuf, 1755 ntohs(con->se_out.port), msg, ptr == NULL ? 1756 "" : ",", ptr == NULL ? "" : ptr); 1757 if (err == 1 && (env->sc_conf.opts & RELAYD_OPT_LOGCONERR)) 1758 log_warn("relay %s, " 1759 "session %d (%d active), %s, %s -> %s:%d, " 1760 "%s%s%s", rlay->rl_conf.name, con->se_id, 1761 relay_sessions, con->se_tag != 0 ? 1762 tag_id2name(con->se_tag) : "0", ibuf, obuf, 1763 ntohs(con->se_out.port), msg, ptr == NULL ? 1764 "" : ",", ptr == NULL ? "" : ptr); 1765 free(ptr); 1766 } 1767 1768 if (proto->close != NULL) 1769 (*proto->close)(con); 1770 1771 free(con->se_priv); 1772 1773 relay_connect_state(con, &con->se_in, STATE_DONE); 1774 if (relay_reset_event(con, &con->se_in)) { 1775 if (con->se_out.s == -1) { 1776 /* 1777 * the output was never connected, 1778 * thus this was an inflight session. 1779 */ 1780 relay_inflight--; 1781 log_debug("%s: sessions inflight decremented, now %d", 1782 __func__, relay_inflight); 1783 } 1784 } 1785 if (con->se_in.output != NULL) 1786 evbuffer_free(con->se_in.output); 1787 1788 relay_connect_state(con, &con->se_out, STATE_DONE); 1789 if (relay_reset_event(con, &con->se_out)) { 1790 /* Some file descriptors are available again. */ 1791 if (evtimer_pending(&rlay->rl_evt, NULL)) { 1792 evtimer_del(&rlay->rl_evt); 1793 event_add(&rlay->rl_ev, NULL); 1794 } 1795 } 1796 if (con->se_out.output != NULL) 1797 evbuffer_free(con->se_out.output); 1798 1799 if (con->se_log != NULL) 1800 evbuffer_free(con->se_log); 1801 1802 if (con->se_cnl != NULL) { 1803 #if 0 1804 proc_compose_imsg(env->sc_ps, PROC_PFE, -1, IMSG_KILLSTATES, -1, 1805 cnl, sizeof(*cnl)); 1806 #endif 1807 free(con->se_cnl); 1808 } 1809 1810 free(con); 1811 relay_sessions--; 1812 } 1813 1814 int 1815 relay_reset_event(struct rsession *con, struct ctl_relay_event *cre) 1816 { 1817 int rv = 0; 1818 1819 if (cre->state != STATE_DONE) 1820 relay_connect_state(con, cre, STATE_CLOSED); 1821 if (cre->bev != NULL) { 1822 bufferevent_disable(cre->bev, EV_READ|EV_WRITE); 1823 bufferevent_free(cre->bev); 1824 } 1825 if (cre->tls != NULL) 1826 tls_close(cre->tls); 1827 tls_free(cre->tls); 1828 tls_free(cre->tls_ctx); 1829 tls_config_free(cre->tls_cfg); 1830 free(cre->tlscert); 1831 if (cre->s != -1) { 1832 close(cre->s); 1833 rv = 1; 1834 } 1835 cre->bev = NULL; 1836 cre->tls = NULL; 1837 cre->tls_cfg = NULL; 1838 cre->tlscert = NULL; 1839 cre->s = -1; 1840 1841 return (rv); 1842 } 1843 1844 int 1845 relay_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg) 1846 { 1847 struct relay *rlay; 1848 struct rsession *con, se; 1849 struct ctl_natlook cnl; 1850 struct timeval tv; 1851 struct host *host; 1852 struct table *table; 1853 struct ctl_status st; 1854 objid_t id; 1855 int cid; 1856 1857 switch (imsg->hdr.type) { 1858 case IMSG_HOST_DISABLE: 1859 memcpy(&id, imsg->data, sizeof(id)); 1860 if ((host = host_find(env, id)) == NULL) 1861 fatalx("%s: desynchronized", __func__); 1862 if ((table = table_find(env, host->conf.tableid)) == 1863 NULL) 1864 fatalx("%s: invalid table id", __func__); 1865 if (host->up == HOST_UP) 1866 table->up--; 1867 host->flags |= F_DISABLE; 1868 host->up = HOST_UNKNOWN; 1869 break; 1870 case IMSG_HOST_ENABLE: 1871 memcpy(&id, imsg->data, sizeof(id)); 1872 if ((host = host_find(env, id)) == NULL) 1873 fatalx("%s: desynchronized", __func__); 1874 host->flags &= ~(F_DISABLE); 1875 host->up = HOST_UNKNOWN; 1876 break; 1877 case IMSG_TABLE_DISABLE: 1878 memcpy(&id, imsg->data, sizeof(id)); 1879 if ((table = table_find(env, id)) == NULL) 1880 fatalx("%s: desynchronized", __func__); 1881 table->conf.flags |= F_DISABLE; 1882 table->up = 0; 1883 TAILQ_FOREACH(host, &table->hosts, entry) 1884 host->up = HOST_UNKNOWN; 1885 break; 1886 case IMSG_TABLE_ENABLE: 1887 memcpy(&id, imsg->data, sizeof(id)); 1888 if ((table = table_find(env, id)) == NULL) 1889 fatalx("%s: desynchronized", __func__); 1890 table->conf.flags &= ~(F_DISABLE); 1891 table->up = 0; 1892 TAILQ_FOREACH(host, &table->hosts, entry) 1893 host->up = HOST_UNKNOWN; 1894 break; 1895 case IMSG_HOST_STATUS: 1896 IMSG_SIZE_CHECK(imsg, &st); 1897 memcpy(&st, imsg->data, sizeof(st)); 1898 if ((host = host_find(env, st.id)) == NULL) 1899 fatalx("%s: invalid host id", __func__); 1900 if (host->flags & F_DISABLE) 1901 break; 1902 if (host->up == st.up) { 1903 log_debug("%s: host %d => %d", __func__, 1904 host->conf.id, host->up); 1905 fatalx("%s: desynchronized", __func__); 1906 } 1907 1908 if ((table = table_find(env, host->conf.tableid)) 1909 == NULL) 1910 fatalx("%s: invalid table id", __func__); 1911 1912 DPRINTF("%s: [%d] state %d for " 1913 "host %u %s", __func__, p->p_ps->ps_instance, st.up, 1914 host->conf.id, host->conf.name); 1915 1916 if ((st.up == HOST_UNKNOWN && host->up == HOST_DOWN) || 1917 (st.up == HOST_DOWN && host->up == HOST_UNKNOWN)) { 1918 host->up = st.up; 1919 break; 1920 } 1921 if (st.up == HOST_UP) 1922 table->up++; 1923 else 1924 table->up--; 1925 host->up = st.up; 1926 break; 1927 case IMSG_NATLOOK: 1928 bcopy(imsg->data, &cnl, sizeof(cnl)); 1929 if ((con = session_find(env, cnl.id)) == NULL || 1930 con->se_cnl == NULL) { 1931 log_debug("%s: session %d: expired", 1932 __func__, cnl.id); 1933 break; 1934 } 1935 bcopy(&cnl, con->se_cnl, sizeof(*con->se_cnl)); 1936 evtimer_del(&con->se_ev); 1937 evtimer_set(&con->se_ev, relay_natlook, con); 1938 bzero(&tv, sizeof(tv)); 1939 evtimer_add(&con->se_ev, &tv); 1940 break; 1941 case IMSG_CTL_SESSION: 1942 IMSG_SIZE_CHECK(imsg, &cid); 1943 memcpy(&cid, imsg->data, sizeof(cid)); 1944 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) { 1945 SPLAY_FOREACH(con, session_tree, 1946 &rlay->rl_sessions) { 1947 memcpy(&se, con, sizeof(se)); 1948 se.se_cid = cid; 1949 proc_compose(env->sc_ps, p->p_id, 1950 IMSG_CTL_SESSION, &se, sizeof(se)); 1951 } 1952 } 1953 proc_compose(env->sc_ps, p->p_id, IMSG_CTL_END, 1954 &cid, sizeof(cid)); 1955 break; 1956 default: 1957 return (-1); 1958 } 1959 1960 return (0); 1961 } 1962 1963 int 1964 relay_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg) 1965 { 1966 switch (imsg->hdr.type) { 1967 case IMSG_CA_PRIVENC: 1968 case IMSG_CA_PRIVDEC: 1969 log_warnx("%s: priv%s result after timeout", __func__, 1970 imsg->hdr.type == IMSG_CA_PRIVENC ? "enc" : "dec"); 1971 return (0); 1972 } 1973 1974 return (-1); 1975 } 1976 1977 int 1978 relay_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) 1979 { 1980 struct relay_ticket_key ticket; 1981 struct relay *rlay; 1982 struct rsession *con; 1983 struct timeval tv; 1984 objid_t id; 1985 1986 switch (imsg->hdr.type) { 1987 case IMSG_BINDANY: 1988 bcopy(imsg->data, &id, sizeof(id)); 1989 if ((con = session_find(env, id)) == NULL) { 1990 log_debug("%s: session %d: expired", 1991 __func__, id); 1992 break; 1993 } 1994 1995 /* Will validate the result later */ 1996 con->se_bnds = imsg_get_fd(imsg); 1997 1998 evtimer_del(&con->se_ev); 1999 evtimer_set(&con->se_ev, relay_bindany, con); 2000 bzero(&tv, sizeof(tv)); 2001 evtimer_add(&con->se_ev, &tv); 2002 break; 2003 case IMSG_CFG_TABLE: 2004 config_gettable(env, imsg); 2005 break; 2006 case IMSG_CFG_HOST: 2007 config_gethost(env, imsg); 2008 break; 2009 case IMSG_CFG_PROTO: 2010 config_getproto(env, imsg); 2011 break; 2012 case IMSG_CFG_RULE: 2013 config_getrule(env, imsg); 2014 break; 2015 case IMSG_CFG_RELAY: 2016 config_getrelay(env, imsg); 2017 break; 2018 case IMSG_CFG_RELAY_TABLE: 2019 config_getrelaytable(env, imsg); 2020 break; 2021 case IMSG_CFG_RELAY_FD: 2022 config_getrelayfd(env, imsg); 2023 break; 2024 case IMSG_CFG_DONE: 2025 config_getcfg(env, imsg); 2026 break; 2027 case IMSG_CTL_START: 2028 relay_launch(); 2029 break; 2030 case IMSG_CTL_RESET: 2031 config_getreset(env, imsg); 2032 break; 2033 case IMSG_TLSTICKET_REKEY: 2034 IMSG_SIZE_CHECK(imsg, (&ticket)); 2035 memcpy(&env->sc_ticket, imsg->data, sizeof(env->sc_ticket)); 2036 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) { 2037 if (rlay->rl_conf.flags & F_TLS) 2038 tls_config_add_ticket_key(rlay->rl_tls_cfg, 2039 env->sc_ticket.tt_keyrev, 2040 env->sc_ticket.tt_key, 2041 sizeof(env->sc_ticket.tt_key)); 2042 } 2043 break; 2044 default: 2045 return (-1); 2046 } 2047 2048 return (0); 2049 } 2050 2051 int 2052 relay_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg) 2053 { 2054 switch (imsg->hdr.type) { 2055 default: 2056 break; 2057 } 2058 2059 return (-1); 2060 } 2061 2062 static int 2063 relay_tls_ctx_create_proto(struct protocol *proto, struct tls_config *tls_cfg) 2064 { 2065 uint32_t protocols = 0; 2066 2067 /* Set the allowed TLS protocols */ 2068 if (proto->tlsflags & TLSFLAG_TLSV1_2) 2069 protocols |= TLS_PROTOCOL_TLSv1_2; 2070 if (proto->tlsflags & TLSFLAG_TLSV1_3) 2071 protocols |= TLS_PROTOCOL_TLSv1_3; 2072 if (tls_config_set_protocols(tls_cfg, protocols) == -1) { 2073 log_warnx("could not set the TLS protocol: %s", 2074 tls_config_error(tls_cfg)); 2075 return (-1); 2076 } 2077 2078 if (tls_config_set_ciphers(tls_cfg, proto->tlsciphers)) { 2079 log_warnx("could not set the TLS cypers: %s", 2080 tls_config_error(tls_cfg)); 2081 return (-1); 2082 } 2083 2084 if ((proto->tlsflags & TLSFLAG_CIPHER_SERVER_PREF) == 0) 2085 tls_config_prefer_ciphers_client(tls_cfg); 2086 2087 /* 2088 * Set session ID context to a random value. It needs to be the 2089 * same across all relay processes or session caching will fail. 2090 */ 2091 if (tls_config_set_session_id(tls_cfg, env->sc_conf.tls_sid, 2092 sizeof(env->sc_conf.tls_sid)) == -1) { 2093 log_warnx("could not set the TLS session ID: %s", 2094 tls_config_error(tls_cfg)); 2095 return (-1); 2096 } 2097 2098 /* Set callback for TLS session tickets if enabled */ 2099 if (proto->tickets == 1) { 2100 /* set timeout to the ticket rekey time */ 2101 tls_config_set_session_lifetime(tls_cfg, TLS_SESSION_LIFETIME); 2102 2103 tls_config_add_ticket_key(tls_cfg, 2104 env->sc_ticket.tt_keyrev, env->sc_ticket.tt_key, 2105 sizeof(env->sc_ticket.tt_key)); 2106 } 2107 2108 if (tls_config_set_ecdhecurves(tls_cfg, proto->tlsecdhecurves) != 0) { 2109 log_warnx("failed to set ecdhe curves %s: %s", 2110 proto->tlsecdhecurves, tls_config_error(tls_cfg)); 2111 return (-1); 2112 } 2113 2114 if (tls_config_set_dheparams(tls_cfg, proto->tlsdhparams) != 0) { 2115 log_warnx("failed to set dh params %s: %s", 2116 proto->tlsdhparams, tls_config_error(tls_cfg)); 2117 return (-1); 2118 } 2119 2120 return (0); 2121 } 2122 2123 /* 2124 * This function is not publicy exported because it is a hack until libtls 2125 * has a proper privsep setup 2126 */ 2127 void tls_config_use_fake_private_key(struct tls_config *config); 2128 2129 int 2130 relay_tls_ctx_create(struct relay *rlay) 2131 { 2132 struct tls_config *tls_cfg, *tls_client_cfg; 2133 struct tls *tls = NULL; 2134 struct relay_cert *cert; 2135 int keyfound = 0; 2136 char *buf = NULL, *cabuf = NULL, *ocspbuf = NULL; 2137 off_t len = 0, calen = 0, ocsplen = 0; 2138 2139 if ((tls_cfg = tls_config_new()) == NULL) { 2140 log_warnx("unable to allocate TLS config"); 2141 return (-1); 2142 } 2143 if ((tls_client_cfg = tls_config_new()) == NULL) { 2144 log_warnx("unable to allocate TLS config"); 2145 return (-1); 2146 } 2147 2148 if (relay_tls_ctx_create_proto(rlay->rl_proto, tls_cfg) == -1) 2149 goto err; 2150 if (relay_tls_ctx_create_proto(rlay->rl_proto, tls_client_cfg) == -1) 2151 goto err; 2152 2153 /* Verify the server certificate if we have a CA chain */ 2154 if (rlay->rl_conf.flags & F_TLSCLIENT) { 2155 /* 2156 * Currently relayd can't verify the name of certs and changing 2157 * this is non trivial. For now just disable name verification. 2158 */ 2159 tls_config_insecure_noverifyname(tls_client_cfg); 2160 2161 if (rlay->rl_tls_ca_fd != -1) { 2162 if ((buf = relay_load_fd(rlay->rl_tls_ca_fd, &len)) == 2163 NULL) { 2164 log_warn("failed to read root certificates"); 2165 goto err; 2166 } 2167 rlay->rl_tls_ca_fd = -1; 2168 2169 if (tls_config_set_ca_mem(tls_client_cfg, buf, len) != 2170 0) { 2171 log_warnx("failed to set root certificates: %s", 2172 tls_config_error(tls_client_cfg)); 2173 goto err; 2174 } 2175 purge_key(&buf, len); 2176 } else { 2177 /* No root cert available so disable the checking */ 2178 tls_config_insecure_noverifycert(tls_client_cfg); 2179 } 2180 2181 rlay->rl_tls_client_cfg = tls_client_cfg; 2182 } 2183 2184 if (rlay->rl_conf.flags & F_TLS) { 2185 log_debug("%s: loading certificate", __func__); 2186 /* 2187 * Use the public key as the "private" key - the secret key 2188 * parameters are hidden in an extra process that will be 2189 * contacted by the RSA engine. The TLS library needs at 2190 * least the public key parameters in the current process. 2191 */ 2192 tls_config_use_fake_private_key(tls_cfg); 2193 2194 TAILQ_FOREACH(cert, env->sc_certs, cert_entry) { 2195 if (cert->cert_relayid != rlay->rl_conf.id || 2196 cert->cert_fd == -1) 2197 continue; 2198 keyfound++; 2199 2200 if ((buf = relay_load_fd(cert->cert_fd, 2201 &len)) == NULL) { 2202 log_warn("failed to load tls certificate"); 2203 goto err; 2204 } 2205 cert->cert_fd = -1; 2206 2207 if (cert->cert_ocsp_fd != -1 && 2208 (ocspbuf = relay_load_fd(cert->cert_ocsp_fd, 2209 &ocsplen)) == NULL) { 2210 log_warn("failed to load OCSP staplefile"); 2211 goto err; 2212 } 2213 if (ocsplen == 0) 2214 purge_key(&ocspbuf, ocsplen); 2215 cert->cert_ocsp_fd = -1; 2216 2217 if (keyfound == 1 && 2218 tls_config_set_keypair_ocsp_mem(tls_cfg, buf, len, 2219 NULL, 0, ocspbuf, ocsplen) != 0) { 2220 log_warnx("failed to set tls certificate: %s", 2221 tls_config_error(tls_cfg)); 2222 goto err; 2223 } 2224 2225 /* loading certificate public key */ 2226 if (keyfound == 1 && 2227 !ssl_load_pkey(buf, len, NULL, &rlay->rl_tls_pkey)) 2228 goto err; 2229 2230 if (tls_config_add_keypair_ocsp_mem(tls_cfg, buf, len, 2231 NULL, 0, ocspbuf, ocsplen) != 0) { 2232 log_warnx("failed to add tls certificate: %s", 2233 tls_config_error(tls_cfg)); 2234 goto err; 2235 } 2236 2237 purge_key(&buf, len); 2238 purge_key(&ocspbuf, ocsplen); 2239 } 2240 2241 if (rlay->rl_tls_cacert_fd != -1) { 2242 if ((cabuf = relay_load_fd(rlay->rl_tls_cacert_fd, 2243 &calen)) == NULL) { 2244 log_warn("failed to load tls CA certificate"); 2245 goto err; 2246 } 2247 log_debug("%s: loading CA certificate", __func__); 2248 if (!ssl_load_pkey(cabuf, calen, 2249 &rlay->rl_tls_cacertx509, &rlay->rl_tls_capkey)) 2250 goto err; 2251 } 2252 rlay->rl_tls_cacert_fd = -1; 2253 2254 tls = tls_server(); 2255 if (tls == NULL) { 2256 log_warnx("unable to allocate TLS context"); 2257 goto err; 2258 } 2259 if (tls_configure(tls, tls_cfg) == -1) { 2260 log_warnx("could not configure the TLS context: %s", 2261 tls_error(tls)); 2262 tls_free(tls); 2263 goto err; 2264 } 2265 rlay->rl_tls_cfg = tls_cfg; 2266 rlay->rl_tls_ctx = tls; 2267 2268 purge_key(&cabuf, calen); 2269 } 2270 2271 if (rlay->rl_tls_client_cfg == NULL) 2272 tls_config_free(tls_client_cfg); 2273 if (rlay->rl_tls_cfg == NULL) 2274 tls_config_free(tls_cfg); 2275 2276 return (0); 2277 err: 2278 purge_key(&ocspbuf, ocsplen); 2279 purge_key(&cabuf, calen); 2280 purge_key(&buf, len); 2281 2282 tls_config_free(tls_client_cfg); 2283 tls_config_free(tls_cfg); 2284 return (-1); 2285 } 2286 2287 static struct tls * 2288 relay_tls_inspect_create(struct relay *rlay, struct ctl_relay_event *cre) 2289 { 2290 struct tls_config *tls_cfg; 2291 struct tls *tls = NULL; 2292 2293 /* TLS inspection: use session-specific certificate */ 2294 if ((tls_cfg = tls_config_new()) == NULL) { 2295 log_warnx("unable to allocate TLS config"); 2296 goto err; 2297 } 2298 if (relay_tls_ctx_create_proto(rlay->rl_proto, tls_cfg) == -1) { 2299 /* error already printed */ 2300 goto err; 2301 } 2302 2303 tls_config_use_fake_private_key(tls_cfg); 2304 2305 if (tls_config_set_keypair_ocsp_mem(tls_cfg, 2306 cre->tlscert, cre->tlscert_len, NULL, 0, NULL, 0) != 0) { 2307 log_warnx("failed to set tls certificate: %s", 2308 tls_config_error(tls_cfg)); 2309 goto err; 2310 } 2311 2312 tls = tls_server(); 2313 if (tls == NULL) { 2314 log_warnx("unable to allocate TLS context"); 2315 goto err; 2316 } 2317 if (tls_configure(tls, tls_cfg) == -1) { 2318 log_warnx("could not configure the TLS context: %s", 2319 tls_error(tls)); 2320 tls_free(tls); 2321 goto err; 2322 } 2323 2324 cre->tls_cfg = tls_cfg; 2325 cre->tls_ctx = tls; 2326 return (tls); 2327 err: 2328 tls_config_free(tls_cfg); 2329 return (NULL); 2330 } 2331 2332 void 2333 relay_tls_transaction(struct rsession *con, struct ctl_relay_event *cre) 2334 { 2335 struct relay *rlay = con->se_relay; 2336 struct tls *tls_server; 2337 const char *errstr; 2338 u_int flag; 2339 2340 if (cre->dir == RELAY_DIR_REQUEST) { 2341 if (cre->tlscert != NULL) 2342 tls_server = relay_tls_inspect_create(rlay, cre); 2343 else 2344 tls_server = rlay->rl_tls_ctx; 2345 if (tls_server == NULL) { 2346 errstr = "no TLS server context available"; 2347 goto err; 2348 } 2349 2350 if (tls_accept_socket(tls_server, &cre->tls, cre->s) == -1) { 2351 errstr = "could not accept the TLS connection"; 2352 goto err; 2353 } 2354 flag = EV_READ; 2355 } else { 2356 cre->tls = tls_client(); 2357 if (cre->tls == NULL || 2358 tls_configure(cre->tls, rlay->rl_tls_client_cfg) == -1) { 2359 errstr = "could not configure the TLS client context"; 2360 goto err; 2361 } 2362 if (tls_connect_socket(cre->tls, cre->s, NULL) == -1) { 2363 errstr = "could not connect the TLS connection"; 2364 goto err; 2365 } 2366 flag = EV_WRITE; 2367 } 2368 2369 log_debug("%s: session %d: scheduling on %s", __func__, con->se_id, 2370 (flag == EV_READ) ? "EV_READ" : "EV_WRITE"); 2371 event_again(&con->se_ev, cre->s, EV_TIMEOUT|flag, relay_tls_handshake, 2372 &con->se_tv_start, &rlay->rl_conf.timeout, cre); 2373 return; 2374 2375 err: 2376 relay_close(con, errstr, 1); 2377 } 2378 2379 void 2380 relay_tls_handshake(int fd, short event, void *arg) 2381 { 2382 struct ctl_relay_event *cre = arg; 2383 struct rsession *con = cre->con; 2384 struct relay *rlay = con->se_relay; 2385 int retry_flag = 0; 2386 int ret; 2387 char *msg; 2388 2389 if (event == EV_TIMEOUT) { 2390 relay_close(con, "TLS handshake timeout", 1); 2391 return; 2392 } 2393 2394 ret = tls_handshake(cre->tls); 2395 if (ret == 0) { 2396 #ifdef DEBUG 2397 log_info( 2398 #else 2399 log_debug( 2400 #endif 2401 "relay %s, tls session %d %s (%d active)", 2402 rlay->rl_conf.name, con->se_id, 2403 cre->dir == RELAY_DIR_REQUEST ? "established" : "connected", 2404 relay_sessions); 2405 2406 if (cre->dir == RELAY_DIR_REQUEST) { 2407 relay_session(con); 2408 return; 2409 } 2410 2411 if (rlay->rl_conf.flags & F_TLSINSPECT) { 2412 const uint8_t *servercert; 2413 size_t len; 2414 2415 servercert = tls_peer_cert_chain_pem(con->se_out.tls, 2416 &len); 2417 if (servercert != NULL) { 2418 con->se_in.tlscert = ssl_update_certificate( 2419 servercert, len, 2420 rlay->rl_tls_pkey, rlay->rl_tls_capkey, 2421 rlay->rl_tls_cacertx509, 2422 &con->se_in.tlscert_len); 2423 } else 2424 con->se_in.tlscert = NULL; 2425 if (con->se_in.tlscert == NULL) 2426 relay_close(con, 2427 "could not create certificate", 1); 2428 else 2429 relay_session(con); 2430 return; 2431 } 2432 relay_connected(fd, EV_WRITE, con); 2433 return; 2434 } else if (ret == TLS_WANT_POLLIN) { 2435 retry_flag = EV_READ; 2436 } else if (ret == TLS_WANT_POLLOUT) { 2437 retry_flag = EV_WRITE; 2438 } else { 2439 if (asprintf(&msg, "TLS handshake error: %s", 2440 tls_error(cre->tls)) >= 0) { 2441 relay_close(con, msg, 1); 2442 free(msg); 2443 } else { 2444 relay_close(con, "TLS handshake error", 1); 2445 } 2446 return; 2447 } 2448 2449 DPRINTF("%s: session %d: scheduling on %s", __func__, con->se_id, 2450 (retry_flag == EV_READ) ? "EV_READ" : "EV_WRITE"); 2451 event_again(&con->se_ev, fd, EV_TIMEOUT|retry_flag, relay_tls_handshake, 2452 &con->se_tv_start, &rlay->rl_conf.timeout, cre); 2453 } 2454 2455 void 2456 relay_tls_connected(struct ctl_relay_event *cre) 2457 { 2458 /* 2459 * Hack libevent - we overwrite the internal bufferevent I/O 2460 * functions to handle the TLS abstraction. 2461 */ 2462 event_del(&cre->bev->ev_read); 2463 event_del(&cre->bev->ev_write); 2464 2465 event_set(&cre->bev->ev_read, cre->s, EV_READ, 2466 relay_tls_readcb, cre->bev); 2467 event_set(&cre->bev->ev_write, cre->s, EV_WRITE, 2468 relay_tls_writecb, cre->bev); 2469 } 2470 2471 void 2472 relay_tls_readcb(int fd, short event, void *arg) 2473 { 2474 char rbuf[IBUF_READ_SIZE]; 2475 struct bufferevent *bufev = arg; 2476 struct ctl_relay_event *cre = bufev->cbarg; 2477 short what = EVBUFFER_READ; 2478 int howmuch = IBUF_READ_SIZE; 2479 ssize_t ret; 2480 size_t len; 2481 2482 if (event == EV_TIMEOUT) { 2483 what |= EVBUFFER_TIMEOUT; 2484 goto err; 2485 } 2486 2487 if (bufev->wm_read.high != 0) 2488 howmuch = MINIMUM(sizeof(rbuf), bufev->wm_read.high); 2489 2490 ret = tls_read(cre->tls, rbuf, howmuch); 2491 if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) { 2492 goto retry; 2493 } else if (ret == -1) { 2494 what |= EVBUFFER_ERROR; 2495 goto err; 2496 } 2497 len = ret; 2498 2499 if (len == 0) { 2500 what |= EVBUFFER_EOF; 2501 goto err; 2502 } 2503 2504 if (evbuffer_add(bufev->input, rbuf, ret) == -1) { 2505 what |= EVBUFFER_ERROR; 2506 goto err; 2507 } 2508 2509 relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read); 2510 2511 len = EVBUFFER_LENGTH(bufev->input); 2512 if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) 2513 return; 2514 if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) { 2515 struct evbuffer *buf = bufev->input; 2516 event_del(&bufev->ev_read); 2517 evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); 2518 return; 2519 } 2520 2521 if (bufev->readcb != NULL) 2522 (*bufev->readcb)(bufev, bufev->cbarg); 2523 return; 2524 2525 retry: 2526 relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read); 2527 return; 2528 2529 err: 2530 (*bufev->errorcb)(bufev, what, bufev->cbarg); 2531 } 2532 2533 void 2534 relay_tls_writecb(int fd, short event, void *arg) 2535 { 2536 struct bufferevent *bufev = arg; 2537 struct ctl_relay_event *cre = bufev->cbarg; 2538 ssize_t ret; 2539 size_t len; 2540 short what = EVBUFFER_WRITE; 2541 2542 if (event == EV_TIMEOUT) { 2543 what |= EVBUFFER_TIMEOUT; 2544 goto err; 2545 } 2546 2547 if (EVBUFFER_LENGTH(bufev->output)) { 2548 ret = tls_write(cre->tls, EVBUFFER_DATA(bufev->output), 2549 EVBUFFER_LENGTH(bufev->output)); 2550 if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) { 2551 goto retry; 2552 } else if (ret == -1) { 2553 what |= EVBUFFER_ERROR; 2554 goto err; 2555 } 2556 len = ret; 2557 evbuffer_drain(bufev->output, len); 2558 } 2559 2560 if (EVBUFFER_LENGTH(bufev->output) != 0) 2561 relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write); 2562 2563 if (bufev->writecb != NULL && 2564 EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) 2565 (*bufev->writecb)(bufev, bufev->cbarg); 2566 return; 2567 2568 retry: 2569 relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write); 2570 return; 2571 2572 err: 2573 (*bufev->errorcb)(bufev, what, bufev->cbarg); 2574 } 2575 2576 int 2577 relay_bufferevent_add(struct event *ev, int timeout) 2578 { 2579 struct timeval tv, *ptv = NULL; 2580 2581 if (timeout) { 2582 timerclear(&tv); 2583 tv.tv_sec = timeout; 2584 ptv = &tv; 2585 } 2586 2587 return (event_add(ev, ptv)); 2588 } 2589 2590 #ifdef notyet 2591 int 2592 relay_bufferevent_printf(struct ctl_relay_event *cre, const char *fmt, ...) 2593 { 2594 int ret; 2595 va_list ap; 2596 2597 va_start(ap, fmt); 2598 ret = evbuffer_add_vprintf(cre->output, fmt, ap); 2599 va_end(ap); 2600 2601 if (cre->bev != NULL && 2602 ret != -1 && EVBUFFER_LENGTH(cre->output) > 0 && 2603 (cre->bev->enabled & EV_WRITE)) 2604 bufferevent_enable(cre->bev, EV_WRITE); 2605 2606 return (ret); 2607 } 2608 #endif 2609 2610 int 2611 relay_bufferevent_print(struct ctl_relay_event *cre, const char *str) 2612 { 2613 if (cre->bev == NULL) 2614 return (evbuffer_add(cre->output, str, strlen(str))); 2615 return (bufferevent_write(cre->bev, str, strlen(str))); 2616 } 2617 2618 int 2619 relay_bufferevent_write_buffer(struct ctl_relay_event *cre, 2620 struct evbuffer *buf) 2621 { 2622 if (cre->bev == NULL) 2623 return (evbuffer_add_buffer(cre->output, buf)); 2624 return (bufferevent_write_buffer(cre->bev, buf)); 2625 } 2626 2627 int 2628 relay_bufferevent_write_chunk(struct ctl_relay_event *cre, 2629 struct evbuffer *buf, size_t size) 2630 { 2631 int ret; 2632 ret = relay_bufferevent_write(cre, EVBUFFER_DATA(buf), size); 2633 if (ret != -1) 2634 evbuffer_drain(buf, size); 2635 return (ret); 2636 } 2637 2638 int 2639 relay_bufferevent_write(struct ctl_relay_event *cre, void *data, size_t size) 2640 { 2641 if (cre->bev == NULL) 2642 return (evbuffer_add(cre->output, data, size)); 2643 return (bufferevent_write(cre->bev, data, size)); 2644 } 2645 2646 int 2647 relay_cmp_af(struct sockaddr_storage *a, struct sockaddr_storage *b) 2648 { 2649 int ret = -1; 2650 struct sockaddr_in ia, ib; 2651 struct sockaddr_in6 ia6, ib6; 2652 2653 switch (a->ss_family) { 2654 case AF_INET: 2655 bcopy(a, &ia, sizeof(struct sockaddr_in)); 2656 bcopy(b, &ib, sizeof(struct sockaddr_in)); 2657 2658 ret = memcmp(&ia.sin_addr, &ib.sin_addr, 2659 sizeof(ia.sin_addr)); 2660 if (ret == 0) 2661 ret = memcmp(&ia.sin_port, &ib.sin_port, 2662 sizeof(ia.sin_port)); 2663 break; 2664 case AF_INET6: 2665 bcopy(a, &ia6, sizeof(struct sockaddr_in6)); 2666 bcopy(b, &ib6, sizeof(struct sockaddr_in6)); 2667 2668 ret = memcmp(&ia6.sin6_addr, &ib6.sin6_addr, 2669 sizeof(ia6.sin6_addr)); 2670 if (ret == 0) 2671 ret = memcmp(&ia6.sin6_port, &ib6.sin6_port, 2672 sizeof(ia6.sin6_port)); 2673 break; 2674 default: 2675 break; 2676 } 2677 2678 return (ret); 2679 } 2680 2681 int 2682 relay_session_cmp(struct rsession *a, struct rsession *b) 2683 { 2684 struct relay *rlay = b->se_relay; 2685 struct protocol *proto = rlay->rl_proto; 2686 2687 if (proto != NULL && proto->cmp != NULL) 2688 return ((*proto->cmp)(a, b)); 2689 2690 return ((int)a->se_id - b->se_id); 2691 } 2692 2693 void 2694 relay_log(struct rsession *con, char *msg) 2695 { 2696 if (con->se_haslog && con->se_log != NULL) { 2697 evbuffer_add(con->se_log, msg, strlen(msg)); 2698 } 2699 } 2700 2701 SPLAY_GENERATE(session_tree, rsession, se_nodes, relay_session_cmp); 2702