Fix Network: Attempt binding to IPv4 when binding to IPv6 fails with EAFNOSUPPORT error
This commit is contained in:
@@ -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 ids containing digits in JSON Pointers failes.
|
||||||
- Patching nested objects with `null` values fails.
|
- Patching nested objects with `null` values fails.
|
||||||
- SQL directory: Return `Failed` instead of `Error` when the query returns no results.
|
- 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
|
## [0.16.4] - 2026-05-05
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,11 @@ use rustls::{
|
|||||||
ALL_VERSIONS, ServerConfig, SupportedCipherSuite,
|
ALL_VERSIONS, ServerConfig, SupportedCipherSuite,
|
||||||
crypto::aws_lc_rs::{ALL_CIPHER_SUITES, cipher_suite::*, default_provider},
|
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 store::registry::{RegistryObject, bootstrap::Bootstrap};
|
||||||
use tokio::net::TcpSocket;
|
use tokio::net::TcpSocket;
|
||||||
use tokio_rustls::TlsAcceptor;
|
use tokio_rustls::TlsAcceptor;
|
||||||
@@ -109,13 +113,39 @@ impl Listeners {
|
|||||||
let mut listeners = Vec::new();
|
let mut listeners = Vec::new();
|
||||||
for addr in listener.bind.iter() {
|
for addr in listener.bind.iter() {
|
||||||
// Parse bind address and build socket
|
// Parse bind address and build socket
|
||||||
let addr = addr.0;
|
let mut addr = addr.0;
|
||||||
let socket = match if addr.is_ipv4() {
|
let socket = match if addr.is_ipv4() {
|
||||||
TcpSocket::new_v4()
|
TcpSocket::new_v4()
|
||||||
} else {
|
} else {
|
||||||
TcpSocket::new_v6()
|
TcpSocket::new_v6()
|
||||||
} {
|
} {
|
||||||
Ok(socket) => socket,
|
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) => {
|
Err(err) => {
|
||||||
bp.build_error(id, format!("Failed to create socket: {err}"));
|
bp.build_error(id, format!("Failed to create socket: {err}"));
|
||||||
return;
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user