]>
Commit | Line | Data |
---|---|---|
bdcaa78a AM |
1 | commit 08504de71813ddbd447bfbca4a325cbe8ce8bcda |
2 | Author: Florian Weimer <fweimer@redhat.com> | |
3 | Date: Tue Mar 12 11:40:47 2019 +0100 | |
4 | ||
5 | resolv: Enable full ICMP errors for UDP DNS sockets [BZ #24047] | |
6 | ||
7 | The Linux kernel suppresses some ICMP error messages by default for | |
8 | UDP sockets. This commit enables full ICMP error reporting, | |
9 | hopefully resulting in faster failover to working name servers. | |
10 | ||
11 | diff --git a/resolv/Makefile b/resolv/Makefile | |
12 | index 8f22e6a154..ebe1b733f2 100644 | |
13 | --- a/resolv/Makefile | |
14 | +++ b/resolv/Makefile | |
15 | @@ -105,7 +105,7 @@ libresolv-routines := res_comp res_debug \ | |
16 | res_data res_mkquery res_query res_send \ | |
17 | inet_net_ntop inet_net_pton inet_neta base64 \ | |
18 | ns_parse ns_name ns_netint ns_ttl ns_print \ | |
19 | - ns_samedomain ns_date \ | |
20 | + ns_samedomain ns_date res_enable_icmp \ | |
21 | compat-hooks compat-gethnamaddr | |
22 | ||
23 | libanl-routines := gai_cancel gai_error gai_misc gai_notify gai_suspend \ | |
24 | diff --git a/resolv/res_enable_icmp.c b/resolv/res_enable_icmp.c | |
25 | new file mode 100644 | |
26 | index 0000000000..bdc9220f08 | |
27 | --- /dev/null | |
28 | +++ b/resolv/res_enable_icmp.c | |
29 | @@ -0,0 +1,37 @@ | |
30 | +/* Enable full ICMP errors on a socket. | |
31 | + Copyright (C) 2019 Free Software Foundation, Inc. | |
32 | + This file is part of the GNU C Library. | |
33 | + | |
34 | + The GNU C Library is free software; you can redistribute it and/or | |
35 | + modify it under the terms of the GNU Lesser General Public | |
36 | + License as published by the Free Software Foundation; either | |
37 | + version 2.1 of the License, or (at your option) any later version. | |
38 | + | |
39 | + The GNU C Library is distributed in the hope that it will be useful, | |
40 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
41 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
42 | + Lesser General Public License for more details. | |
43 | + | |
44 | + You should have received a copy of the GNU Lesser General Public | |
45 | + License along with the GNU C Library; if not, see | |
46 | + <http://www.gnu.org/licenses/>. */ | |
47 | + | |
48 | +#include <errno.h> | |
49 | +#include <netinet/in.h> | |
50 | +#include <sys/socket.h> | |
51 | + | |
52 | +int | |
53 | +__res_enable_icmp (int family, int fd) | |
54 | +{ | |
55 | + int one = 1; | |
56 | + switch (family) | |
57 | + { | |
58 | + case AF_INET: | |
59 | + return setsockopt (fd, SOL_IP, IP_RECVERR, &one, sizeof (one)); | |
60 | + case AF_INET6: | |
61 | + return setsockopt (fd, SOL_IPV6, IPV6_RECVERR, &one, sizeof (one)); | |
62 | + default: | |
63 | + __set_errno (EAFNOSUPPORT); | |
64 | + return -1; | |
65 | + } | |
66 | +} | |
67 | diff --git a/resolv/res_send.c b/resolv/res_send.c | |
68 | index fa040c1198..0f6ec83a7b 100644 | |
69 | --- a/resolv/res_send.c | |
70 | +++ b/resolv/res_send.c | |
71 | @@ -943,6 +943,18 @@ reopen (res_state statp, int *terrno, int ns) | |
72 | return (-1); | |
73 | } | |
74 | ||
75 | + /* Enable full ICMP error reporting for this | |
76 | + socket. */ | |
77 | + if (__res_enable_icmp (nsap->sa_family, | |
78 | + EXT (statp).nssocks[ns]) < 0) | |
79 | + { | |
80 | + int saved_errno = errno; | |
81 | + __res_iclose (statp, false); | |
82 | + __set_errno (saved_errno); | |
83 | + *terrno = saved_errno; | |
84 | + return -1; | |
85 | + } | |
86 | + | |
87 | /* | |
88 | * On a 4.3BSD+ machine (client and server, | |
89 | * actually), sending to a nameserver datagram | |
90 | diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h | |
91 | index 6ab8f2af09..1500adc607 100644 | |
92 | --- a/resolv/resolv-internal.h | |
93 | +++ b/resolv/resolv-internal.h | |
94 | @@ -100,4 +100,10 @@ libc_hidden_proto (__inet_pton_length) | |
95 | /* Called as part of the thread shutdown sequence. */ | |
96 | void __res_thread_freeres (void) attribute_hidden; | |
97 | ||
98 | +/* The Linux kernel does not enable all ICMP messages on a UDP socket | |
99 | + by default. A call this function enables full error reporting for | |
100 | + the socket FD. FAMILY must be AF_INET or AF_INET6. Returns 0 on | |
101 | + success, -1 on failure. */ | |
102 | +int __res_enable_icmp (int family, int fd) attribute_hidden; | |
103 | + | |
104 | #endif /* _RESOLV_INTERNAL_H */ |