While this will likely be just temporary, it is better to fix the error then disable test case.
71 lines
2.9 KiB
Diff
71 lines
2.9 KiB
Diff
From 3583079b8a746256d762c69fd8f58f30ce314276 Mon Sep 17 00:00:00 2001
|
|
From: KJ Tsanaktsidis <kj@kjtsanaktsidis.id.au>
|
|
Date: Sat, 9 Dec 2023 12:30:39 +1100
|
|
Subject: [PATCH] Partially revert "Set AI_ADDRCONFIG when making
|
|
getaddrinfo(3) calls"
|
|
|
|
This _partially_ reverts commit
|
|
d2ba8ea54a4089959afdeecdd963e3c4ff391748, but for UDP sockets only.
|
|
|
|
With TCP sockets (and other things which use `rsock_init_inetsock`), the
|
|
order of operations is to call `getaddrinfo(3)` with AF_UNSPEC, look at
|
|
the returned addresses, pick one, and then call `socket(2)` with the
|
|
family for that address (i.e. AF_INET or AF_INET6).
|
|
|
|
With UDP sockets, however, this is reversed; `UDPSocket.new` takes an
|
|
address family as an argument, and then calls `socket(2)` with that
|
|
family. A subsequent call to UDPSocket#connect will then call
|
|
`getaddrinfo(3)` with that family.
|
|
|
|
The problem here is that...
|
|
|
|
* If you are in a networking situation that _only_ has loopback addrs,
|
|
* And you want to look up a name like "localhost" (or NULL)
|
|
* And you pass AF_INET or AF_INET6 as the ai_family argument to
|
|
getaddrinfo(3),
|
|
* And you pass AI_ADDRCONFIG to the hints argument as well,
|
|
|
|
then glibc on Linux will not return an address. This is because
|
|
AI_ADDRCONFIG is supposed to return addresses for families we actually
|
|
have an address for and could conceivably connect to, but also is
|
|
documented to explicitly ignore localhost in that situation.
|
|
|
|
It honestly doesn't make a ton of sense to pass AI_ADDRCONFIG if you're
|
|
explicitly passing the address family anyway, because you're not looking
|
|
for "an address for this name we can connect to"; you're looking for "an
|
|
IPv(4|6) address for this name". And the original glibc bug that
|
|
d2ba8ea5 was supposed to work around was related to parallel issuance of
|
|
A and AAAA queries, which of course won't happen if an address family is
|
|
explicitly specified.
|
|
|
|
So, we fix this by not passing AI_ADDRCONFIG for calls to
|
|
`rsock_addrinfo` that we also pass an explicit family to (i.e. for
|
|
UDPsocket).
|
|
|
|
[Bug #20048]
|
|
---
|
|
ext/socket/udpsocket.c | 9 +--------
|
|
1 file changed, 1 insertion(+), 8 deletions(-)
|
|
|
|
diff --git a/ext/socket/udpsocket.c b/ext/socket/udpsocket.c
|
|
index cf3eb6ab9a69f..5224e48a96a1f 100644
|
|
--- a/ext/socket/udpsocket.c
|
|
+++ b/ext/socket/udpsocket.c
|
|
@@ -88,16 +88,9 @@ udp_connect(VALUE sock, VALUE host, VALUE port)
|
|
{
|
|
struct udp_arg arg;
|
|
VALUE ret;
|
|
- int addrinfo_hints = 0;
|
|
|
|
GetOpenFile(sock, arg.fptr);
|
|
-
|
|
-#ifdef HAVE_CONST_AI_ADDRCONFIG
|
|
- addrinfo_hints |= AI_ADDRCONFIG;
|
|
-#endif
|
|
-
|
|
- arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM,
|
|
- addrinfo_hints);
|
|
+ arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0);
|
|
ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
|
|
rsock_freeaddrinfo, (VALUE)arg.res);
|
|
if (!ret) rsock_sys_fail_host_port("connect(2)", host, port);
|