diff --git a/src/protocols/ssh/client.c b/src/protocols/ssh/client.c index bfa90e01..be8492c5 100644 --- a/src/protocols/ssh/client.c +++ b/src/protocols/ssh/client.c @@ -55,7 +55,7 @@ #define GUAC_SSH_DEFAULT_FONT_NAME "monospace" #define GUAC_SSH_DEFAULT_FONT_SIZE 12 -#define GUAC_SSH_DEFAULT_PORT 22 +#define GUAC_SSH_DEFAULT_PORT "22" /* Client plugin arguments */ const char* GUAC_CLIENT_ARGS[] = { @@ -170,9 +170,9 @@ int guac_client_init(guac_client* client, int argc, char** argv) { /* Read port */ if (argv[IDX_PORT][0] != 0) - client_data->port = atoi(argv[IDX_PORT]); + strcpy(client_data->port, argv[IDX_PORT]); else - client_data->port = GUAC_SSH_DEFAULT_PORT; + strcpy(client_data->port, GUAC_SSH_DEFAULT_PORT); /* Create terminal */ client_data->term = guac_terminal_create(client, diff --git a/src/protocols/ssh/client.h b/src/protocols/ssh/client.h index 560c5e28..b53cad1f 100644 --- a/src/protocols/ssh/client.h +++ b/src/protocols/ssh/client.h @@ -61,7 +61,7 @@ typedef struct ssh_guac_client_data { /** * The port of the SSH server to connect to. */ - int port; + char port[64]; /** * The name of the user to login as. diff --git a/src/protocols/ssh/ssh_client.c b/src/protocols/ssh/ssh_client.c index 395bc25b..2dd6748e 100644 --- a/src/protocols/ssh/ssh_client.c +++ b/src/protocols/ssh/ssh_client.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -136,23 +137,77 @@ void* ssh_input_thread(void* data) { static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client) { + int retval; + int fd; - struct sockaddr_in addr; + struct addrinfo* addresses; + struct addrinfo* current_address; + + char connected_address[1024]; + char connected_port[64]; ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP + }; + /* Get socket */ fd = socket(AF_INET, SOCK_STREAM, 0); - /* Connect to SSH server */ - addr.sin_family = AF_INET; - addr.sin_port = htons(22); - addr.sin_addr.s_addr = htonl(0x0A0000C0); /* proto-test: 10.0.0.192 */ + /* Get addresses connection */ + if ((retval = getaddrinfo(client_data->hostname, client_data->port, + &hints, &addresses))) { - /* Connect */ - if (connect(fd, (struct sockaddr*)(&addr), - sizeof(struct sockaddr_in)) != 0) { - guac_client_log_error(client, "Connection failed: %s", strerror(errno)); + guac_client_log_error(client, + "Error parsing given address or port: %s", + gai_strerror(retval)); + return NULL; + + } + + /* Attempt connection to each address until success */ + current_address = addresses; + while (current_address != NULL) { + + int retval; + + /* Resolve hostname */ + if ((retval = getnameinfo(current_address->ai_addr, + current_address->ai_addrlen, + connected_address, sizeof(connected_address), + connected_port, sizeof(connected_port), + NI_NUMERICHOST | NI_NUMERICSERV))) + guac_client_log_error(client, "Unable to resolve host: %s", + gai_strerror(retval)); + + /* Connect */ + if (connect(fd, current_address->ai_addr, + current_address->ai_addrlen) == 0) { + + guac_client_log_info(client, "Successfully connected to " + "host %s, port %s", connected_address, connected_port); + + /* Done if successful connect */ + break; + + } + + /* Otherwise log information regarding bind failure */ + else + guac_client_log_info(client, "Unable to connect to " + "host %s, port %s: %s", + connected_address, connected_port, strerror(errno)); + + current_address = current_address->ai_next; + + } + + /* If unable to connect to anything, fail */ + if (current_address == NULL) { + guac_client_log_error(client, "Unable to connect to any addresses."); return NULL; }