102 lines
3.4 KiB
Diff
102 lines
3.4 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,20 +858,22 @@ 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)
|
|
{
|
|
gethosts (AF_INET6);
|
|
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) || !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) || !got_ipv6)))
|
|
+ && suppress_af != AF_INET)
|
|
{
|
|
gethosts (AF_INET);
|
|
|
|
--- 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;
|
|
}
|
|
}
|