diff options
author | Daiki Ueno <dueno@redhat.com> | 2021-07-14 11:15:34 +0200 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2021-07-16 08:58:06 +0200 |
commit | 09c1db3399d682523443af64158e1862082da23e (patch) | |
tree | df91869d84fd7e42c10d097ebe461f29cbde4ffc /apps | |
parent | 52f7e44ec88a4d803dc9783cd7c71f87014ae3ee (diff) |
apps: Use the first detected address family if IPv6 is not available
This is a follow up of 15729bef385211bc2a0497e2d53a45c45d677d2c. Even
when the host does not support IPv6 at all, BIO_lookup_ex may now
return IN6ADDR_ANY in addition to INADDR_ANY, as the second element of
the ai_next field.
After eee8a40aa5e06841eed6fa8eb4f6109238d59aea, the do_server function
prefers the IPv6 address and fails on the BIO_socket call. This adds
a fallback code to retry with the IPv4 address returned as the first
element to avoid the error.
The failure had been partially avoided in the previous code with
AI_ADDRCONFIG, because getaddrinfo returns only IPv4 address if no
IPv6 address is associated with external interface. However, it would
be still a problem if the external interface has an IPv6 address
assigned, while the loopback interface doesn't.
Signed-off-by: Daiki Ueno <dueno@redhat.com>
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16074)
Diffstat (limited to 'apps')
-rw-r--r-- | apps/lib/s_socket.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/apps/lib/s_socket.c b/apps/lib/s_socket.c index bddf16045f..6884fd86cd 100644 --- a/apps/lib/s_socket.c +++ b/apps/lib/s_socket.c @@ -267,6 +267,8 @@ int do_server(int *accept_sock, const char *host, const char *port, const BIO_ADDRINFO *next; int sock_family, sock_type, sock_protocol, sock_port; const BIO_ADDR *sock_address; + int sock_family_fallback = AF_UNSPEC; + const BIO_ADDR *sock_address_fallback = NULL; int sock_options = BIO_SOCK_REUSEADDR; int ret = 0; @@ -298,6 +300,10 @@ int do_server(int *accept_sock, const char *host, const char *port, && BIO_ADDRINFO_protocol(next) == sock_protocol) { if (sock_family == AF_INET && BIO_ADDRINFO_family(next) == AF_INET6) { + /* In case AF_INET6 is returned but not supported by the + * kernel, retry with the first detected address family */ + sock_family_fallback = sock_family; + sock_address_fallback = sock_address; sock_family = AF_INET6; sock_address = BIO_ADDRINFO_address(next); } else if (sock_family == AF_INET6 @@ -308,6 +314,10 @@ int do_server(int *accept_sock, const char *host, const char *port, #endif asock = BIO_socket(sock_family, sock_type, sock_protocol, 0); + if (asock == INVALID_SOCKET && sock_family_fallback != AF_UNSPEC) { + asock = BIO_socket(sock_family_fallback, sock_type, sock_protocol, 0); + sock_address = sock_address_fallback; + } if (asock == INVALID_SOCKET || !BIO_listen(asock, sock_address, sock_options)) { BIO_ADDRINFO_free(res); |