From fb20df91ea260cbd03b5a4078b64545e4649dc78 Mon Sep 17 00:00:00 2001 From: Maurus Decimus <11444311+mdecimus@users.noreply.github.com> Date: Thu, 7 May 2026 15:30:11 +0200 Subject: [PATCH] Fix Network: Attempt binding to IPv4 when binding to IPv6 fails with `EAFNOSUPPORT` error --- CHANGELOG.md | 1 + crates/common/src/config/server/listener.rs | 50 ++++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a1e9775..2751e078 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ If you are upgrading from v0.16.x, replace the binary (or run `docker pull`). If - Patching ids containing digits in JSON Pointers failes. - Patching nested objects with `null` values fails. - SQL directory: Return `Failed` instead of `Error` when the query returns no results. +- Network: Attempt binding to IPv4 when binding to IPv6 fails with `EAFNOSUPPORT` error. ## [0.16.4] - 2026-05-05 diff --git a/crates/common/src/config/server/listener.rs b/crates/common/src/config/server/listener.rs index 2970d85a..94504dd6 100644 --- a/crates/common/src/config/server/listener.rs +++ b/crates/common/src/config/server/listener.rs @@ -24,7 +24,11 @@ use rustls::{ ALL_VERSIONS, ServerConfig, SupportedCipherSuite, crypto::aws_lc_rs::{ALL_CIPHER_SUITES, cipher_suite::*, default_provider}, }; -use std::{str::FromStr, sync::Arc}; +use std::{ + net::{IpAddr, Ipv4Addr, SocketAddr as StdSocketAddr}, + str::FromStr, + sync::Arc, +}; use store::registry::{RegistryObject, bootstrap::Bootstrap}; use tokio::net::TcpSocket; use tokio_rustls::TlsAcceptor; @@ -109,13 +113,39 @@ impl Listeners { let mut listeners = Vec::new(); for addr in listener.bind.iter() { // Parse bind address and build socket - let addr = addr.0; + let mut addr = addr.0; let socket = match if addr.is_ipv4() { TcpSocket::new_v4() } else { TcpSocket::new_v6() } { Ok(socket) => socket, + Err(err) + if is_eafnosupport(&err) + && addr.is_ipv6() + && addr.ip().is_unspecified() => + { + let v4_addr = + StdSocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), addr.port()); + bp.build_warning( + id, + format!( + "IPv6 unavailable on this host ({err}); \ + falling back from {addr} to {v4_addr}" + ), + ); + addr = v4_addr; + match TcpSocket::new_v4() { + Ok(socket) => socket, + Err(err) => { + bp.build_error( + id, + format!("Failed to create IPv4 fallback socket: {err}"), + ); + return; + } + } + } Err(err) => { bp.build_error(id, format!("Failed to create socket: {err}")); return; @@ -284,3 +314,19 @@ impl Listeners { } } } + +fn is_eafnosupport(err: &std::io::Error) -> bool { + let code = err.raw_os_error(); + #[cfg(unix)] + { + code == Some(libc::EAFNOSUPPORT) + } + #[cfg(windows)] + { + code == Some(10047) + } + #[cfg(not(any(unix, windows)))] + { + false + } +}