1 /* $OpenBSD: relay.c,v 1.260 2024/10/28 19:56:18 tb 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
relay(struct privsep * ps,struct privsep_proc * p)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
relay_shutdown(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
relay_ruledebug(struct relay_rule * rule)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
relay_protodebug(struct relay * rlay)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
relay_privinit(struct relay * rlay)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
relay_init(struct privsep * ps,struct privsep_proc * p,void * arg)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
relay_session_publish(struct rsession * s)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
relay_session_unpublish(struct rsession * s)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
relay_statistics(int fd,short events,void * arg)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
relay_launch(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
relay_socket_af(struct sockaddr_storage * ss,in_port_t port)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
relay_socket_getport(struct sockaddr_storage * ss)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
relay_socket(struct sockaddr_storage * ss,in_port_t port,struct protocol * proto,int fd,int reuseport)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
relay_socket_connect(struct sockaddr_storage * ss,in_port_t port,struct protocol * proto,int fd)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
relay_socket_listen(struct sockaddr_storage * ss,in_port_t port,struct protocol * proto)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
relay_connected(int fd,short sig,void * arg)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
relay_input(struct rsession * con)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
relay_write(struct bufferevent * bev,void * arg)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
relay_dump(struct ctl_relay_event * cre,const void * buf,size_t len)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
relay_read(struct bufferevent * bev,void * arg)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
relay_splice(struct ctl_relay_event * cre)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
relay_splicelen(struct ctl_relay_event * cre)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
relay_spliceadjust(struct ctl_relay_event * cre)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
relay_error(struct bufferevent * bev,short error,void * arg)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
relay_accept(int fd,short event,void * arg)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
relay_hash_addr(SIPHASH_CTX * ctx,struct sockaddr_storage * ss,int portset)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
relay_from_table(struct rsession * con)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
relay_natlook(int fd,short event,void * arg)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
relay_session(struct rsession * con)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
relay_bindanyreq(struct rsession * con,in_port_t port,int proto)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
relay_bindany(int fd,short event,void * arg)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
relay_connect_state(struct rsession * con,struct ctl_relay_event * cre,enum relay_state new)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
relay_connect_retry(int fd,short sig,void * arg)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
relay_preconnect(struct rsession * con)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
relay_connect(struct rsession * con)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
relay_close(struct rsession * con,const char * msg,int err)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
relay_reset_event(struct rsession * con,struct ctl_relay_event * cre)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
relay_dispatch_pfe(int fd,struct privsep_proc * p,struct imsg * imsg)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
relay_dispatch_ca(int fd,struct privsep_proc * p,struct imsg * imsg)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
relay_dispatch_parent(int fd,struct privsep_proc * p,struct imsg * imsg)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
relay_dispatch_hce(int fd,struct privsep_proc * p,struct imsg * imsg)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
relay_tls_ctx_create_proto(struct protocol * proto,struct tls_config * tls_cfg)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
relay_tls_ctx_create(struct relay * rlay)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)) == NULL) {
2163 log_warn("failed to read root certificates");
2164 goto err;
2165 }
2166 rlay->rl_tls_ca_fd = -1;
2167
2168 if (tls_config_set_ca_mem(tls_client_cfg, buf, len) !=
2169 0) {
2170 log_warnx("failed to set root certificates: %s",
2171 tls_config_error(tls_client_cfg));
2172 goto err;
2173 }
2174 purge_key(&buf, len);
2175 } else {
2176 /* No root cert available so disable the checking */
2177 tls_config_insecure_noverifycert(tls_client_cfg);
2178 }
2179
2180 rlay->rl_tls_client_cfg = tls_client_cfg;
2181 }
2182
2183 if (rlay->rl_conf.flags & F_TLS) {
2184 log_debug("%s: loading certificate", __func__);
2185 /*
2186 * Use the public key as the "private" key - the secret key
2187 * parameters are hidden in an extra process that will be
2188 * contacted by the RSA engine. The TLS library needs at
2189 * least the public key parameters in the current process.
2190 */
2191 tls_config_use_fake_private_key(tls_cfg);
2192
2193 TAILQ_FOREACH(cert, env->sc_certs, cert_entry) {
2194 if (cert->cert_relayid != rlay->rl_conf.id ||
2195 cert->cert_fd == -1)
2196 continue;
2197 keyfound++;
2198
2199 if ((buf = relay_load_fd(cert->cert_fd,
2200 &len)) == NULL) {
2201 log_warn("failed to load tls certificate");
2202 goto err;
2203 }
2204 cert->cert_fd = -1;
2205
2206 if (cert->cert_ocsp_fd != -1 &&
2207 (ocspbuf = relay_load_fd(cert->cert_ocsp_fd,
2208 &ocsplen)) == NULL) {
2209 log_warn("failed to load OCSP staplefile");
2210 goto err;
2211 }
2212 if (ocsplen == 0)
2213 purge_key(&ocspbuf, ocsplen);
2214 cert->cert_ocsp_fd = -1;
2215
2216 if (keyfound == 1 &&
2217 tls_config_set_keypair_ocsp_mem(tls_cfg, buf, len,
2218 NULL, 0, ocspbuf, ocsplen) != 0) {
2219 log_warnx("failed to set tls certificate: %s",
2220 tls_config_error(tls_cfg));
2221 goto err;
2222 }
2223
2224 /* loading certificate public key */
2225 if (keyfound == 1 &&
2226 !ssl_load_pkey(buf, len, NULL, &rlay->rl_tls_pkey))
2227 goto err;
2228
2229 if (tls_config_add_keypair_ocsp_mem(tls_cfg, buf, len,
2230 NULL, 0, ocspbuf, ocsplen) != 0) {
2231 log_warnx("failed to add tls certificate: %s",
2232 tls_config_error(tls_cfg));
2233 goto err;
2234 }
2235
2236 purge_key(&buf, len);
2237 purge_key(&ocspbuf, ocsplen);
2238 }
2239
2240 if (rlay->rl_tls_cacert_fd != -1) {
2241 if ((cabuf = relay_load_fd(rlay->rl_tls_cacert_fd,
2242 &calen)) == NULL) {
2243 log_warn("failed to load tls CA certificate");
2244 goto err;
2245 }
2246 log_debug("%s: loading CA certificate", __func__);
2247 if (!ssl_load_pkey(cabuf, calen,
2248 &rlay->rl_tls_cacertx509, &rlay->rl_tls_capkey))
2249 goto err;
2250 }
2251 rlay->rl_tls_cacert_fd = -1;
2252
2253 if (rlay->rl_tls_client_ca_fd != -1) {
2254 if ((buf = relay_load_fd(rlay->rl_tls_client_ca_fd,
2255 &len)) == NULL) {
2256 log_warn(
2257 "failed to read tls client CA certificate");
2258 goto err;
2259 }
2260
2261 if (tls_config_set_ca_mem(tls_cfg, buf, len) != 0) {
2262 log_warnx(
2263 "failed to set tls client CA cert: %s",
2264 tls_config_error(tls_cfg));
2265 goto err;
2266 }
2267 purge_key(&buf, len);
2268
2269 tls_config_verify_client(tls_cfg);
2270 }
2271 rlay->rl_tls_client_ca_fd = -1;
2272
2273 tls = tls_server();
2274 if (tls == NULL) {
2275 log_warnx("unable to allocate TLS context");
2276 goto err;
2277 }
2278 if (tls_configure(tls, tls_cfg) == -1) {
2279 log_warnx("could not configure the TLS context: %s",
2280 tls_error(tls));
2281 tls_free(tls);
2282 goto err;
2283 }
2284 rlay->rl_tls_cfg = tls_cfg;
2285 rlay->rl_tls_ctx = tls;
2286
2287 purge_key(&cabuf, calen);
2288 }
2289
2290 if (rlay->rl_tls_client_cfg == NULL)
2291 tls_config_free(tls_client_cfg);
2292 if (rlay->rl_tls_cfg == NULL)
2293 tls_config_free(tls_cfg);
2294
2295 return (0);
2296 err:
2297 purge_key(&ocspbuf, ocsplen);
2298 purge_key(&cabuf, calen);
2299 purge_key(&buf, len);
2300
2301 tls_config_free(tls_client_cfg);
2302 tls_config_free(tls_cfg);
2303 return (-1);
2304 }
2305
2306 static struct tls *
relay_tls_inspect_create(struct relay * rlay,struct ctl_relay_event * cre)2307 relay_tls_inspect_create(struct relay *rlay, struct ctl_relay_event *cre)
2308 {
2309 struct tls_config *tls_cfg;
2310 struct tls *tls = NULL;
2311
2312 /* TLS inspection: use session-specific certificate */
2313 if ((tls_cfg = tls_config_new()) == NULL) {
2314 log_warnx("unable to allocate TLS config");
2315 goto err;
2316 }
2317 if (relay_tls_ctx_create_proto(rlay->rl_proto, tls_cfg) == -1) {
2318 /* error already printed */
2319 goto err;
2320 }
2321
2322 tls_config_use_fake_private_key(tls_cfg);
2323
2324 if (tls_config_set_keypair_ocsp_mem(tls_cfg,
2325 cre->tlscert, cre->tlscert_len, NULL, 0, NULL, 0) != 0) {
2326 log_warnx("failed to set tls certificate: %s",
2327 tls_config_error(tls_cfg));
2328 goto err;
2329 }
2330
2331 tls = tls_server();
2332 if (tls == NULL) {
2333 log_warnx("unable to allocate TLS context");
2334 goto err;
2335 }
2336 if (tls_configure(tls, tls_cfg) == -1) {
2337 log_warnx("could not configure the TLS context: %s",
2338 tls_error(tls));
2339 tls_free(tls);
2340 goto err;
2341 }
2342
2343 cre->tls_cfg = tls_cfg;
2344 cre->tls_ctx = tls;
2345 return (tls);
2346 err:
2347 tls_config_free(tls_cfg);
2348 return (NULL);
2349 }
2350
2351 void
relay_tls_transaction(struct rsession * con,struct ctl_relay_event * cre)2352 relay_tls_transaction(struct rsession *con, struct ctl_relay_event *cre)
2353 {
2354 struct relay *rlay = con->se_relay;
2355 struct tls *tls_server;
2356 const char *errstr;
2357 u_int flag;
2358
2359 if (cre->dir == RELAY_DIR_REQUEST) {
2360 if (cre->tlscert != NULL)
2361 tls_server = relay_tls_inspect_create(rlay, cre);
2362 else
2363 tls_server = rlay->rl_tls_ctx;
2364 if (tls_server == NULL) {
2365 errstr = "no TLS server context available";
2366 goto err;
2367 }
2368
2369 if (tls_accept_socket(tls_server, &cre->tls, cre->s) == -1) {
2370 errstr = "could not accept the TLS connection";
2371 goto err;
2372 }
2373 flag = EV_READ;
2374 } else {
2375 cre->tls = tls_client();
2376 if (cre->tls == NULL ||
2377 tls_configure(cre->tls, rlay->rl_tls_client_cfg) == -1) {
2378 errstr = "could not configure the TLS client context";
2379 goto err;
2380 }
2381 if (tls_connect_socket(cre->tls, cre->s, NULL) == -1) {
2382 errstr = "could not connect the TLS connection";
2383 goto err;
2384 }
2385 flag = EV_WRITE;
2386 }
2387
2388 log_debug("%s: session %d: scheduling on %s", __func__, con->se_id,
2389 (flag == EV_READ) ? "EV_READ" : "EV_WRITE");
2390 event_again(&con->se_ev, cre->s, EV_TIMEOUT|flag, relay_tls_handshake,
2391 &con->se_tv_start, &rlay->rl_conf.timeout, cre);
2392 return;
2393
2394 err:
2395 relay_close(con, errstr, 1);
2396 }
2397
2398 void
relay_tls_handshake(int fd,short event,void * arg)2399 relay_tls_handshake(int fd, short event, void *arg)
2400 {
2401 struct ctl_relay_event *cre = arg;
2402 struct rsession *con = cre->con;
2403 struct relay *rlay = con->se_relay;
2404 int retry_flag = 0;
2405 int ret;
2406 char *msg;
2407
2408 if (event == EV_TIMEOUT) {
2409 relay_close(con, "TLS handshake timeout", 1);
2410 return;
2411 }
2412
2413 ret = tls_handshake(cre->tls);
2414 if (ret == 0) {
2415 #ifdef DEBUG
2416 log_info(
2417 #else
2418 log_debug(
2419 #endif
2420 "relay %s, tls session %d %s (%d active)",
2421 rlay->rl_conf.name, con->se_id,
2422 cre->dir == RELAY_DIR_REQUEST ? "established" : "connected",
2423 relay_sessions);
2424
2425 if (cre->dir == RELAY_DIR_REQUEST) {
2426 relay_session(con);
2427 return;
2428 }
2429
2430 if (rlay->rl_conf.flags & F_TLSINSPECT) {
2431 const uint8_t *servercert;
2432 size_t len;
2433
2434 servercert = tls_peer_cert_chain_pem(con->se_out.tls,
2435 &len);
2436 if (servercert != NULL) {
2437 con->se_in.tlscert = ssl_update_certificate(
2438 servercert, len,
2439 rlay->rl_tls_pkey, rlay->rl_tls_capkey,
2440 rlay->rl_tls_cacertx509,
2441 &con->se_in.tlscert_len);
2442 } else
2443 con->se_in.tlscert = NULL;
2444 if (con->se_in.tlscert == NULL)
2445 relay_close(con,
2446 "could not create certificate", 1);
2447 else
2448 relay_session(con);
2449 return;
2450 }
2451 relay_connected(fd, EV_WRITE, con);
2452 return;
2453 } else if (ret == TLS_WANT_POLLIN) {
2454 retry_flag = EV_READ;
2455 } else if (ret == TLS_WANT_POLLOUT) {
2456 retry_flag = EV_WRITE;
2457 } else {
2458 if (asprintf(&msg, "TLS handshake error: %s",
2459 tls_error(cre->tls)) >= 0) {
2460 relay_close(con, msg, 1);
2461 free(msg);
2462 } else {
2463 relay_close(con, "TLS handshake error", 1);
2464 }
2465 return;
2466 }
2467
2468 DPRINTF("%s: session %d: scheduling on %s", __func__, con->se_id,
2469 (retry_flag == EV_READ) ? "EV_READ" : "EV_WRITE");
2470 event_again(&con->se_ev, fd, EV_TIMEOUT|retry_flag, relay_tls_handshake,
2471 &con->se_tv_start, &rlay->rl_conf.timeout, cre);
2472 }
2473
2474 void
relay_tls_connected(struct ctl_relay_event * cre)2475 relay_tls_connected(struct ctl_relay_event *cre)
2476 {
2477 /*
2478 * Hack libevent - we overwrite the internal bufferevent I/O
2479 * functions to handle the TLS abstraction.
2480 */
2481 event_del(&cre->bev->ev_read);
2482 event_del(&cre->bev->ev_write);
2483
2484 event_set(&cre->bev->ev_read, cre->s, EV_READ,
2485 relay_tls_readcb, cre->bev);
2486 event_set(&cre->bev->ev_write, cre->s, EV_WRITE,
2487 relay_tls_writecb, cre->bev);
2488 }
2489
2490 void
relay_tls_readcb(int fd,short event,void * arg)2491 relay_tls_readcb(int fd, short event, void *arg)
2492 {
2493 char rbuf[IBUF_READ_SIZE];
2494 struct bufferevent *bufev = arg;
2495 struct ctl_relay_event *cre = bufev->cbarg;
2496 short what = EVBUFFER_READ;
2497 int howmuch = IBUF_READ_SIZE;
2498 ssize_t ret;
2499 size_t len;
2500
2501 if (event == EV_TIMEOUT) {
2502 what |= EVBUFFER_TIMEOUT;
2503 goto err;
2504 }
2505
2506 if (bufev->wm_read.high != 0)
2507 howmuch = MINIMUM(sizeof(rbuf), bufev->wm_read.high);
2508
2509 ret = tls_read(cre->tls, rbuf, howmuch);
2510 if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) {
2511 goto retry;
2512 } else if (ret == -1) {
2513 what |= EVBUFFER_ERROR;
2514 goto err;
2515 }
2516 len = ret;
2517
2518 if (len == 0) {
2519 what |= EVBUFFER_EOF;
2520 goto err;
2521 }
2522
2523 if (evbuffer_add(bufev->input, rbuf, ret) == -1) {
2524 what |= EVBUFFER_ERROR;
2525 goto err;
2526 }
2527
2528 relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
2529
2530 len = EVBUFFER_LENGTH(bufev->input);
2531 if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
2532 return;
2533 if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
2534 struct evbuffer *buf = bufev->input;
2535 event_del(&bufev->ev_read);
2536 evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
2537 return;
2538 }
2539
2540 if (bufev->readcb != NULL)
2541 (*bufev->readcb)(bufev, bufev->cbarg);
2542 return;
2543
2544 retry:
2545 relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
2546 return;
2547
2548 err:
2549 (*bufev->errorcb)(bufev, what, bufev->cbarg);
2550 }
2551
2552 void
relay_tls_writecb(int fd,short event,void * arg)2553 relay_tls_writecb(int fd, short event, void *arg)
2554 {
2555 struct bufferevent *bufev = arg;
2556 struct ctl_relay_event *cre = bufev->cbarg;
2557 ssize_t ret;
2558 size_t len;
2559 short what = EVBUFFER_WRITE;
2560
2561 if (event == EV_TIMEOUT) {
2562 what |= EVBUFFER_TIMEOUT;
2563 goto err;
2564 }
2565
2566 if (EVBUFFER_LENGTH(bufev->output)) {
2567 ret = tls_write(cre->tls, EVBUFFER_DATA(bufev->output),
2568 EVBUFFER_LENGTH(bufev->output));
2569 if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) {
2570 goto retry;
2571 } else if (ret == -1) {
2572 what |= EVBUFFER_ERROR;
2573 goto err;
2574 }
2575 len = ret;
2576 evbuffer_drain(bufev->output, len);
2577 }
2578
2579 if (EVBUFFER_LENGTH(bufev->output) != 0)
2580 relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
2581
2582 if (bufev->writecb != NULL &&
2583 EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
2584 (*bufev->writecb)(bufev, bufev->cbarg);
2585 return;
2586
2587 retry:
2588 relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
2589 return;
2590
2591 err:
2592 (*bufev->errorcb)(bufev, what, bufev->cbarg);
2593 }
2594
2595 int
relay_bufferevent_add(struct event * ev,int timeout)2596 relay_bufferevent_add(struct event *ev, int timeout)
2597 {
2598 struct timeval tv, *ptv = NULL;
2599
2600 if (timeout) {
2601 timerclear(&tv);
2602 tv.tv_sec = timeout;
2603 ptv = &tv;
2604 }
2605
2606 return (event_add(ev, ptv));
2607 }
2608
2609 #ifdef notyet
2610 int
relay_bufferevent_printf(struct ctl_relay_event * cre,const char * fmt,...)2611 relay_bufferevent_printf(struct ctl_relay_event *cre, const char *fmt, ...)
2612 {
2613 int ret;
2614 va_list ap;
2615
2616 va_start(ap, fmt);
2617 ret = evbuffer_add_vprintf(cre->output, fmt, ap);
2618 va_end(ap);
2619
2620 if (cre->bev != NULL &&
2621 ret != -1 && EVBUFFER_LENGTH(cre->output) > 0 &&
2622 (cre->bev->enabled & EV_WRITE))
2623 bufferevent_enable(cre->bev, EV_WRITE);
2624
2625 return (ret);
2626 }
2627 #endif
2628
2629 int
relay_bufferevent_print(struct ctl_relay_event * cre,const char * str)2630 relay_bufferevent_print(struct ctl_relay_event *cre, const char *str)
2631 {
2632 if (cre->bev == NULL)
2633 return (evbuffer_add(cre->output, str, strlen(str)));
2634 return (bufferevent_write(cre->bev, str, strlen(str)));
2635 }
2636
2637 int
relay_bufferevent_write_buffer(struct ctl_relay_event * cre,struct evbuffer * buf)2638 relay_bufferevent_write_buffer(struct ctl_relay_event *cre,
2639 struct evbuffer *buf)
2640 {
2641 if (cre->bev == NULL)
2642 return (evbuffer_add_buffer(cre->output, buf));
2643 return (bufferevent_write_buffer(cre->bev, buf));
2644 }
2645
2646 int
relay_bufferevent_write_chunk(struct ctl_relay_event * cre,struct evbuffer * buf,size_t size)2647 relay_bufferevent_write_chunk(struct ctl_relay_event *cre,
2648 struct evbuffer *buf, size_t size)
2649 {
2650 int ret;
2651 ret = relay_bufferevent_write(cre, EVBUFFER_DATA(buf), size);
2652 if (ret != -1)
2653 evbuffer_drain(buf, size);
2654 return (ret);
2655 }
2656
2657 int
relay_bufferevent_write(struct ctl_relay_event * cre,void * data,size_t size)2658 relay_bufferevent_write(struct ctl_relay_event *cre, void *data, size_t size)
2659 {
2660 if (cre->bev == NULL)
2661 return (evbuffer_add(cre->output, data, size));
2662 return (bufferevent_write(cre->bev, data, size));
2663 }
2664
2665 int
relay_cmp_af(struct sockaddr_storage * a,struct sockaddr_storage * b)2666 relay_cmp_af(struct sockaddr_storage *a, struct sockaddr_storage *b)
2667 {
2668 int ret = -1;
2669 struct sockaddr_in ia, ib;
2670 struct sockaddr_in6 ia6, ib6;
2671
2672 switch (a->ss_family) {
2673 case AF_INET:
2674 bcopy(a, &ia, sizeof(struct sockaddr_in));
2675 bcopy(b, &ib, sizeof(struct sockaddr_in));
2676
2677 ret = memcmp(&ia.sin_addr, &ib.sin_addr,
2678 sizeof(ia.sin_addr));
2679 if (ret == 0)
2680 ret = memcmp(&ia.sin_port, &ib.sin_port,
2681 sizeof(ia.sin_port));
2682 break;
2683 case AF_INET6:
2684 bcopy(a, &ia6, sizeof(struct sockaddr_in6));
2685 bcopy(b, &ib6, sizeof(struct sockaddr_in6));
2686
2687 ret = memcmp(&ia6.sin6_addr, &ib6.sin6_addr,
2688 sizeof(ia6.sin6_addr));
2689 if (ret == 0)
2690 ret = memcmp(&ia6.sin6_port, &ib6.sin6_port,
2691 sizeof(ia6.sin6_port));
2692 break;
2693 default:
2694 break;
2695 }
2696
2697 return (ret);
2698 }
2699
2700 int
relay_session_cmp(struct rsession * a,struct rsession * b)2701 relay_session_cmp(struct rsession *a, struct rsession *b)
2702 {
2703 struct relay *rlay = b->se_relay;
2704 struct protocol *proto = rlay->rl_proto;
2705
2706 if (proto != NULL && proto->cmp != NULL)
2707 return ((*proto->cmp)(a, b));
2708
2709 return ((int)a->se_id - b->se_id);
2710 }
2711
2712 void
relay_log(struct rsession * con,char * msg)2713 relay_log(struct rsession *con, char *msg)
2714 {
2715 if (con->se_haslog && con->se_log != NULL) {
2716 evbuffer_add(con->se_log, msg, strlen(msg));
2717 }
2718 }
2719
2720 SPLAY_GENERATE(session_tree, rsession, se_nodes, relay_session_cmp);
2721