2013-07-22 23:06:28 +02:00
|
|
|
#include <event2/dns.h>
|
|
|
|
#include <event2/util.h>
|
|
|
|
#include <event2/event.h>
|
|
|
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "tmate.h"
|
|
|
|
|
|
|
|
#define TMATE_DNS_RETRY_TIMEOUT 10
|
|
|
|
|
|
|
|
struct tmate_session tmate_session;
|
|
|
|
|
|
|
|
static void lookup_and_connect(void);
|
|
|
|
|
2015-12-23 11:41:41 +01:00
|
|
|
static void on_dns_retry(__unused evutil_socket_t fd, __unused short what,
|
|
|
|
__unused void *arg)
|
2013-07-22 23:06:28 +02:00
|
|
|
{
|
|
|
|
lookup_and_connect();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dns_cb(int errcode, struct evutil_addrinfo *addr, void *ptr)
|
|
|
|
{
|
|
|
|
struct evutil_addrinfo *ai;
|
|
|
|
struct timeval tv;
|
2013-10-04 23:36:46 +02:00
|
|
|
const char *host = ptr;
|
2013-07-22 23:06:28 +02:00
|
|
|
|
|
|
|
if (errcode) {
|
|
|
|
tmate_status_message("%s lookup failure. Retrying in %d seconds (%s)",
|
2013-10-04 23:36:46 +02:00
|
|
|
host, TMATE_DNS_RETRY_TIMEOUT,
|
2013-07-22 23:06:28 +02:00
|
|
|
evutil_gai_strerror(errcode));
|
|
|
|
|
|
|
|
tv.tv_sec = TMATE_DNS_RETRY_TIMEOUT;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
|
2015-12-23 11:41:41 +01:00
|
|
|
evtimer_assign(&tmate_session.ev_dns_retry, tmate_session.ev_base,
|
|
|
|
on_dns_retry, NULL);
|
|
|
|
evtimer_add(&tmate_session.ev_dns_retry, &tv);
|
2013-07-22 23:06:28 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-04 23:36:46 +02:00
|
|
|
tmate_status_message("Connecting to %s...", host);
|
2013-07-22 23:06:28 +02:00
|
|
|
|
|
|
|
for (ai = addr; ai; ai = ai->ai_next) {
|
|
|
|
char buf[128];
|
|
|
|
const char *ip = NULL;
|
|
|
|
if (ai->ai_family == AF_INET) {
|
|
|
|
struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
|
|
|
|
ip = evutil_inet_ntop(AF_INET, &sin->sin_addr, buf, 128);
|
|
|
|
} else if (ai->ai_family == AF_INET6) {
|
|
|
|
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
|
|
|
|
ip = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf, 128);
|
|
|
|
}
|
|
|
|
|
|
|
|
tmate_debug("Trying server %s", ip);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note: We don't deal with the client list. Clients manage it
|
|
|
|
* and free client structs when necessary.
|
|
|
|
*/
|
|
|
|
(void)tmate_ssh_client_alloc(&tmate_session, ip);
|
|
|
|
}
|
|
|
|
|
|
|
|
evutil_freeaddrinfo(addr);
|
|
|
|
|
2013-08-13 21:41:41 +02:00
|
|
|
/*
|
|
|
|
* XXX For some reason, freeing the DNS resolver makes MacOSX flip out...
|
|
|
|
* not sure what's going on...
|
2015-12-23 11:41:41 +01:00
|
|
|
* evdns_base_free(tmate_session.ev_dnsbase, 0);
|
|
|
|
* tmate_session.ev_dnsbase = NULL;
|
2013-08-13 21:41:41 +02:00
|
|
|
*/
|
2013-07-22 23:06:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void lookup_and_connect(void)
|
|
|
|
{
|
|
|
|
struct evutil_addrinfo hints;
|
2013-10-04 23:36:46 +02:00
|
|
|
const char *tmate_server_host;
|
2013-07-22 23:06:28 +02:00
|
|
|
|
2015-12-23 11:41:41 +01:00
|
|
|
if (!tmate_session.ev_dnsbase)
|
|
|
|
tmate_session.ev_dnsbase = evdns_base_new(tmate_session.ev_base, 1);
|
|
|
|
if (!tmate_session.ev_dnsbase)
|
2013-07-22 23:06:28 +02:00
|
|
|
tmate_fatal("Cannot initialize the DNS lookup service");
|
|
|
|
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_family = AF_UNSPEC;
|
|
|
|
hints.ai_flags = 0;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
hints.ai_protocol = IPPROTO_TCP;
|
|
|
|
|
2015-12-23 11:41:41 +01:00
|
|
|
tmate_server_host = options_get_string(global_s_options,
|
2013-10-04 23:36:46 +02:00
|
|
|
"tmate-server-host");
|
|
|
|
tmate_info("Looking up %s...", tmate_server_host);
|
2015-12-23 11:41:41 +01:00
|
|
|
(void)evdns_getaddrinfo(tmate_session.ev_dnsbase, tmate_server_host, NULL,
|
|
|
|
&hints, dns_cb, (void *)tmate_server_host);
|
2013-07-22 23:06:28 +02:00
|
|
|
}
|
|
|
|
|
2013-11-07 01:07:47 +01:00
|
|
|
static void ssh_log_function(int priority, const char *function,
|
2015-12-23 11:41:41 +01:00
|
|
|
const char *buffer, __unused void *userdata)
|
2013-11-07 01:07:47 +01:00
|
|
|
{
|
|
|
|
tmate_debug("[%d] [%s] %s", priority, function, buffer);
|
|
|
|
}
|
|
|
|
|
2015-12-23 11:41:41 +01:00
|
|
|
void tmate_session_init(struct event_base *base)
|
2013-07-22 23:06:28 +02:00
|
|
|
{
|
2015-12-23 11:41:41 +01:00
|
|
|
tmate_session.ev_base = base;
|
|
|
|
|
2013-11-07 01:07:47 +01:00
|
|
|
ssh_set_log_callback(ssh_log_function);
|
2013-07-22 23:06:28 +02:00
|
|
|
|
|
|
|
tmate_encoder_init(&tmate_session.encoder);
|
|
|
|
tmate_decoder_init(&tmate_session.decoder);
|
|
|
|
|
2013-07-23 01:45:34 +02:00
|
|
|
TAILQ_INIT(&tmate_session.clients);
|
|
|
|
|
|
|
|
tmate_session.need_passphrase = 0;
|
|
|
|
tmate_session.passphrase = NULL;
|
|
|
|
|
2013-07-22 23:06:28 +02:00
|
|
|
/* The header will be written as soon as the first client connects */
|
|
|
|
tmate_write_header();
|
|
|
|
}
|
2013-07-23 00:05:44 +02:00
|
|
|
|
|
|
|
void tmate_session_start(void)
|
|
|
|
{
|
|
|
|
/* We split init and start because:
|
|
|
|
* - We need to process the tmux config file during the connection as
|
|
|
|
* we are setting up the tmate identity.
|
|
|
|
* - While we are parsing the config file, we need to be able to
|
|
|
|
* serialize it, and so we need a worker encoder.
|
|
|
|
*/
|
|
|
|
lookup_and_connect();
|
|
|
|
}
|