summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
authorAlexey Izbyshev <izbyshev@ispras.ru>2023-02-25 01:07:33 +0300
committerRich Felker <dalias@aerifal.cx>2023-02-27 10:03:56 -0500
commitd0b7f9768df133428b6587a5273551c56c46d6a6 (patch)
treedf653ccc3e63dec0ec704bb658880b7362bf72aa /src/network
parentbec42ef393c0ad64e699a901ab0746d16bfde251 (diff)
downloadmusl-d0b7f9768df133428b6587a5273551c56c46d6a6.tar.gz
dns: fix workaround for systems defaulting to ipv6-only sockets
When IPv6 nameservers are present, __res_msend_rc attempts to disable IPV6_V6ONLY socket option to ensure that it can communicate with IPv4 nameservers (if they are present too) via IPv4-mapped IPv6 addresses. However, this option can't be disabled on bound sockets, so setsockopt always fails.
Diffstat (limited to 'src/network')
-rw-r--r--src/network/res_msend.c31
1 files changed, 16 insertions, 15 deletions
diff --git a/src/network/res_msend.c b/src/network/res_msend.c
index 2643be22..86c2fcf4 100644
--- a/src/network/res_msend.c
+++ b/src/network/res_msend.c
@@ -133,6 +133,22 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
family = AF_INET;
sl = sizeof sa.sin;
}
+
+ /* Convert any IPv4 addresses in a mixed environment to v4-mapped */
+ if (fd >= 0 && family == AF_INET6) {
+ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0);
+ for (i=0; i<nns; i++) {
+ if (ns[i].sin.sin_family != AF_INET) continue;
+ memcpy(ns[i].sin6.sin6_addr.s6_addr+12,
+ &ns[i].sin.sin_addr, 4);
+ memcpy(ns[i].sin6.sin6_addr.s6_addr,
+ "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
+ ns[i].sin6.sin6_family = AF_INET6;
+ ns[i].sin6.sin6_flowinfo = 0;
+ ns[i].sin6.sin6_scope_id = 0;
+ }
+ }
+
sa.sin.sin_family = family;
if (fd < 0 || bind(fd, (void *)&sa, sl) < 0) {
if (fd >= 0) close(fd);
@@ -152,21 +168,6 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
pthread_cleanup_push(cleanup, pfd);
pthread_setcancelstate(cs, 0);
- /* Convert any IPv4 addresses in a mixed environment to v4-mapped */
- if (family == AF_INET6) {
- setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0);
- for (i=0; i<nns; i++) {
- if (ns[i].sin.sin_family != AF_INET) continue;
- memcpy(ns[i].sin6.sin6_addr.s6_addr+12,
- &ns[i].sin.sin_addr, 4);
- memcpy(ns[i].sin6.sin6_addr.s6_addr,
- "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
- ns[i].sin6.sin6_family = AF_INET6;
- ns[i].sin6.sin6_flowinfo = 0;
- ns[i].sin6.sin6_scope_id = 0;
- }
- }
-
memset(alens, 0, sizeof *alens * nqueries);
retry_interval = timeout / attempts;