Skip to content

Commit

Permalink
Fix FreeRDP#4281: Added option to prefer IPv6 over IPv4
Browse files Browse the repository at this point in the history
  • Loading branch information
akallabeth committed Nov 27, 2017
1 parent 8f8ce70 commit 2cc6429
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 23 deletions.
26 changes: 20 additions & 6 deletions client/common/cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "heartbeat", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support heartbeat PDUs" },
{ "help", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_HELP, NULL, NULL, NULL, -1, "?", "Print help" },
{ "home-drive", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect user home as share" },
{ "ipv6", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "6", "Prefer IPv6 AAA record over IPv4 A record"},
#if defined(WITH_JPEG)
{ "jpeg", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Enable JPEG codec" },
{ "jpeg-quality", COMMAND_LINE_VALUE_REQUIRED, "<percentage>", NULL, NULL, -1, NULL, "JPEG quality" },
Expand Down Expand Up @@ -232,12 +233,12 @@ static void freerdp_client_print_command_line_args(COMMAND_LINE_ARGUMENT_A* arg)
|| (arg->Flags & COMMAND_LINE_VALUE_OPTIONAL))
{
BOOL overlong = FALSE;

printf(" %s", "/");

if (arg->Format)
{
size_t length = (strlen(arg->Name) + strlen(arg->Format) + 2);

if (arg->Flags & COMMAND_LINE_VALUE_OPTIONAL)
length += 2;

Expand Down Expand Up @@ -315,7 +316,6 @@ BOOL freerdp_client_print_command_line_help_ex(int argc, char** argv,
printf("Multimedia Redirection: /multimedia:sys:alsa\n");
printf("USB Device Redirection: /usb:id,dev:054c:0268\n");
printf("\n");

printf("For Gateways, the https_proxy environment variable is respected:\n");
#ifdef _WIN32
printf(" set HTTPS_PROXY=http://proxy.contoso.com:3128/\n");
Expand All @@ -324,7 +324,6 @@ BOOL freerdp_client_print_command_line_help_ex(int argc, char** argv,
#endif
printf(" xfreerdp /g:rdp.contoso.com ...\n");
printf("\n");

printf("More documentation is coming, in the meantime consult source files\n");
printf("\n");
return TRUE;
Expand All @@ -348,7 +347,6 @@ static int freerdp_client_command_line_pre_filter(void* context, int index,
if (!(settings->ConnectionFile = _strdup(argv[index])))
return COMMAND_LINE_ERROR_MEMORY;


return 1;
}
}
Expand All @@ -362,7 +360,6 @@ static int freerdp_client_command_line_pre_filter(void* context, int index,
if (!(settings->AssistanceFile = _strdup(argv[index])))
return COMMAND_LINE_ERROR_MEMORY;


return 1;
}
}
Expand Down Expand Up @@ -1073,6 +1070,7 @@ BOOL freerdp_parse_hostname(char* hostname, char** host, int* port)

if ((errno != 0) || (val <= 0) || (val > UINT16_MAX))
return FALSE;

*host = (char*) calloc(length + 1UL, sizeof(char));

if (!(*host))
Expand Down Expand Up @@ -1495,7 +1493,6 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
else
{

if (allowUnknown)
{
flags |= COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
Expand Down Expand Up @@ -1557,6 +1554,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,

if ((errno != 0) || (val == 0) || (val > UINT16_MAX))
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;

length = (int)(p - arg->Value);
settings->ServerPort = val;

Expand Down Expand Up @@ -1690,6 +1688,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
settings->PercentScreenUseWidth = 1;
partial = TRUE;
}

if (strchr(p, 'h'))
{
settings->PercentScreenUseHeight = 1;
Expand Down Expand Up @@ -1952,6 +1951,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,

if ((errno != 0) || (val == 0) || (val > UINT16_MAX))
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;

length = (int)(p - arg->Value);
settings->GatewayPort = val;

Expand Down Expand Up @@ -2071,6 +2071,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
long type;
char* pEnd;
type = strtol(arg->Value, &pEnd, 10);

if (errno != 0)
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;

Expand Down Expand Up @@ -2167,6 +2168,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
{
settings->RedirectHomeDrive = arg->Value ? TRUE : FALSE;
}
CommandLineSwitchCase(arg, "ipv6")
{
settings->PreferIPv6OverIPv4 = TRUE;
}
CommandLineSwitchCase(arg, "clipboard")
{
settings->RedirectClipboard = arg->Value ? TRUE : FALSE;
Expand Down Expand Up @@ -2211,6 +2216,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
long type;
char* pEnd;
type = strtol(arg->Value, &pEnd, 10);

if (errno != 0)
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;

Expand Down Expand Up @@ -2277,6 +2283,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
if (arg->Value)
{
#ifdef WITH_GFX_H264

if (_strnicmp("AVC444", arg->Value, 6) == 0)
{
settings->GfxH264 = TRUE;
Expand All @@ -2295,8 +2302,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
CommandLineSwitchCase(arg, "gfx-thin-client")
{
settings->GfxThinClient = arg->Value ? TRUE : FALSE;

if (settings->GfxThinClient)
settings->GfxSmallCache = TRUE;

settings->SupportGraphicsPipeline = TRUE;
}
CommandLineSwitchCase(arg, "gfx-small-cache")
Expand Down Expand Up @@ -2385,6 +2394,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,

if ((errno != 0) || (val > UINT32_MAX))
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;

settings->SendPreconnectionPdu = TRUE;
settings->PreconnectionId = val;
}
Expand Down Expand Up @@ -2453,6 +2463,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
CommandLineSwitchCase(arg, "from-stdin")
{
settings->CredentialsFromStdin = TRUE;

if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
{
promptForPassword = (strncmp(arg->Value, "force", 6) == 0);
Expand Down Expand Up @@ -2582,6 +2593,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
{
settings->NSCodec = TRUE;
}

#if defined(WITH_JPEG)
else if (strcmp(arg->Value, "jpeg") == 0)
{
Expand All @@ -2590,6 +2602,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
if (settings->JpegQuality == 0)
settings->JpegQuality = 75;
}

#endif
}
CommandLineSwitchCase(arg, "fast-path")
Expand Down Expand Up @@ -3137,6 +3150,7 @@ BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings)
int count;
count = 1;
p[0] = "echo";

if (!freerdp_client_add_dynamic_channel(settings, count, p))
return FALSE;
}
Expand Down
3 changes: 2 additions & 1 deletion include/freerdp/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,8 @@ struct rdp_settings
/* Serial and Parallel Port Redirection */
ALIGN64 BOOL RedirectSerialPorts; /* 4672 */
ALIGN64 BOOL RedirectParallelPorts; /* 4673 */
UINT64 padding4800[4800 - 4674]; /* 4674 */
ALIGN64 BOOL PreferIPv6OverIPv4; /* 4674 */
UINT64 padding4800[4800 - 4675]; /* 4675 */

/**
* Other Redirection
Expand Down
42 changes: 26 additions & 16 deletions libfreerdp/core/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,26 +664,37 @@ BIO_METHOD* BIO_s_buffered_socket(void)
return bio_methods;
}

char* freerdp_tcp_get_ip_address(int sockfd)
static char* freerdp_tcp_get_ip_address(int sockfd, BOOL* pIPv6)
{
BYTE* ip;
socklen_t length;
char ipAddress[32];
char ipAddress[INET6_ADDRSTRLEN + 1];
struct sockaddr_in sockaddr;
length = sizeof(sockaddr);
ZeroMemory(&sockaddr, length);

if (getsockname(sockfd, (struct sockaddr*) &sockaddr, &length) == 0)
{
ip = (BYTE*)(&sockaddr.sin_addr);
sprintf_s(ipAddress, sizeof(ipAddress), "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8"", ip[0], ip[1], ip[2],
ip[3]);
}
else
if (getsockname(sockfd, (struct sockaddr*) &sockaddr, &length) != 0)
return NULL;

switch (sockaddr.sin_family)
{
strcpy(ipAddress, "127.0.0.1");
case AF_INET:
case AF_INET6:
if (!inet_ntop(sockaddr.sin_family, &sockaddr.sin_addr, ipAddress, sizeof(ipAddress)))
return NULL;

break;

case AF_UNIX:
strcpy(ipAddress, "127.0.0.1");
break;

default:
return NULL;
}

if (pIPv6)
*pIPv6 = (sockaddr.sin_family == AF_INET6);

return _strdup(ipAddress);
}

Expand Down Expand Up @@ -813,7 +824,7 @@ static BOOL freerdp_tcp_connect_timeout(rdpContext* context, int sockfd,
}

static int freerdp_tcp_connect_multi(rdpContext* context, char** hostnames,
UINT32* ports, int count, int port,
UINT32* ports, UINT32 count, int port,
int timeout)
{
int index;
Expand Down Expand Up @@ -992,7 +1003,7 @@ BOOL freerdp_tcp_set_keep_alive_mode(int sockfd)

#endif
#ifndef SOL_TCP
/* "tcp" from /etc/protocols as getprotobyname(3C) */
/* "tcp" from /etc/protocols as getprotobyname(3C) */
#define SOL_TCP 6
#endif
#ifdef TCP_KEEPCNT
Expand Down Expand Up @@ -1110,7 +1121,7 @@ int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,

addr = result;

if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0))
if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0) && !settings->PreferIPv6OverIPv4)
{
while ((addr = addr->ai_next))
{
Expand Down Expand Up @@ -1143,9 +1154,8 @@ int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings,
}
}

settings->IPv6Enabled = FALSE;
free(settings->ClientAddress);
settings->ClientAddress = freerdp_tcp_get_ip_address(sockfd);
settings->ClientAddress = freerdp_tcp_get_ip_address(sockfd, &settings->IPv6Enabled);

if (!settings->ClientAddress)
{
Expand Down

0 comments on commit 2cc6429

Please sign in to comment.