git: 144361386696 - main - getaddrinfo: distinguish missing addrs from unresolvable names

From: Mike Karels <karels_at_FreeBSD.org>
Date: Wed, 02 Nov 2022 16:04:30 UTC
The branch main has been updated by karels:

URL: https://cgit.FreeBSD.org/src/commit/?id=144361386696582c04592f200a4c2e3339c81a25

commit 144361386696582c04592f200a4c2e3339c81a25
Author:     Mike Karels <karels@FreeBSD.org>
AuthorDate: 2022-11-02 15:57:59 +0000
Commit:     Mike Karels <karels@FreeBSD.org>
CommitDate: 2022-11-02 16:03:31 +0000

    getaddrinfo: distinguish missing addrs from unresolvable names
    
    Rework getaddrinfo(3) to return different error values for unresolvable
    names (same as before, EAI_NONAME) and those without a requested addr
    (EAI_ADDRFAMILY) when using DNS.  This is implemented via an added
    error in the nsswitch layer, NS_ADDRFAMILY, which is used only by
    getaddrinfo().  The error is passed through nsdispatch(3), but that
    routine has no changes to handle this error.  The error originates in
    the getaddrinfo DNS layer called via nsdispatch(), and is processed
    by the search layer that calls nsdispatch().
    
    While here, add a little style to returns near those that were
    modified.
    
    Reviewed in https://reviews.freebsd.org/D37139 with related changes.
    
    Reviewed by:    bz
    MFC after:      1 month
---
 include/nsswitch.h         |  1 +
 lib/libc/net/getaddrinfo.c | 16 +++++++++++-----
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/include/nsswitch.h b/include/nsswitch.h
index f7131292dd78..2be7a59fd1b9 100644
--- a/include/nsswitch.h
+++ b/include/nsswitch.h
@@ -53,6 +53,7 @@
 #define	NS_NOTFOUND	(1<<2)		/* source responded 'no such entry' */
 #define	NS_TRYAGAIN	(1<<3)		/* source busy, may respond to retry */
 #define NS_RETURN	(1<<4)		/* stop search, e.g. for ERANGE */
+#define NS_ADDRFAMILY	(1<<5)		/* no addr for fam, getaddrinfo only */
 #define NS_TERMINATE	(NS_SUCCESS|NS_RETURN) /* flags that end search */
 #define	NS_STATUSMASK	0x000000ff	/* bitmask to get the status flags */
 
diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c
index a33f240bc376..7d8770b4f99f 100644
--- a/lib/libc/net/getaddrinfo.c
+++ b/lib/libc/net/getaddrinfo.c
@@ -1953,6 +1953,9 @@ explore_fqdn(const struct addrinfo *pai, const char *hostname,
 	case NS_NOTFOUND:
 		error = EAI_NONAME;
 		goto free;
+	case NS_ADDRFAMILY:
+		error = EAI_ADDRFAMILY;
+		goto free;
 	case NS_SUCCESS:
 		error = 0;
 		for (cur = result; cur; cur = cur->ai_next) {
@@ -2341,7 +2344,9 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
 	if (res_searchN(hostname, &q, res) < 0) {
 		free(buf);
 		free(buf2);
-		return NS_NOTFOUND;
+		if (res->res_h_errno == NO_DATA)
+			return (NS_ADDRFAMILY);
+		return (NS_NOTFOUND);
 	}
 	/* prefer IPv6 */
 	if (q.next) {
@@ -2363,15 +2368,16 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
 	if (sentinel.ai_next == NULL)
 		switch (res->res_h_errno) {
 		case HOST_NOT_FOUND:
+			return (NS_NOTFOUND);
 		case NO_DATA:
-			return NS_NOTFOUND;
+			return (NS_ADDRFAMILY);
 		case TRY_AGAIN:
-			return NS_TRYAGAIN;
+			return (NS_TRYAGAIN);
 		default:
-			return NS_UNAVAIL;
+			return (NS_UNAVAIL);
 		}
 	*((struct addrinfo **)rv) = sentinel.ai_next;
-	return NS_SUCCESS;
+	return (NS_SUCCESS);
 }
 
 static void