103 lines
2.8 KiB
Diff
103 lines
2.8 KiB
Diff
From 462b02de4107845ab235e1668f78a43a31eb11fc Mon Sep 17 00:00:00 2001
|
|
From: Ondrej Holy <oholy@redhat.com>
|
|
Date: Wed, 14 Jan 2026 13:38:42 +0100
|
|
Subject: [PATCH] [core,tcp] Fix PreferIPv6OverIPv4 fallback to IPv4 addresses
|
|
|
|
Backport of commit 0bdd8da0993231216a7bb4d5e6e33e47d817a944.
|
|
|
|
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
---
|
|
libfreerdp/core/tcp.c | 61 ++++++++++++++++++++++++++++++++++++-------
|
|
1 file changed, 51 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c
|
|
index 8a731f117..3cf24c160 100644
|
|
--- a/libfreerdp/core/tcp.c
|
|
+++ b/libfreerdp/core/tcp.c
|
|
@@ -1064,6 +1064,53 @@ static BOOL freerdp_tcp_set_keep_alive_mode(const rdpSettings* settings, int soc
|
|
return TRUE;
|
|
}
|
|
|
|
+static struct addrinfo* reorder_addrinfo_by_preference(rdpContext* context, struct addrinfo* addr)
|
|
+{
|
|
+ WINPR_ASSERT(context);
|
|
+ WINPR_ASSERT(addr);
|
|
+
|
|
+ const BOOL preferIPv6 =
|
|
+ freerdp_settings_get_bool(context->settings, FreeRDP_PreferIPv6OverIPv4);
|
|
+ if (!preferIPv6)
|
|
+ return addr;
|
|
+
|
|
+ struct addrinfo* ipv6Head = NULL;
|
|
+ struct addrinfo* ipv6Tail = NULL;
|
|
+ struct addrinfo* otherHead = NULL;
|
|
+ struct addrinfo* otherTail = NULL;
|
|
+
|
|
+ /* Partition the list into IPv6 and other addresses */
|
|
+ while (addr)
|
|
+ {
|
|
+ struct addrinfo* next = addr->ai_next;
|
|
+ addr->ai_next = NULL;
|
|
+
|
|
+ if (addr->ai_family == AF_INET6)
|
|
+ {
|
|
+ if (!ipv6Head)
|
|
+ ipv6Head = addr;
|
|
+ else
|
|
+ ipv6Tail->ai_next = addr;
|
|
+ ipv6Tail = addr;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (!otherHead)
|
|
+ otherHead = addr;
|
|
+ else
|
|
+ otherTail->ai_next = addr;
|
|
+ otherTail = addr;
|
|
+ }
|
|
+ addr = next;
|
|
+ }
|
|
+
|
|
+ /* Concatenate the lists */
|
|
+ if (ipv6Tail)
|
|
+ ipv6Tail->ai_next = otherHead;
|
|
+
|
|
+ return ipv6Head ? ipv6Head : otherHead;
|
|
+}
|
|
+
|
|
static int get_next_addrinfo(rdpContext* context, struct addrinfo* input, struct addrinfo** result,
|
|
UINT32 errorCode)
|
|
{
|
|
@@ -1074,14 +1121,6 @@ static int get_next_addrinfo(rdpContext* context, struct addrinfo* input, struct
|
|
if (!addr)
|
|
goto fail;
|
|
|
|
- if (freerdp_settings_get_bool(context->settings, FreeRDP_PreferIPv6OverIPv4))
|
|
- {
|
|
- while (addr && (addr->ai_family != AF_INET6))
|
|
- addr = addr->ai_next;
|
|
- if (!addr)
|
|
- addr = input;
|
|
- }
|
|
-
|
|
*result = addr;
|
|
return 0;
|
|
|
|
@@ -1161,9 +1200,11 @@ int freerdp_tcp_connect(rdpContext* context, rdpSettings* settings, const char*
|
|
freerdp_set_last_error_log(context, 0);
|
|
|
|
/*
|
|
- * If PreferIPv6OverIPv4 = TRUE we force to IPv6 if there
|
|
- * is such an address available, but fall back to first if not found
|
|
+ * If PreferIPv6OverIPv4 = TRUE we reorder addresses by preference:
|
|
+ * IPv6 addresses come first, then other addresses.
|
|
*/
|
|
+ result = reorder_addrinfo_by_preference(context, result);
|
|
+
|
|
const int rc =
|
|
get_next_addrinfo(context, result, &addr, FREERDP_ERROR_DNS_NAME_NOT_FOUND);
|
|
if (rc < 0)
|
|
--
|
|
2.52.0
|
|
|