Set IP(V6)_RECVERR on connect UDP sockets (via libuv)

The connect()ed UDP socket provides feedback on a variety of ICMP
errors (eg port unreachable) which bind can then use to decide what to
do with errors (report them to the client, try again with a different
nameserver etc).  However, Linux's implementation does not report what
it considers "transient" conditions, which is defined as Destination
host Unreachable, Destination network unreachable, Source Route Failed
and Message Too Big.

Explicitly enable IP_RECVERR / IPV6_RECVERR (via libuv uv_udp_bind()
flag) to learn about ICMP destination network/host unreachable.
This commit is contained in:
Ondřej Surý 2022-04-25 14:09:44 +02:00
parent 7b506384f0
commit 407b37c3f2
2 changed files with 7 additions and 0 deletions

View file

@ -562,6 +562,9 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <sys/socket.h>],
[AC_MSG_RESULT([no])
AC_CHECK_DECLS([UV_UDP_RECVMMSG], [], [], [[#include <uv.h>]])])
# libuv recverr support
AC_CHECK_DECLS([UV_UDP_LINUX_RECVERR], [], [], [[#include <uv.h>]])
# [pairwise: --enable-doh --with-libnghttp2=auto, --enable-doh --with-libnghttp2=yes, --disable-doh]
AC_ARG_ENABLE([doh],
[AS_HELP_STRING([--disable-doh], [enable DNS over HTTPS, requires libnghttp2 (default=yes)])],

View file

@ -882,6 +882,10 @@ udp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
uv_bind_flags |= UV_UDP_IPV6ONLY;
}
#if HAVE_DECL_UV_UDP_LINUX_RECVERR
uv_bind_flags |= UV_UDP_LINUX_RECVERR;
#endif
r = uv_udp_bind(&sock->uv_handle.udp, &sock->iface.type.sa,
uv_bind_flags);
if (r != 0) {