Fix Network: Attempt binding to IPv4 when binding to IPv6 fails with EAFNOSUPPORT error

This commit is contained in:
Maurus Decimus
2026-05-07 15:30:11 +02:00
parent b2a5bb99e6
commit fb20df91ea
2 changed files with 49 additions and 2 deletions

View File

@@ -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

View File

@@ -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
}
}