From 5d41d476f386d3e4ba6a6c87936ef3d9ab6f1601 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 24 Apr 2025 17:05:14 +0200 Subject: [PATCH] MINOR: sock-inet: detect apparent IPv6 connectivity In order to ease dual-stack deployments, we could at least try to check if ipv6 seems to be reachable. For this we're adding a test based on a UDP connect (no traffic) on port 53 to the base of public addresses (2001::) and see if the connect() is permitted, indicating that the routing table knows how to reach it, or fails. Based on this result we're setting a global variable that other subsystems might use to preset their defaults. --- include/haproxy/sock_inet.h | 1 + src/sock_inet.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/include/haproxy/sock_inet.h b/include/haproxy/sock_inet.h index 1c3b7a303..1d4a8b7a0 100644 --- a/include/haproxy/sock_inet.h +++ b/include/haproxy/sock_inet.h @@ -30,6 +30,7 @@ extern int sock_inet6_v6only_default; extern int sock_inet_tcp_maxseg_default; extern int sock_inet6_tcp_maxseg_default; +extern int sock_inet6_seems_reachable; #ifdef HA_HAVE_MPTCP extern int sock_inet_mptcp_maxseg_default; diff --git a/src/sock_inet.c b/src/sock_inet.c index 20a9ab598..cf60c5a1c 100644 --- a/src/sock_inet.c +++ b/src/sock_inet.c @@ -79,6 +79,9 @@ int sock_inet6_v6only_default = 0; int sock_inet_tcp_maxseg_default = -1; int sock_inet6_tcp_maxseg_default = -1; +/* indicate whether v6 looks reachable (this is only a hint) */ +int sock_inet6_seems_reachable = 0; + /* Default MPTCPv4/MPTCPv6 MSS settings. -1=unknown. */ #ifdef HA_HAVE_MPTCP int sock_inet_mptcp_maxseg_default = -1; @@ -526,6 +529,24 @@ static void sock_inet_prepare() close(fd); } #endif + + /* detect IPv6 reachability: for this we perform a UDP connect to + * address 2001:: on port 53. No packet will be sent, it will just + * check the routing table towards this prefix for the majority of + * public addresses. In case of error we assume no IPv6 connectivity. + */ + fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (fd >= 0) { + struct sockaddr_in6 dest = { }; + + dest.sin6_family = AF_INET6; + dest.sin6_addr.s6_addr[0] = 0x20; + dest.sin6_addr.s6_addr[1] = 0x01; + dest.sin6_port = htons(53); + if (connect(fd, (struct sockaddr*)&dest, sizeof(dest)) == 0) + sock_inet6_seems_reachable = 1; + close(fd); + } } INITCALL0(STG_PREPARE, sock_inet_prepare);