From 562fa8a03d20957bff73fa3e1c5429aa3672dfd0 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 28 Jun 2024 08:42:16 +0200 Subject: [PATCH] [core,tcp] Improve IPv4 or IPv6 connect * Fix +ipv6 option, now fall back to IPv4 if no IPv6 entry found * Add new option ForceIPvX to fail connect if no such entry is found --- client/common/cmdline.c | 25 ++++++++++- client/common/cmdline.h | 4 +- include/freerdp/settings_types_private.h | 3 +- libfreerdp/common/settings_getters.c | 7 +++ libfreerdp/common/settings_str.h | 1 + libfreerdp/core/tcp.c | 43 +++++++++++++++---- .../core/test/settings_property_lists.h | 1 + 7 files changed, 71 insertions(+), 13 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index dcb8b8d02..9cf95db6c 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -4554,10 +4554,31 @@ static int freerdp_client_settings_parse_command_line_arguments_int( if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectHomeDrive, enable)) return COMMAND_LINE_ERROR; } + CommandLineSwitchCase(arg, "ipv4") + { + if (strncmp(arg->Value, "force", 6) == 0) + { + if (!freerdp_settings_set_uint32(settings, FreeRDP_ForceIPvX, 4)) + return COMMAND_LINE_ERROR; + } + else + { + if (!freerdp_settings_set_bool(settings, FreeRDP_PreferIPv6OverIPv4, FALSE)) + return COMMAND_LINE_ERROR; + } + } CommandLineSwitchCase(arg, "ipv6") { - if (!freerdp_settings_set_bool(settings, FreeRDP_PreferIPv6OverIPv4, enable)) - return COMMAND_LINE_ERROR; + if (strncmp(arg->Value, "force", 6) == 0) + { + if (!freerdp_settings_set_uint32(settings, FreeRDP_ForceIPvX, 6)) + return COMMAND_LINE_ERROR; + } + else + { + if (!freerdp_settings_set_bool(settings, FreeRDP_PreferIPv6OverIPv4, TRUE)) + return COMMAND_LINE_ERROR; + } } CommandLineSwitchCase(arg, "clipboard") { diff --git a/client/common/cmdline.h b/client/common/cmdline.h index ad46ee721..3d0de3313 100644 --- a/client/common/cmdline.h +++ b/client/common/cmdline.h @@ -247,7 +247,9 @@ static const COMMAND_LINE_ARGUMENT_A global_cmd_args[] = { "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", + { "ipv4", COMMAND_LINE_VALUE_OPTIONAL, "[:force]", NULL, NULL, -1, "4", + "Prefer IPv4 AAA record over IPv6 A record" }, + { "ipv6", COMMAND_LINE_VALUE_OPTIONAL, "[:force]", 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, "JPEG codec support" }, diff --git a/include/freerdp/settings_types_private.h b/include/freerdp/settings_types_private.h index 2c95a6639..099e689cc 100644 --- a/include/freerdp/settings_types_private.h +++ b/include/freerdp/settings_types_private.h @@ -746,7 +746,8 @@ struct rdp_settings SETTINGS_DEPRECATED(ALIGN64 BOOL RedirectSerialPorts); /* 4672 */ SETTINGS_DEPRECATED(ALIGN64 BOOL RedirectParallelPorts); /* 4673 */ SETTINGS_DEPRECATED(ALIGN64 BOOL PreferIPv6OverIPv4); /* 4674 */ - UINT64 padding4800[4800 - 4675]; /* 4675 */ + SETTINGS_DEPRECATED(ALIGN64 UINT32 ForceIPvX); /* 4675 */ + UINT64 padding4800[4800 - 4676]; /* 4676 */ /** * Other Redirection diff --git a/libfreerdp/common/settings_getters.c b/libfreerdp/common/settings_getters.c index 352a285e7..0ae9b0ff9 100644 --- a/libfreerdp/common/settings_getters.c +++ b/libfreerdp/common/settings_getters.c @@ -1736,6 +1736,9 @@ UINT32 freerdp_settings_get_uint32(const rdpSettings* settings, FreeRDP_Settings case FreeRDP_Floatbar: return settings->Floatbar; + case FreeRDP_ForceIPvX: + return settings->ForceIPvX; + case FreeRDP_FrameAcknowledge: return settings->FrameAcknowledge; @@ -2169,6 +2172,10 @@ BOOL freerdp_settings_set_uint32(rdpSettings* settings, FreeRDP_Settings_Keys_UI settings->Floatbar = cnv.c; break; + case FreeRDP_ForceIPvX: + settings->ForceIPvX = cnv.c; + break; + case FreeRDP_FrameAcknowledge: settings->FrameAcknowledge = cnv.c; break; diff --git a/libfreerdp/common/settings_str.h b/libfreerdp/common/settings_str.h index 75e24718c..239185ab2 100644 --- a/libfreerdp/common/settings_str.h +++ b/libfreerdp/common/settings_str.h @@ -334,6 +334,7 @@ static const struct settings_str_entry settings_map[] = { { FreeRDP_FakeMouseMotionInterval, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_FakeMouseMotionInterval" }, { FreeRDP_Floatbar, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_Floatbar" }, + { FreeRDP_ForceIPvX, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_ForceIPvX" }, { FreeRDP_FrameAcknowledge, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_FrameAcknowledge" }, { FreeRDP_GatewayAcceptedCertLength, FREERDP_SETTINGS_TYPE_UINT32, "FreeRDP_GatewayAcceptedCertLength" }, diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index f424cc048..7712ca915 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -1176,21 +1176,46 @@ int freerdp_tcp_default_connect(rdpContext* context, rdpSettings* settings, cons } freerdp_set_last_error_log(context, 0); + /* By default we take the first returned entry. + * + * If PreferIPv6OverIPv4 = TRUE we force to IPv6 if there + * is such an address available, but fall back to first if not found + */ addr = result; - - if ((addr->ai_family == AF_INET6) && (addr->ai_next != 0) && - !settings->PreferIPv6OverIPv4) + if (freerdp_settings_get_bool(settings, FreeRDP_PreferIPv6OverIPv4)) { - while ((addr = addr->ai_next)) - { - if (addr->ai_family == AF_INET) - break; - } - + while (addr && (addr->ai_family != AF_INET6)) + addr = addr->ai_next; if (!addr) addr = result; } + /* We want to force IPvX, abort if not detected */ + const UINT32 IPvX = freerdp_settings_get_uint32(settings, FreeRDP_ForceIPvX); + switch (IPvX) + { + case 4: + case 6: + { + const int family = (IPvX == 4) ? AF_INET : AF_INET6; + while (addr && (addr->ai_family != family)) + addr = addr->ai_next; + if (!addr) + { + freerdp_set_last_error_if_not(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND); + return -1; + } + } + break; + default: + break; + } + + if (!addr) + { + freerdp_set_last_error_if_not(context, FREERDP_ERROR_DNS_NAME_NOT_FOUND); + return -1; + } sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (sockfd < 0) diff --git a/libfreerdp/core/test/settings_property_lists.h b/libfreerdp/core/test/settings_property_lists.h index b6095c2b5..f2f265f76 100644 --- a/libfreerdp/core/test/settings_property_lists.h +++ b/libfreerdp/core/test/settings_property_lists.h @@ -257,6 +257,7 @@ static const size_t uint32_list_indices[] = { FreeRDP_ExtEncryptionMethods, FreeRDP_FakeMouseMotionInterval, FreeRDP_Floatbar, + FreeRDP_ForceIPvX, FreeRDP_FrameAcknowledge, FreeRDP_GatewayAcceptedCertLength, FreeRDP_GatewayCredentialsSource,