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

(cherry picked from commit 1443613866)
This commit is contained in:
Mike Karels 2022-11-02 10:57:59 -05:00
parent a467b50033
commit f395174bbb
2 changed files with 12 additions and 5 deletions

View file

@ -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 */

View file

@ -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