distribution/packages/devel/glibc/patches/glibc-fix-dns-with-broken-routers.patch

107 lines
3.6 KiB
Diff

commit 45918e237cd32bb3d9a5fde83f81f83b52584771
Author: Stefan Saraev <stefan@saraev.ca>
Date: Tue Oct 1 12:09:07 2013 +0300
fix dns with broken routers
ref: https://fedoraproject.org/wiki/Networking/NameResolution/ADDRCONFIG
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -730,6 +730,38 @@ gaih_inet (const char *name, const struc
if (res_ctx == NULL)
no_more = 1;
+ /* AI_ADDRCONFIG determines whether or not we should suppress any
+ * hostname lookups. If the local host has only IPv4 interfaces,
+ * then suppress lookups for IPv6 addresses, and vice versa; if
+ * the local host has only IPv6 interfaces, suppress any lookups
+ * for IPv4 addresses..
+ *
+ * Link-local IPv6 addresses and loopback addresses of either
+ * family are ignored when determining whether or not the host has
+ * an interface of the given address family, cf. __check_pf().
+ *
+ * This logic is only applied for AF_UNSPEC. If the caller
+ * explicitly requested an address family, give him what he asked
+ * for.
+ *
+ * If we didn't find any interfaces of either address family,
+ * we ignore AI_ADDRCONFIG and return all available resutlts. */
+ int suppress_af = 0;
+ if (req->ai_family == AF_UNSPEC)
+ {
+ struct in6addrinfo *in6ai = NULL;
+ size_t in6ailen = 0;
+ bool seen_ipv4 = false;
+ bool seen_ipv6 = false;
+ __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
+ __free_in6ai (in6ai);
+
+ if(seen_ipv4 && !seen_ipv6)
+ suppress_af = AF_INET6;
+ else if(seen_ipv6 && !seen_ipv4)
+ suppress_af = AF_INET;
+ }
+
while (!no_more)
{
no_data = 0;
@@ -737,7 +769,7 @@ gaih_inet (const char *name, const struc
/* gethostbyname4_r sends out parallel A and AAAA queries and
is thus only suitable for PF_UNSPEC. */
- if (req->ai_family == PF_UNSPEC)
+ if (req->ai_family == PF_UNSPEC && !suppress_af)
fct4 = __nss_lookup_function (nip, "gethostbyname4_r");
if (fct4 != NULL)
@@ -826,25 +858,27 @@ gaih_inet (const char *name, const struc
if (fct != NULL)
{
- if (req->ai_family == AF_INET6
- || req->ai_family == AF_UNSPEC)
+ if ((req->ai_family == AF_INET6
+ || req->ai_family == AF_UNSPEC)
+ && suppress_af != AF_INET6)
{
if ((result = gethosts (fct, AF_INET6, name, req, tmpbuf,
res, &status, &no_data)) != 0)
{
__resolv_context_put (res_ctx);
goto out;
}
no_inet6_data = no_data;
inet6_status = status;
}
- if (req->ai_family == AF_INET
- || req->ai_family == AF_UNSPEC
- || (req->ai_family == AF_INET6
- && (req->ai_flags & AI_V4MAPPED)
- /* Avoid generating the mapped addresses if we
- know we are not going to need them. */
- && ((req->ai_flags & AI_ALL) || !res->got_ipv6)))
+ if ((req->ai_family == AF_INET
+ || req->ai_family == AF_UNSPEC
+ || (req->ai_family == AF_INET6
+ && (req->ai_flags & AI_V4MAPPED)
+ /* Avoid generating the mapped addresses if we
+ know we are not going to need them. */
+ && ((req->ai_flags & AI_ALL) || !res->got_ipv6)))
+ && suppress_af != AF_INET)
{
if ((result = gethosts (fct, AF_INET, name, req, tmpbuf,
res, &status, &no_data)) != 0)
--- a/sysdeps/unix/sysv/linux/check_pf.c
+++ b/sysdeps/unix/sysv/linux/check_pf.c
@@ -224,7 +224,8 @@ make_request (int fd, pid_t pid)
}
else
{
- if (!IN6_IS_ADDR_LOOPBACK (address))
+ if (!IN6_IS_ADDR_LOOPBACK (address) &&
+ !IN6_IS_ADDR_LINKLOCAL (address))
seen_ipv6 = true;
}
}