]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: sock-inet: detect apparent IPv6 connectivity
authorWilly Tarreau <w@1wt.eu>
Thu, 24 Apr 2025 15:05:14 +0000 (17:05 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 24 Apr 2025 15:52:28 +0000 (17:52 +0200)
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
src/sock_inet.c

index 1c3b7a3033c08c6843a6614902e690a3b56a0ed5..1d4a8b7a001e0e96a3c2ee85c5e73e427defb89d 100644 (file)
@@ -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;
index 20a9ab5984619d4988b23a4764fbb8658e1e25ab..cf60c5a1ca0a556be3e22acee3b76a39041ef494 100644 (file)
@@ -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);