From nobody Thu Jun 19 20:01:21 2025 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4bNWhL1pxCz5PSrB; Thu, 19 Jun 2025 20:01:22 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4bNWhL0WHdz3CZK; Thu, 19 Jun 2025 20:01:22 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1750363282; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=vFgz5I21c3DF6+6mzF6XlnVGJXa2Qzn1+fEP16EQZtc=; b=dAG3byi8zUMwVUVM13xb26zdcmQ4nl1vt6bzVMS42iKBNdOd3vl8GlYFR825TqO8Xv9JJi 0mcRBmRuYtANh71RRIBT46gHFTm4DH1OAafGC88Ez1X97PG7cCunDHYHUz0S5EANu0prKH ZYQScz0GkMFoAHV/eyOu6+FXQuyaa3Seoq/nQvJ0EDXIxYbmoRXoJLOvnXIBsfK1F43DHn 3sYDCaEiFZymIQeTwmbD84QtlbpggYHXPVYxjJd3sWIg390BR21k6PR/FlOBO8zMskv0MQ E6f6WQ7JeYhUFC9tizdGBCyus87pjGFVWl1FaBCBA9L9JDbraSy0yxS0MalW3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1750363282; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=vFgz5I21c3DF6+6mzF6XlnVGJXa2Qzn1+fEP16EQZtc=; b=J9L9+DgL8TUugYFJXBiv7yOcMXoQkxI/STB9NECnAHm+xJNg282Bz42aHEmEWmNEPhCQkB ddlIVFMdAdL4KdFLTr8Okh4kG6IW1fa3J+ciIr1ES0DurHsYYlS4EfPLwXA9RyTZjbEbOd cDNiEfWuPBYsGP+oRw97t1PN3yOuTW6eAwH/rksiwCyS/0Rq8ix2UFLmiZQzcoocBHtsy2 epI/QuwOeGBooe6EBXOlpLVB2kbiEEJby0/nIzjhGKoEU7xtBPOtLNaWb4IHl+i/sE5lwi RX5/zJ0PVXZfTlEAwe3DFtS0byYBZ51C2M8h88EMaFmQ8rmoZcvm06SUPQeR5A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1750363282; a=rsa-sha256; cv=none; b=U9GYf3qCZojgyq+wWmUhjNcZXtxioAa+O4jIN2Pfg9q1I0X4NwbZlDaRKTwiZaX8tBX9LZ F7GVzPEqpwYkmGpKlxKD5XQbPoYD3bUBQ6nuH+i5IpU1rTGrTxjefY5n1ih5BEgqR+OIn2 z4NhuO/B3wnNMbub67NBIBQZjUyoakzcDwR8HRZZlhXE+QgwNncmXacPfe/VbZdxJzvJp3 uksnvba/xUbxj7bOIoNkbIIOjXhuQDeY0pubFB1yERzg8bSoVtEFXmgfoXX87oL9b5ET7I wcodF0VLqNIjdSDjoeqSG6TGjPWAR9KFhdynScsZ/HV3RkkxbgW16cW1F4Mhug== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4bNWhL04kJz1S84; Thu, 19 Jun 2025 20:01:22 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 55JK1Lmw039110; Thu, 19 Jun 2025 20:01:21 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 55JK1Lcu039107; Thu, 19 Jun 2025 20:01:21 GMT (envelope-from git) Date: Thu, 19 Jun 2025 20:01:21 GMT Message-Id: <202506192001.55JK1Lcu039107@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Gleb Smirnoff Subject: git: 8d98d889e1fc - stable/14 - libc/getaddrinfo(2): return EAI_AGAIN on nameserver timeout List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: glebius X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 8d98d889e1fcdf38488b107b7191c38f3ea662d2 Auto-Submitted: auto-generated The branch stable/14 has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=8d98d889e1fcdf38488b107b7191c38f3ea662d2 commit 8d98d889e1fcdf38488b107b7191c38f3ea662d2 Author: Gleb Smirnoff AuthorDate: 2025-03-28 21:35:35 +0000 Commit: Gleb Smirnoff CommitDate: 2025-06-19 20:00:19 +0000 libc/getaddrinfo(2): return EAI_AGAIN on nameserver timeout A nameserver timeout is a soft failure, future attempts may succeed. Returning EAI_AGAIN is crucial for API users to tell a soft name resolution failure from negative resolution result. Before the change we would return EAI_ADDRFAMILY, which I believe, is a regression from 144361386696, and before that revision we used to return EAI_NONAME in most of the cases. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D49411 (cherry picked from commit d803854bccb9ea527c1769ac403e011ff0e121e5) --- lib/libc/net/getaddrinfo.c | 58 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c index 2b9499d5099b..b8af23ebe8da 100644 --- a/lib/libc/net/getaddrinfo.c +++ b/lib/libc/net/getaddrinfo.c @@ -2341,9 +2341,14 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) if (res_searchN(hostname, &q, res) < 0) { free(buf); free(buf2); - if (res->res_h_errno == NO_DATA) + switch (res->res_h_errno) { + case NO_DATA: return (NS_ADDRFAMILY); - return (NS_NOTFOUND); + case TRY_AGAIN: + return (NS_TRYAGAIN); + default: + return (NS_NOTFOUND); + } } /* prefer IPv6 */ if (q.next) { @@ -2705,9 +2710,18 @@ res_queryN(const char *name, struct res_target *target, res_state res) int n; u_int oflags; struct res_target *t; - int rcode; + u_int rcode; int ancount; + /* + * Extend rcode values in the scope of this function. The DNS header + * rcode we use in this function (hp->rcode) is limited by 4 bits, so + * anything starting from 16 is safe wrt aliasing. However, nameser.h + * already has extended enum __ns_rcode, so for future safety let's use + * even larger values. + */ +#define RCODE_UNREACH 32 +#define RCODE_TIMEDOUT 33 rcode = NOERROR; ancount = 0; @@ -2768,7 +2782,29 @@ again: printf(";; res_nquery: retry without EDNS0\n"); goto again; } - rcode = hp->rcode; /* record most recent error */ + /* + * Historically if a DNS server replied with ICMP port + * unreach res_nsend() would signal that with + * ECONNREFUSED and the upper layers would convert that + * into TRY_AGAIN. See 3a0b3b673936b and deeper. + * Also, res_nsend() may set errno to ECONNREFUSED due + * to internal failures. This may not be intentional, + * but we also treat that as soft failures. + * + * A more practical case is when a DNS server(s) were + * queried and didn't respond anything, which usually + * indicates a soft network failure. + */ + switch (errno) { + case ECONNREFUSED: + rcode = RCODE_UNREACH; + break; + case ETIMEDOUT: + rcode = RCODE_TIMEDOUT; + break; + default: + rcode = hp->rcode; + } #ifdef DEBUG if (res->options & RES_DEBUG) printf(";; res_query: send error\n"); @@ -2800,6 +2836,8 @@ again: case NXDOMAIN: RES_SET_H_ERRNO(res, HOST_NOT_FOUND); break; + case RCODE_UNREACH: + case RCODE_TIMEDOUT: case SERVFAIL: RES_SET_H_ERRNO(res, TRY_AGAIN); break; @@ -2862,10 +2900,6 @@ res_searchN(const char *name, struct res_target *target, res_state res) ret = res_querydomainN(name, NULL, target, res); if (ret > 0 || trailing_dot) return (ret); - if (errno == ECONNREFUSED) { - RES_SET_H_ERRNO(res, TRY_AGAIN); - return (-1); - } switch (res->res_h_errno) { case NO_DATA: case HOST_NOT_FOUND: @@ -2906,7 +2940,6 @@ res_searchN(const char *name, struct res_target *target, res_state res) ret = res_querydomainN(name, *domain, target, res); if (ret > 0) return (ret); - /* * If no server present, give up. * If name isn't found in this domain, @@ -2920,11 +2953,6 @@ res_searchN(const char *name, struct res_target *target, res_state res) * but try the input name below in case it's * fully-qualified. */ - if (errno == ECONNREFUSED) { - RES_SET_H_ERRNO(res, TRY_AGAIN); - return (-1); - } - switch (res->res_h_errno) { case NO_DATA: got_nodata++; @@ -2933,8 +2961,8 @@ res_searchN(const char *name, struct res_target *target, res_state res) /* keep trying */ break; case TRY_AGAIN: - got_servfail++; if (hp->rcode == SERVFAIL) { + got_servfail++; /* try next search element, if any */ break; }