From 8158ce5fe47428cc29c737bc845a0e89368562e3 Mon Sep 17 00:00:00 2001 From: David Gow Date: Mon, 9 Oct 2023 22:28:16 +0800 Subject: [PATCH] Force AF_INET6 when binding to a NULL address Currently, to listen on 'all' addresses, NULL is used as the SDLNet_Address pointer. This results in NULL being passed to getaddrinfo() in MakeAddrInfoWithPort(), as well as the hint AI_PASSIVE and address family AF_UNSPEC being used. It's the latter which can cause problems: on a dual-stack IPv4/IPv6 setup, AF_UNSPEC can resolve to AF_INET, resulting in the socket only binding to IPv4 addresses. This means that any attempt to connect to such a socket using the destination's IPv6 address (which may be the only address returned by SDLNet_ResolveHostname()) will fail. There are two possible solutions here: - Create several sockets, one for each available address family, and bind each to their associated NULL address. - Force the family to AF_INET6, and enable v4 address mapping, which will allow IPv4 addresses to be treated as IPv6 addresses of the form ::ffff:
This implements the latter: it has the advantage of being much simpler (only one socket is required), but the disadvantages of not working as-is on IPv4-only systems (which are rarer, but still exist), and not supporting non-IP protocols at all (I assume we're not planning to support IPX). --- src/SDL_net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SDL_net.c b/src/SDL_net.c index 41308c0..0056dc2 100644 --- a/src/SDL_net.c +++ b/src/SDL_net.c @@ -743,10 +743,10 @@ static struct addrinfo *MakeAddrInfoWithPort(const SDLNet_Address *addr, const i // want to keep things generic and also not set up a port at resolve time. struct addrinfo hints; SDL_zero(hints); - hints.ai_family = ainfo ? ainfo->ai_family : AF_UNSPEC; + hints.ai_family = ainfo ? ainfo->ai_family : AF_INET6; hints.ai_socktype = socktype; //hints.ai_protocol = ainfo ? ainfo->ai_protocol : 0; - hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | (!ainfo ? AI_PASSIVE : 0); + hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | (!ainfo ? AI_PASSIVE | AI_V4MAPPED : 0); char service[16]; SDL_snprintf(service, sizeof (service), "%d", (int) port);