diff options
author | Florian Weimer <fweimer@redhat.com> | 2019-03-12 11:40:47 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2019-03-12 11:40:47 +0100 |
commit | 08504de71813ddbd447bfbca4a325cbe8ce8bcda (patch) | |
tree | 220785321a7949a077d9ea8c381eb810430ccb09 | |
parent | 5fbcd76351eeda3479175e2dce62b342f8964e86 (diff) | |
download | glibc-08504de71813ddbd447bfbca4a325cbe8ce8bcda.tar.gz glibc-08504de71813ddbd447bfbca4a325cbe8ce8bcda.tar.xz 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-- | ChangeLog | 10 | ||||
-rw-r--r-- | resolv/Makefile | 2 | ||||
-rw-r--r-- | resolv/res_enable_icmp.c | 37 | ||||
-rw-r--r-- | resolv/res_send.c | 12 | ||||
-rw-r--r-- | resolv/resolv-internal.h | 6 |
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 */ |