Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions src/net/posix-stack.cc
Original file line number Diff line number Diff line change
Expand Up @@ -914,9 +914,16 @@ posix_network_stack::posix_network_stack(const program_options::option_group& op
server_socket
posix_network_stack::listen(socket_address sa, listen_options opt) {
using server_socket = seastar::server_socket;
// allow unspecified bind address -> default to ipv4 wildcard
// An unspecified address listens on both families where the host has
// IPv6 ([::] with IPV6_V6ONLY off), and on 0.0.0.0 where it does not. A
// listen_options::ipv6_only the caller set is kept.
if (sa.is_unspecified()) {
sa = inet_address(inet_address::family::INET);
if (supports_ipv6()) {
sa = inet_address(inet_address::family::INET6);
opt.ipv6_only = opt.ipv6_only.value_or(false);
} else {
sa = inet_address(inet_address::family::INET);
}
}
if (sa.is_af_unix()) {
return server_socket(std::make_unique<posix_server_socket_impl>(0, sa, internal::posix_listen(sa, opt), opt.lba, opt.fixed_cpu, opt.proxy_protocol, _allocator));
Expand All @@ -940,9 +947,16 @@ posix_ap_network_stack::posix_ap_network_stack(const program_options::option_gro
server_socket
posix_ap_network_stack::listen(socket_address sa, listen_options opt) {
using server_socket = seastar::server_socket;
// allow unspecified bind address -> default to ipv4 wildcard
// An unspecified address listens on both families where the host has
// IPv6 ([::] with IPV6_V6ONLY off), and on 0.0.0.0 where it does not. A
// listen_options::ipv6_only the caller set is kept.
if (sa.is_unspecified()) {
sa = inet_address(inet_address::family::INET);
if (supports_ipv6()) {
sa = inet_address(inet_address::family::INET6);
opt.ipv6_only = opt.ipv6_only.value_or(false);
} else {
sa = inet_address(inet_address::family::INET);
}
}
if (sa.is_af_unix()) {
return server_socket(std::make_unique<posix_ap_server_socket_impl>(0, sa, _allocator));
Expand Down
19 changes: 19 additions & 0 deletions tests/unit/ipv6_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,25 @@ SEASTAR_TEST_CASE(dual_stack_listen_test) {
}
}

// listen() with no address at all listens for both families where it can,
// instead of quietly picking IPv4 and being unreachable on an IPv6-only host.
SEASTAR_TEST_CASE(listen_unspecified_address_test) {
if (!check_ipv6_support()) {
co_return;
}
auto ss = server_socket(engine().net().listen(socket_address(), {}));
BOOST_REQUIRE_EQUAL(ss.local_address().family(), AF_INET6);
BOOST_REQUIRE(ss.local_address().addr().is_addr_any());

auto accepted = ss.accept();
auto cs = co_await connect(ipv4_addr("127.0.0.1", ss.local_address().port()));
auto ar = co_await std::move(accepted);
// an IPv4 peer arrives, and (per the v4-mapped normalisation) reads as IPv4
BOOST_REQUIRE_EQUAL(ar.remote_address.unmapped().addr(), net::inet_address("127.0.0.1"));
cs.shutdown_output();
ar.connection.shutdown_output();
}

// ipv6_addr compares and hashes like ipv4_addr.
SEASTAR_TEST_CASE(ipv6_addr_value_type_test) {
const ipv6_addr a("2001:db8::1", 9092);
Expand Down
Loading