* [musl] EAI_NODATA in musl @ 2022-09-19 22:14 Rich Felker 2022-09-19 22:26 ` Rich Felker 0 siblings, 1 reply; 4+ messages in thread From: Rich Felker @ 2022-09-19 22:14 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 852 bytes --] I just posted on libc-coord about an idea that sounded good, and it turns out glibc and nearly everyone else have had it for a long time: https://www.openwall.com/lists/libc-coord/2022/09/19/2 I'd like to bring the same to musl, even though it's not standardized yet, since it's a clear candidate for standardization and solves a major problem with the libc DNS API, namely inability to distinguish NxDomain from NODATA. Aside from that, it should help justify musl's distinguishing of these two (very different) results in how search domain fallbacks work and how results for one of the A or AAAA erroring out get handled. Our misleadingly reporting "name exists but has no address" as "name doesn't exist" has made it hard for folks to understand why we don't keep going on the search when "name does not exist". Draft patch attached, untested. [-- Attachment #2: nodata.diff --] [-- Type: text/plain, Size: 1525 bytes --] diff --git a/include/netdb.h b/include/netdb.h index d096c781..3af065e2 100644 --- a/include/netdb.h +++ b/include/netdb.h @@ -44,6 +44,7 @@ struct addrinfo { #define EAI_NONAME -2 #define EAI_AGAIN -3 #define EAI_FAIL -4 +#define EAI_NODATA -5 #define EAI_FAMILY -6 #define EAI_SOCKTYPE -7 #define EAI_SERVICE -8 diff --git a/src/network/gai_strerror.c b/src/network/gai_strerror.c index 9596580e..56b71503 100644 --- a/src/network/gai_strerror.c +++ b/src/network/gai_strerror.c @@ -6,7 +6,7 @@ static const char msgs[] = "Name does not resolve\0" "Try again\0" "Non-recoverable error\0" - "Unknown error\0" + "Name has no usable address\0" "Unrecognized address family or invalid length\0" "Unrecognized socket type\0" "Unrecognized service\0" diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index bec6ba22..37d481f9 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -79,7 +79,7 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati case 0: continue; default: - badfam = EAI_NONAME; + badfam = EAI_NODATA; break; } @@ -175,7 +175,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx); if (ctx.cnt) return ctx.cnt; - return EAI_NONAME; + return EAI_NODATA; } static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family) ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [musl] EAI_NODATA in musl 2022-09-19 22:14 [musl] EAI_NODATA in musl Rich Felker @ 2022-09-19 22:26 ` Rich Felker 2022-09-19 23:31 ` Rich Felker 0 siblings, 1 reply; 4+ messages in thread From: Rich Felker @ 2022-09-19 22:26 UTC (permalink / raw) To: musl On Mon, Sep 19, 2022 at 06:14:03PM -0400, Rich Felker wrote: > I just posted on libc-coord about an idea that sounded good, and it > turns out glibc and nearly everyone else have had it for a long time: > > https://www.openwall.com/lists/libc-coord/2022/09/19/2 > > I'd like to bring the same to musl, even though it's not standardized > yet, since it's a clear candidate for standardization and solves a > major problem with the libc DNS API, namely inability to distinguish > NxDomain from NODATA. > > Aside from that, it should help justify musl's distinguishing of these > two (very different) results in how search domain fallbacks work and > how results for one of the A or AAAA erroring out get handled. Our > misleadingly reporting "name exists but has no address" as "name > doesn't exist" has made it hard for folks to understand why we don't > keep going on the search when "name does not exist". > > Draft patch attached, untested. > > diff --git a/include/netdb.h b/include/netdb.h > index d096c781..3af065e2 100644 > --- a/include/netdb.h > +++ b/include/netdb.h > @@ -44,6 +44,7 @@ struct addrinfo { > #define EAI_NONAME -2 > #define EAI_AGAIN -3 > #define EAI_FAIL -4 > +#define EAI_NODATA -5 > #define EAI_FAMILY -6 > #define EAI_SOCKTYPE -7 > #define EAI_SERVICE -8 > diff --git a/src/network/gai_strerror.c b/src/network/gai_strerror.c > index 9596580e..56b71503 100644 > --- a/src/network/gai_strerror.c > +++ b/src/network/gai_strerror.c > @@ -6,7 +6,7 @@ static const char msgs[] = > "Name does not resolve\0" > "Try again\0" > "Non-recoverable error\0" > - "Unknown error\0" > + "Name has no usable address\0" > "Unrecognized address family or invalid length\0" > "Unrecognized socket type\0" > "Unrecognized service\0" > diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c > index bec6ba22..37d481f9 100644 > --- a/src/network/lookup_name.c > +++ b/src/network/lookup_name.c > @@ -79,7 +79,7 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati > case 0: > continue; > default: > - badfam = EAI_NONAME; > + badfam = EAI_NODATA; > break; > } > > @@ -175,7 +175,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static > __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx); > > if (ctx.cnt) return ctx.cnt; > - return EAI_NONAME; > + return EAI_NODATA; > } > > static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family) Some details to work out: 1. getaddrinfo errors out with EAI_NONAME early when AI_ADDRCONFIG finds that the requested address family is not configured. The logic here probably needs to be changed to still perform a lookup but suppress the results if all requested families were precluded by AI_ADDRCONFIG. 2. gethostbyname* need to process EAI_NODATA and convert to (already existing) NO_DATA. 3. There was one other point where EAI_NONAME appeared in lookup_name.c but it was wrong and just fixed by 1e7fb12f77. Anything else? Rich ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [musl] EAI_NODATA in musl 2022-09-19 22:26 ` Rich Felker @ 2022-09-19 23:31 ` Rich Felker 2022-09-21 15:41 ` Rich Felker 0 siblings, 1 reply; 4+ messages in thread From: Rich Felker @ 2022-09-19 23:31 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 698 bytes --] On Mon, Sep 19, 2022 at 06:26:07PM -0400, Rich Felker wrote: > [...] > > Some details to work out: > > 1. getaddrinfo errors out with EAI_NONAME early when AI_ADDRCONFIG > finds that the requested address family is not configured. The > logic here probably needs to be changed to still perform a lookup > but suppress the results if all requested families were precluded > by AI_ADDRCONFIG. > > 2. gethostbyname* need to process EAI_NODATA and convert to (already > existing) NO_DATA. > > 3. There was one other point where EAI_NONAME appeared in > lookup_name.c but it was wrong and just fixed by 1e7fb12f77. > > Anything else? Updated patch attached addressing the above. [-- Attachment #2: nodata2.diff --] [-- Type: text/plain, Size: 3027 bytes --] diff --git a/include/netdb.h b/include/netdb.h index d096c781..3af065e2 100644 --- a/include/netdb.h +++ b/include/netdb.h @@ -44,6 +44,7 @@ struct addrinfo { #define EAI_NONAME -2 #define EAI_AGAIN -3 #define EAI_FAIL -4 +#define EAI_NODATA -5 #define EAI_FAMILY -6 #define EAI_SOCKTYPE -7 #define EAI_SERVICE -8 diff --git a/src/network/gai_strerror.c b/src/network/gai_strerror.c index 9596580e..56b71503 100644 --- a/src/network/gai_strerror.c +++ b/src/network/gai_strerror.c @@ -6,7 +6,7 @@ static const char msgs[] = "Name does not resolve\0" "Try again\0" "Non-recoverable error\0" - "Unknown error\0" + "Name has no usable address\0" "Unrecognized address family or invalid length\0" "Unrecognized socket type\0" "Unrecognized service\0" diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c index 9df045f6..64ad259a 100644 --- a/src/network/getaddrinfo.c +++ b/src/network/getaddrinfo.c @@ -16,6 +16,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru char canon[256], *outcanon; int nservs, naddrs, nais, canon_len, i, j, k; int family = AF_UNSPEC, flags = 0, proto = 0, socktype = 0; + int no_family = 0; struct aibuf *out; if (!host && !serv) return EAI_NONAME; @@ -82,7 +83,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru default: return EAI_SYSTEM; } - if (family == tf[i]) return EAI_NONAME; + if (family == tf[i]) no_family = 1; family = tf[1-i]; } } @@ -93,6 +94,8 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru naddrs = __lookup_name(addrs, canon, host, family, flags); if (naddrs < 0) return naddrs; + if (no_family) return EAI_NODATA; + nais = nservs * naddrs; canon_len = strlen(canon); out = calloc(1, nais * sizeof(*out) + canon_len + 1); diff --git a/src/network/gethostbyname2_r.c b/src/network/gethostbyname2_r.c index c9f3acc4..a5eb67fe 100644 --- a/src/network/gethostbyname2_r.c +++ b/src/network/gethostbyname2_r.c @@ -23,6 +23,9 @@ int gethostbyname2_r(const char *name, int af, case EAI_NONAME: *err = HOST_NOT_FOUND; return 0; + case EAI_NODATA: + *err = NO_DATA; + return 0; case EAI_AGAIN: *err = TRY_AGAIN; return EAGAIN; diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index bec6ba22..37d481f9 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -79,7 +79,7 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati case 0: continue; default: - badfam = EAI_NONAME; + badfam = EAI_NODATA; break; } @@ -175,7 +175,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx); if (ctx.cnt) return ctx.cnt; - return EAI_NONAME; + return EAI_NODATA; } static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family) ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [musl] EAI_NODATA in musl 2022-09-19 23:31 ` Rich Felker @ 2022-09-21 15:41 ` Rich Felker 0 siblings, 0 replies; 4+ messages in thread From: Rich Felker @ 2022-09-21 15:41 UTC (permalink / raw) To: musl On Mon, Sep 19, 2022 at 07:31:04PM -0400, Rich Felker wrote: > On Mon, Sep 19, 2022 at 06:26:07PM -0400, Rich Felker wrote: > > [...] > > > > Some details to work out: > > > > 1. getaddrinfo errors out with EAI_NONAME early when AI_ADDRCONFIG > > finds that the requested address family is not configured. The > > logic here probably needs to be changed to still perform a lookup > > but suppress the results if all requested families were precluded > > by AI_ADDRCONFIG. > > > > 2. gethostbyname* need to process EAI_NODATA and convert to (already > > existing) NO_DATA. > > > > 3. There was one other point where EAI_NONAME appeared in > > lookup_name.c but it was wrong and just fixed by 1e7fb12f77. > > > > Anything else? > > Updated patch attached addressing the above. > diff --git a/include/netdb.h b/include/netdb.h > index d096c781..3af065e2 100644 > --- a/include/netdb.h > +++ b/include/netdb.h > @@ -44,6 +44,7 @@ struct addrinfo { > #define EAI_NONAME -2 > #define EAI_AGAIN -3 > #define EAI_FAIL -4 > +#define EAI_NODATA -5 > #define EAI_FAMILY -6 > #define EAI_SOCKTYPE -7 > #define EAI_SERVICE -8 > diff --git a/src/network/gai_strerror.c b/src/network/gai_strerror.c > index 9596580e..56b71503 100644 > --- a/src/network/gai_strerror.c > +++ b/src/network/gai_strerror.c > @@ -6,7 +6,7 @@ static const char msgs[] = > "Name does not resolve\0" > "Try again\0" > "Non-recoverable error\0" > - "Unknown error\0" > + "Name has no usable address\0" > "Unrecognized address family or invalid length\0" > "Unrecognized socket type\0" > "Unrecognized service\0" > diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c > index 9df045f6..64ad259a 100644 > --- a/src/network/getaddrinfo.c > +++ b/src/network/getaddrinfo.c > @@ -16,6 +16,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru > char canon[256], *outcanon; > int nservs, naddrs, nais, canon_len, i, j, k; > int family = AF_UNSPEC, flags = 0, proto = 0, socktype = 0; > + int no_family = 0; > struct aibuf *out; > > if (!host && !serv) return EAI_NONAME; > @@ -82,7 +83,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru > default: > return EAI_SYSTEM; > } > - if (family == tf[i]) return EAI_NONAME; > + if (family == tf[i]) no_family = 1; > family = tf[1-i]; > } > } > @@ -93,6 +94,8 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru > naddrs = __lookup_name(addrs, canon, host, family, flags); > if (naddrs < 0) return naddrs; > > + if (no_family) return EAI_NODATA; > + > nais = nservs * naddrs; > canon_len = strlen(canon); > out = calloc(1, nais * sizeof(*out) + canon_len + 1); > diff --git a/src/network/gethostbyname2_r.c b/src/network/gethostbyname2_r.c > index c9f3acc4..a5eb67fe 100644 > --- a/src/network/gethostbyname2_r.c > +++ b/src/network/gethostbyname2_r.c > @@ -23,6 +23,9 @@ int gethostbyname2_r(const char *name, int af, > case EAI_NONAME: > *err = HOST_NOT_FOUND; > return 0; > + case EAI_NODATA: > + *err = NO_DATA; > + return 0; > case EAI_AGAIN: > *err = TRY_AGAIN; > return EAGAIN; > diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c > index bec6ba22..37d481f9 100644 > --- a/src/network/lookup_name.c > +++ b/src/network/lookup_name.c > @@ -79,7 +79,7 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati > case 0: > continue; > default: > - badfam = EAI_NONAME; > + badfam = EAI_NODATA; > break; > } > > @@ -175,7 +175,7 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static > __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx); > > if (ctx.cnt) return ctx.cnt; > - return EAI_NONAME; > + return EAI_NODATA; > } > > static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family) One more thing: presently IP literals with address family mismatching the request error with EAI_NONAME. glibc has an error EAI_ADDRFAMILY for this, but semantically it's equivalent to the above proposed EAI_NODATA: "Name has no usable address" and I think we should just use EAI_NODATA here. In principle EAI_ADDRFAMILY would be nice if it could tell the caller (definitively) "this name *does* have an address of some sort, but not in the requested address family or as limited by AI_ADDRCONFIG". But doing this requires always looking up both v4 and v6 even when the caller did not ask for them. That is, it introduces a distinction that requires more work just to give a more specific error. IMO this is not a good thing unless the specificity would actually have some use, which it doesn't seem to here. And indeed glibc doesn't do that either. It only uses EAI_ADDRFAMILY for IP literals. So, in addition to the above patch, for now I propose just changing __lookup_ipliteral to return EAI_NODATA for mismatching family instead of EAI_NONANE. We could add EAI_ADDRFAMILY with behavior matching glibc later if we really want to. Rich ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-09-21 15:41 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-09-19 22:14 [musl] EAI_NODATA in musl Rich Felker 2022-09-19 22:26 ` Rich Felker 2022-09-19 23:31 ` Rich Felker 2022-09-21 15:41 ` Rich Felker
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/musl/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).