1
0
mirror of https://github.com/tmate-io/tmate-ssh-server.git synced 2020-11-18 19:53:51 -08:00
tmate-ssh-server/tmate-master.c
2015-09-22 15:13:54 -04:00

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;
}