aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2019-03-12 11:40:47 +0100
committerFlorian Weimer <fweimer@redhat.com>2019-03-12 11:40:47 +0100
commit08504de71813ddbd447bfbca4a325cbe8ce8bcda (patch)
tree220785321a7949a077d9ea8c381eb810430ccb09
parent5fbcd76351eeda3479175e2dce62b342f8964e86 (diff)
downloadglibc-08504de71813ddbd447bfbca4a325cbe8ce8bcda.tar
glibc-08504de71813ddbd447bfbca4a325cbe8ce8bcda.tar.gz
glibc-08504de71813ddbd447bfbca4a325cbe8ce8bcda.tar.bz2
glibc-08504de71813ddbd447bfbca4a325cbe8ce8bcda.zip
resolv: Enable full ICMP errors for UDP DNS sockets [BZ #24047]
The Linux kernel suppresses some ICMP error messages by default for UDP sockets. This commit enables full ICMP error reporting, hopefully resulting in faster failover to working name servers.
-rw-r--r--ChangeLog10
-rw-r--r--resolv/Makefile2
-rw-r--r--resolv/res_enable_icmp.c37
-rw-r--r--resolv/res_send.c12
-rw-r--r--resolv/resolv-internal.h6
5 files changed, 66 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 9bf1e4e3c8..2f72e0f8ec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2019-03-12 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #24047]
+ resolv: Enable full ICMP errors for UDP DNS sockets
+ * resolv/res_enable_icmp.c: New file.
+ * resolv/Makefile (libresolv-routines): Add res_enable_icmp.
+ * resolv/resolv-internal.h (__res_enable_icmp): Declare.
+ * resolv/res_send.c (reopen): Call __res_enable_icmp on new
+ socket.
+
2019-03-11 Mao Han <han_mao@c-sky.com>
* elf/elf.h (EF_CSKY_ABIMASK, EF_CSKY_OTHER, EF_CSKY_PROCESSOR)
diff --git a/resolv/Makefile b/resolv/Makefile
index 8f22e6a154..ebe1b733f2 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -105,7 +105,7 @@ libresolv-routines := res_comp res_debug \
res_data res_mkquery res_query res_send \
inet_net_ntop inet_net_pton inet_neta base64 \
ns_parse ns_name ns_netint ns_ttl ns_print \
- ns_samedomain ns_date \
+ ns_samedomain ns_date res_enable_icmp \
compat-hooks compat-gethnamaddr
libanl-routines := gai_cancel gai_error gai_misc gai_notify gai_suspend \
diff --git a/resolv/res_enable_icmp.c b/resolv/res_enable_icmp.c
new file mode 100644
index 0000000000..bdc9220f08
--- /dev/null
+++ b/resolv/res_enable_icmp.c
@@ -0,0 +1,37 @@
+/* Enable full ICMP errors on a socket.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+int
+__res_enable_icmp (int family, int fd)
+{
+ int one = 1;
+ switch (family)
+ {
+ case AF_INET:
+ return setsockopt (fd, SOL_IP, IP_RECVERR, &one, sizeof (one));
+ case AF_INET6:
+ return setsockopt (fd, SOL_IPV6, IPV6_RECVERR, &one, sizeof (one));
+ default:
+ __set_errno (EAFNOSUPPORT);
+ return -1;
+ }
+}
diff --git a/resolv/res_send.c b/resolv/res_send.c
index fa040c1198..0f6ec83a7b 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -943,6 +943,18 @@ reopen (res_state statp, int *terrno, int ns)
return (-1);
}
+ /* Enable full ICMP error reporting for this
+ socket. */
+ if (__res_enable_icmp (nsap->sa_family,
+ EXT (statp).nssocks[ns]) < 0)
+ {
+ int saved_errno = errno;
+ __res_iclose (statp, false);
+ __set_errno (saved_errno);
+ *terrno = saved_errno;
+ return -1;
+ }
+
/*
* On a 4.3BSD+ machine (client and server,
* actually), sending to a nameserver datagram
diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h
index 6ab8f2af09..1500adc607 100644
--- a/resolv/resolv-internal.h
+++ b/resolv/resolv-internal.h
@@ -100,4 +100,10 @@ libc_hidden_proto (__inet_pton_length)
/* Called as part of the thread shutdown sequence. */
void __res_thread_freeres (void) attribute_hidden;
+/* The Linux kernel does not enable all ICMP messages on a UDP socket
+ by default. A call this function enables full error reporting for
+ the socket FD. FAMILY must be AF_INET or AF_INET6. Returns 0 on
+ success, -1 on failure. */
+int __res_enable_icmp (int family, int fd) attribute_hidden;
+
#endif /* _RESOLV_INTERNAL_H */