40
#include "session_fixture.h"
41
#include "openssh_fixture.h"
43
#ifdef HAVE_SYS_SOCKET_H
44
#include <sys/socket.h>
49
#ifdef HAVE_ARPA_INET_H
52
#ifdef HAVE_NETINET_IN_H
53
#include <netinet/in.h>
61
#if defined(_WIN32) && defined(_WIN64)
62
#define LIBSSH2_SOCKET_MASK "%lld"
64
#define LIBSSH2_SOCKET_MASK "%d"
67
#ifdef LIBSSH2_WINDOWS_UWP
68
#define popen(x, y) (NULL)
75
static int have_docker = 0;
77
int openssh_fixture_have_docker(void)
82
static int run_command_varg(char **output, const char *command, va_list args)
85
static int run_command_varg(char **output, const char *command, va_list args)
87
static const char redirect_stderr[] = "%s 2>&1";
90
char command_buf[BUFSIZ];
91
char buf[BUFSIZ + sizeof(redirect_stderr)];
100
ret = vsnprintf(command_buf, sizeof(command_buf), command, args);
101
if(ret < 0 || ret >= BUFSIZ) {
102
fprintf(stderr, "Unable to format command (%s)\n", command);
107
if(strlen(command_buf) + strlen(redirect_stderr) >= sizeof(buf)) {
108
fprintf(stderr, "Unable to rewrite command (%s)\n", command);
112
ret = snprintf(buf, sizeof(buf), redirect_stderr, command_buf);
113
if(ret < 0 || ret >= BUFSIZ) {
114
fprintf(stderr, "Unable to rewrite command (%s)\n", command);
118
fprintf(stdout, "Command: %s\n", command_buf);
119
pipe = popen(buf, "r");
121
fprintf(stderr, "Unable to execute command '%s'\n", command);
126
while(buf_len < (sizeof(buf) - 1) &&
127
fgets(&buf[buf_len], (int)(sizeof(buf) - buf_len), pipe)) {
128
buf_len = strlen(buf);
133
fprintf(stderr, "Error running command '%s' (exit %d): %s\n",
140
size_t end = strlen(buf);
141
while(end > 0 && isspace((int)buf[end - 1])) {
145
*output = strdup(buf);
150
static int run_command(char **output, const char *command, ...)
151
LIBSSH2_PRINTF(2, 3);
153
static int run_command(char **output, const char *command, ...)
158
va_start(args, command);
159
ret = run_command_varg(output, command, args);
165
static const char *openssh_server_image(void)
167
return getenv("OPENSSH_SERVER_IMAGE");
170
static int build_openssh_server_docker_image(void)
173
const char *container_image_name = openssh_server_image();
174
if(container_image_name) {
175
int ret = run_command(NULL, "docker pull %s",
176
container_image_name);
178
ret = run_command(NULL, "docker tag %s libssh2/openssh_server",
179
container_image_name);
185
return run_command(NULL,
186
"docker build --quiet -t libssh2/openssh_server %s",
187
srcdir_path("openssh_server"));
194
static const char *openssh_server_port(void)
196
return getenv("OPENSSH_SERVER_PORT");
199
static int start_openssh_server(char **container_id_out)
202
const char *container_host_port = openssh_server_port();
203
if(container_host_port) {
204
return run_command(container_id_out,
205
"docker run --rm -d -p %s:22 "
206
"libssh2/openssh_server",
207
container_host_port);
210
return run_command(container_id_out,
211
"docker run --rm -d -p 22 "
212
"libssh2/openssh_server");
215
*container_id_out = strdup("");
220
static int stop_openssh_server(char *container_id)
223
return run_command(NULL, "docker stop %s", container_id);
230
static const char *docker_machine_name(void)
232
return getenv("DOCKER_MACHINE_NAME");
235
static int is_running_inside_a_container(void)
240
const char *cgroup_filename = "/proc/self/cgroup";
246
f = fopen(cgroup_filename, "r");
251
while((read = getline(&line, &len, f)) != -1) {
252
if(strstr(line, "docker")) {
263
static void portable_sleep(unsigned int seconds)
272
static int ip_address_from_container(char *container_id, char **ip_address_out)
274
const char *active_docker_machine = docker_machine_name();
275
if(active_docker_machine) {
281
unsigned int wait_time = 500;
283
int ret = run_command(ip_address_out, "docker-machine ip %s",
284
active_docker_machine);
288
else if(attempt_no > 5) {
291
"Unable to get IP from docker-machine after %d attempts\n",
296
portable_sleep(wait_time);
303
if(is_running_inside_a_container()) {
304
return run_command(ip_address_out,
305
"docker inspect --format "
306
"\"{{ .NetworkSettings.IPAddress }}\""
311
return run_command(ip_address_out,
312
"docker inspect --format "
313
"\"{{ index (index (index "
314
".NetworkSettings.Ports "
315
"\\\"22/tcp\\\") 0) \\\"HostIp\\\" }}\" %s",
321
static int port_from_container(char *container_id, char **port_out)
323
if(is_running_inside_a_container()) {
324
*port_out = strdup("22");
328
return run_command(port_out,
329
"docker inspect --format "
330
"\"{{ index (index (index .NetworkSettings.Ports "
331
"\\\"22/tcp\\\") 0) \\\"HostPort\\\" }}\" %s",
336
static libssh2_socket_t open_socket_to_container(char *container_id)
338
char *ip_address = NULL;
339
char *port_string = NULL;
341
libssh2_socket_t sock;
342
struct sockaddr_in sin;
343
unsigned int counter;
344
libssh2_socket_t ret = LIBSSH2_INVALID_SOCKET;
348
res = ip_address_from_container(container_id, &ip_address);
350
fprintf(stderr, "Failed to get IP address for container %s\n",
355
res = port_from_container(container_id, &port_string);
357
fprintf(stderr, "Failed to get port for container %s\n",
364
env = getenv("OPENSSH_SERVER_HOST");
368
ip_address = strdup(env);
369
env = openssh_server_port();
373
port_string = strdup(env);
379
if(ip_address && strcmp(ip_address, "0.0.0.0") == 0) {
381
ip_address = strdup("127.0.0.1");
384
hostaddr = inet_addr(ip_address);
385
if(hostaddr == (uint32_t)(-1)) {
386
fprintf(stderr, "Failed to convert %s host address\n", ip_address);
390
sock = socket(AF_INET, SOCK_STREAM, 0);
391
if(sock == LIBSSH2_INVALID_SOCKET) {
393
"Failed to open socket (" LIBSSH2_SOCKET_MASK ")\n", sock);
397
sin.sin_family = AF_INET;
398
sin.sin_port = htons((unsigned short)strtol(port_string, NULL, 0));
399
sin.sin_addr.s_addr = hostaddr;
401
for(counter = 0; counter < 3; ++counter) {
402
if(connect(sock, (struct sockaddr*)(&sin),
403
sizeof(struct sockaddr_in))) {
405
"Connection to %s:%s attempt #%d failed: retrying...\n",
406
ip_address, port_string, counter);
407
portable_sleep(1 + 2*counter);
414
if(ret == LIBSSH2_INVALID_SOCKET) {
415
fprintf(stderr, "Failed to connect to %s:%s\n",
416
ip_address, port_string);
427
static void close_socket_to_container(libssh2_socket_t sock)
429
if(sock != LIBSSH2_INVALID_SOCKET) {
439
static char *running_container_id = NULL;
441
int start_openssh_fixture(void)
447
ret = WSAStartup(MAKEWORD(2, 0), &wsadata);
449
fprintf(stderr, "WSAStartup failed with error: %d\n", ret);
454
have_docker = !getenv("OPENSSH_NO_DOCKER");
456
ret = build_openssh_server_docker_image();
458
return start_openssh_server(&running_container_id);
461
fprintf(stderr, "Failed to build docker image\n");
466
void stop_openssh_fixture(void)
468
if(running_container_id) {
469
stop_openssh_server(running_container_id);
470
free(running_container_id);
471
running_container_id = NULL;
473
else if(have_docker) {
474
fprintf(stderr, "Cannot stop container - none started\n");
482
libssh2_socket_t open_socket_to_openssh_server(void)
484
return open_socket_to_container(running_container_id);
487
void close_socket_to_openssh_server(libssh2_socket_t sock)
489
close_socket_to_container(sock);