From 0dc0e0156836bf17f1f760e78ce8a95e43068aa4 Mon Sep 17 00:00:00 2001 From: Jean-Louis Dupond Date: Fri, 17 Oct 2014 12:08:39 +0200 Subject: [PATCH] Add ipv6 client support --- client/common/cmdline.c | 40 ++++++++++++++++++++++++++--------- libfreerdp/core/tcp.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 02db02e..f1f9640 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1200,19 +1200,39 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, CommandLineSwitchCase(arg, "v") { - p = strchr(arg->Value, ':'); - - if (p) + p = strchr(arg->Value, '['); + /* ipv4 */ + if (!p) { - length = (int) (p - arg->Value); - settings->ServerPort = atoi(&p[1]); - settings->ServerHostname = (char*) malloc(length + 1); - strncpy(settings->ServerHostname, arg->Value, length); - settings->ServerHostname[length] = '\0'; + p = strchr(arg->Value, ':'); + if (p) + { + length = (int) (p - arg->Value); + settings->ServerPort = atoi(&p[1]); + settings->ServerHostname = (char*) malloc(length + 1); + strncpy(settings->ServerHostname, arg->Value, length); + settings->ServerHostname[length] = '\0'; + } + else + { + settings->ServerHostname = _strdup(arg->Value); + } } - else + else /* ipv6 */ { - settings->ServerHostname = _strdup(arg->Value); + char *p2 = strchr(arg->Value, ']'); + /* not a valid [] ipv6 addr found */ + if (!p2) + continue; + + length = p2 - p; + settings->ServerHostname = (char*) malloc(length); + strncpy(settings->ServerHostname, p+1, length-1); + if (*(p2 + 1) == ':') + { + settings->ServerPort = atoi(&p2[2]); + } + printf("hostname %s port %d\n", settings->ServerHostname, settings->ServerPort); } } CommandLineSwitchCase(arg, "spn-class") diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index faf1cec..24e3933 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include #ifdef HAVE_POLL_H #include @@ -523,6 +525,7 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) struct timeval tv; #endif +#ifdef NO_IPV6 tcp->socketBio = BIO_new(BIO_s_connect()); if (!tcp->socketBio) @@ -542,6 +545,58 @@ BOOL tcp_connect(rdpTcp* tcp, const char* hostname, int port, int timeout) if (tcp->sockfd < 0) return FALSE; +#else /* NO_IPV6 */ + struct addrinfo hints = {0}; + struct addrinfo *result; + struct addrinfo *tmp; + char port_str[11]; + + //ZeroMemory(&hints, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_STREAM; + /* + * FIXME: the following is a nasty workaround. Find a cleaner way: + * Either set port manually afterwards or get it passed as string? + */ + snprintf(port_str, 11, "%u", port); + + status = getaddrinfo(hostname, port_str, &hints, &result); + if (status) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status)); + return FALSE; + } + + /* For now prefer IPv4 over IPv6. */ + tmp = result; + if (tmp->ai_family == AF_INET6 && tmp->ai_next != 0) + { + while ((tmp = tmp->ai_next)) + { + if (tmp->ai_family == AF_INET) + break; + } + if (!tmp) + tmp = result; + } + tcp->sockfd = socket(tmp->ai_family, tmp->ai_socktype, tmp->ai_protocol); + + if (tcp->sockfd < 0) { + freeaddrinfo(result); + return FALSE; + } + + if (connect(tcp->sockfd, tmp->ai_addr, tmp->ai_addrlen) < 0) { + fprintf(stderr, "connect: %s\n", strerror(errno)); + freeaddrinfo(result); + return FALSE; + } + freeaddrinfo(result); + tcp->socketBio = BIO_new_socket(tcp->sockfd, BIO_NOCLOSE); + + /* TODO: make sure the handshake is done by querying the bio */ + // if (BIO_should_retry(tcp->socketBio)) + // return FALSE; +#endif /* NO_IPV6 */ if (status <= 0) { -- 2.7.4