mirror of
https://github.com/tmate-io/tmate-ssh-server.git
synced 2020-11-18 19:53:51 -08:00
124 lines
3.0 KiB
C
124 lines
3.0 KiB
C
#include <sys/socket.h>
|
|
#include <netinet/tcp.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "tmate.h"
|
|
#include "tmate-protocol.h"
|
|
|
|
static void ctl_daemon_fwd_msg(struct tmate_session *session,
|
|
struct tmate_unpacker *uk)
|
|
{
|
|
if (uk->argc != 1)
|
|
tmate_decoder_error();
|
|
tmate_send_mc_obj(&uk->argv[0]);
|
|
}
|
|
|
|
void tmate_dispatch_master_message(struct tmate_session *session,
|
|
struct tmate_unpacker *uk)
|
|
{
|
|
int cmd = unpack_int(uk);
|
|
switch (cmd) {
|
|
#define dispatch(c, f) case c: f(session, uk); break
|
|
dispatch(TMATE_CTL_DEAMON_FWD_MSG, ctl_daemon_fwd_msg);
|
|
default: tmate_fatal("Bad master message type: %d", cmd);
|
|
}
|
|
}
|
|
|
|
#define pack(what, ...) _pack(&tmate_session->master_encoder, what, __VA_ARGS__)
|
|
|
|
void tmate_send_master_daemon_msg(struct tmate_session *session,
|
|
struct tmate_unpacker *uk)
|
|
{
|
|
struct timespec time_diff, current_time;
|
|
int i;
|
|
|
|
if (!tmate_has_master())
|
|
return;
|
|
|
|
pack(array, 2);
|
|
pack(int, TMATE_CTL_DEAMON_OUT_MSG);
|
|
|
|
pack(array, uk->argc);
|
|
for (i = 0; i < uk->argc; i++)
|
|
pack(object, uk->argv[i]);
|
|
}
|
|
|
|
void tmate_send_master_header(struct tmate_session *session)
|
|
{
|
|
if (!tmate_has_master())
|
|
return;
|
|
|
|
pack(array, 6);
|
|
pack(int, TMATE_CTL_AUTH);
|
|
pack(int, CONTROL_PROTOCOL_VERSION);
|
|
pack(string, session->ssh_client.ip_address);
|
|
pack(string, session->ssh_client.pubkey);
|
|
pack(string, session->session_token);
|
|
pack(string, session->session_token_ro);
|
|
}
|
|
|
|
void tmate_init_master_session(struct tmate_session *session)
|
|
{
|
|
if (!tmate_has_master())
|
|
return;
|
|
|
|
/* Further init */
|
|
}
|
|
|
|
static int _tmate_connect_to_master(const char *hostname, int port)
|
|
{
|
|
int sockfd = -1;
|
|
struct sockaddr_in servaddr;
|
|
struct hostent *host;
|
|
|
|
sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (sockfd < 0)
|
|
tmate_fatal("Cannot create socket");
|
|
|
|
host = gethostbyname(hostname);
|
|
if (!host)
|
|
tmate_fatal("Cannot resolve %s", hostname);
|
|
|
|
memset(&servaddr, 0, sizeof(servaddr));
|
|
servaddr.sin_family = host->h_addrtype;
|
|
memcpy(&servaddr.sin_addr, host->h_addr, host->h_length);
|
|
servaddr.sin_port = htons(port);
|
|
|
|
if (connect(sockfd, &servaddr, sizeof(servaddr)) < 0)
|
|
tmate_fatal("Cannot connect to master at %s:%d", hostname, port);
|
|
|
|
int flag = 1;
|
|
if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)) < 0)
|
|
tmate_fatal("Can't set master socket to TCP_NODELAY");
|
|
|
|
if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0)
|
|
tmate_fatal("Can't set master socket to non-blocking");
|
|
|
|
tmate_notice("Connected to master at %s:%d", hostname, port);
|
|
|
|
return sockfd;
|
|
}
|
|
|
|
int tmate_connect_to_master(void)
|
|
{
|
|
return _tmate_connect_to_master(tmate_settings->master_hostname,
|
|
tmate_settings->master_port);
|
|
}
|
|
|
|
void timespec_subtract(struct timespec *result,
|
|
struct timespec *x, struct timespec *y)
|
|
{
|
|
if (x->tv_nsec < y->tv_nsec) {
|
|
result->tv_sec = x->tv_sec - y->tv_sec - 1;
|
|
result->tv_nsec = x->tv_nsec - y->tv_nsec + 1000000000;
|
|
} else {
|
|
result->tv_sec = x->tv_sec - y->tv_sec;
|
|
result->tv_nsec = x->tv_nsec - y->tv_nsec;
|
|
}
|
|
}
|
|
|
|
unsigned long long timespec_to_millisec(struct timespec *ts)
|
|
{
|
|
return ts->tv_sec * 1000ULL + ts->tv_nsec / 1000000ULL;
|
|
}
|