103 lines
3.0 KiB
Diff
103 lines
3.0 KiB
Diff
From 4864954a384e4028298e95a19795505f688b21ae Mon Sep 17 00:00:00 2001
|
|
From: Ondrej Holy <oholy@redhat.com>
|
|
Date: Wed, 14 Jan 2026 11:38:11 +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 6edfb6d71..83cc9af1e 100644
|
|
--- a/libfreerdp/core/tcp.c
|
|
+++ b/libfreerdp/core/tcp.c
|
|
@@ -1081,6 +1081,53 @@ int freerdp_tcp_connect(rdpContext* context, const char* hostname, int port, DWO
|
|
return transport_tcp_connect(context->rdp->transport, hostname, port, timeout);
|
|
}
|
|
|
|
+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)
|
|
{
|
|
@@ -1091,14 +1138,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;
|
|
- }
|
|
-
|
|
/* We want to force IPvX, abort if not detected */
|
|
const UINT32 IPvX = freerdp_settings_get_uint32(context->settings, FreeRDP_ForceIPvX);
|
|
switch (IPvX)
|
|
@@ -1237,9 +1276,11 @@ int freerdp_tcp_default_connect(rdpContext* context, rdpSettings* settings, cons
|
|
|
|
/* 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
|
|
+ * 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
|
|
|