From patchwork Tue Feb 26 15:25:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 1048411 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-100262-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="mn3LyyBz"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4482hZ00w1z9s4Z for ; Wed, 27 Feb 2019 02:26:05 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:mime-version :content-type; q=dns; s=default; b=jgWwqWFduP0kW2G7foaW39fxlgDMk YwSQhtk64SdN6PGEHUIfmKyburnsRwTcr9o5k/8J78dMKQjiEBnO8VzUNi2+I4Sq QNnH0YGvCZ7xKz1Vn3ZN/0aPMYB/LdEMJWs1MQIU/ZYhoI5wcKf5WxoS+sNiti5b CU6tsz3l2F1YKk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:subject:date:message-id:mime-version :content-type; s=default; bh=gEJV96i706fYhDmONQdsTU37eH4=; b=mn3 LyyBzv4//ncS9cnBt6uLwi6Pp0LzJSnjZLJDppH3lxGFMBLw9EWJji9lyMsiVaCM gs2DYw0+9xhUnJsutAdTOw787Sjx76SYp8juaemxi9NyJAdOpOmnBnybTDnst2YO vzCLTRavKx+y3005UX6YjScRR1rdxE29qXQG3hZU= Received: (qmail 121135 invoked by alias); 26 Feb 2019 15:25:59 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 121109 invoked by uid 89); 26 Feb 2019 15:25:58 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=shutdown, FAMILY, DNS X-HELO: mx1.redhat.com From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH] resolv: Enable full ICMP errors for UDP DNS sockets [BZ #24047] Date: Tue, 26 Feb 2019 16:25:50 +0100 Message-ID: <87mumi6075.fsf@oldenburg2.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) MIME-Version: 1.0 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. (This change has seen some real-world testing in Fedora 30 and Fedora rawhide, with no issues reported.) 2019-02-26 Florian Weimer [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. Reviewed-by: Carlos O'Donell 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 + . */ + +#include +#include +#include + +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 */