Skip to content

net: ipv6_addr equality and hash, ipv4_addr(socket_address) throws instead of terminating - #9

Open
david-yu wants to merge 2 commits into
ipv6/07-tls-verify-server-namefrom
ipv6/08-address-types
Open

david-yu wants to merge 2 commits into
ipv6/07-tls-verify-server-namefrom
ipv6/08-address-types

Conversation

@david-yu

@david-yu david-yu commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Part 8 of 10 of the IPv6 series, split out of #1 and rebased on current scylladb/seastar master. Based on #8, so the diff here is only this PR's 2 commits.

Why

Two gaps in the address types:

  • ipv4_addr has operator== and std::hash; ipv6_addr had neither.
  • ipv4_addr(const socket_address&) is implicit and has been noexcept since b72a0cbd0, but it delegates to a constructor that throws for an IPv6 address, so an IPv6 socket_address reaching an ipv4_addr parameter called std::terminate.

What

  • net: add operator== and std::hash for ipv6_addr (ab7e301d0) — also drops the stale FIXME on network_stack::connect: the local address has followed the destination's family since 453d531b0.
  • net: report an error instead of terminating on ipv4_addr(socket_address) (00e7787f0) — drops the noexcept; the native stack's make_bound_datagram_channel now throws for a non-AF_INET address like its unbound counterpart, instead of reaching an assert.

API

  • ipv4_addr(const socket_address&) loses noexcept. Calls are unaffected; only code that requires the conversion to be noexcept would notice.
  • std::hash<::sockaddr_in> and operator==(::sockaddr_in, ::sockaddr_in) stay (review on net, dns, tls: make Seastar work on IPv6-only and dual-stack hosts #1).
  • No socket_address::wildcard(family, port) any more: inet_address(family) (669685c78) and ipv6_addr(port) already spell a family's any-address.

Testing

On the core-aws VM (Ubuntu 24.04, GCC 14, C++23, RelWithDebInfo, GnuTLS and OpenSSL in one tree), this PR's head builds and passes dns, ipv6, socket, rpc, httpd, httpd_openssl, tls, tls_openssl, network_interface, websocket and unix_domain with SEASTAR_TEST_REQUIRE_IPV6=1, so none of their IPv6 cases skipped.

Stack

  1. tests, ci: fail instead of skip when IPv6 is expected #2 tests, ci: fail instead of skip when IPv6 is expected
  2. dns: reach nameservers over IPv6 #3 dns: reach nameservers over IPv6
  3. dns: literals for any family, c-ares error text, link-local nameservers #4 dns: literals for any family, c-ares error text, link-local nameservers
  4. net, http, rpc: dual-stack listeners (IPV6_V6ONLY, IPv4-mapped peers) #5 net, http, rpc: dual-stack listeners (IPV6_V6ONLY, IPv4-mapped peers)
  5. net: IPv6 zones and strict literal parsing #6 net: IPv6 zones and strict literal parsing
  6. tls: do not send IP literals in the SNI extension #7 tls: do not send IP literals in the SNI extension
  7. tls: verify server_name on OpenSSL, opt-in #8 tls: verify server_name on OpenSSL, opt-in
  8. net: ipv6_addr equality and hash, ipv4_addr(socket_address) throws instead of terminating #9 net: ipv6_addr equality and hash, ipv4_addr(socket_address) throws instead of terminating ← this PR
  9. net: listen on an unspecified address binds any family #10 net: listen on an unspecified address binds any family
  10. http: build the Host header from an address in authority form #11 http: build the Host header from an address in authority form

ipv4_addr has both; ipv6_addr had neither, so an IPv6 endpoint could not
be compared or used as a hash-map key without first converting it to a
socket_address.

Also drop the stale FIXME on network_stack::connect: the local address
has followed the destination's family since 453d531.
The socket_address to ipv4_addr conversion is implicit and has been
noexcept since b72a0cb, but it delegates to
ipv4_addr(const inet_address&, uint16_t), which throws for an IPv6
address that is not IPv4-mapped — so passing an IPv6 socket_address
anywhere an ipv4_addr is expected terminated the process instead of
raising std::invalid_argument.

Drop the noexcept. The only caller inside a noexcept function is
socket_address::is_wildcard(), in its AF_INET arm, where the conversion
cannot throw; that is now commented. The native stack's
make_bound_datagram_channel checked nothing and reached an assert on a
non-AF_INET address, while its unbound counterpart throws: make it throw
too.
@david-yu
david-yu force-pushed the ipv6/08-address-types branch from 59cd693 to 00e7787 Compare September 25, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant