1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-30 22:43:12 +03:00
* resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname2_r): If res_search
	fails don't rely on errno value.
	(getanswer_r): Set *ERRNOP in error cases.

	* sysdeps/posix/getaddrinfo.c (gaih_local): Test protocol and socktype.
	(gaih_inet_serv): Return EIA_NODATA if name is known but has no
	associated data.  Test for matching numeric address and family.
	(getaddrinfo): Remember EAI_NODATA result and return this in case
	everything fails.
	Reported by Arkadiusz Miskiewicz <misiek@misiek.eu.org>.
This commit is contained in:
Ulrich Drepper
1999-09-12 19:24:42 +00:00
parent 9e5dcaa88c
commit a0bf6ac732
3 changed files with 81 additions and 42 deletions

View File

@ -1,5 +1,16 @@
1999-09-12 Ulrich Drepper <drepper@cygnus.com> 1999-09-12 Ulrich Drepper <drepper@cygnus.com>
* resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname2_r): If res_search
fails don't rely on errno value.
(getanswer_r): Set *ERRNOP in error cases.
* sysdeps/posix/getaddrinfo.c (gaih_local): Test protocol and socktype.
(gaih_inet_serv): Return EIA_NODATA if name is known but has no
associated data. Test for matching numeric address and family.
(getaddrinfo): Remember EAI_NODATA result and return this in case
everything fails.
Reported by Arkadiusz Miskiewicz <misiek@misiek.eu.org>.
* locale/programs/ld-address.c: Fix handling of non-existing * locale/programs/ld-address.c: Fix handling of non-existing
definitions for this category. Correctly ignore content of this definitions for this category. Correctly ignore content of this
category is this is necessary. category is this is necessary.

View File

@ -163,7 +163,7 @@ _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
if (n < 0) if (n < 0)
{ {
*h_errnop = h_errno; *h_errnop = h_errno;
*errnop = errno; *errnop = *h_errnop == TRY_AGAIN ? EAGAIN : ENOENT;
return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND; return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
} }
@ -342,6 +342,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
name_ok = res_dnok; name_ok = res_dnok;
break; break;
default: default:
*errnop = ENOENT;
return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */ return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */
} }
@ -356,6 +357,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
if (qdcount != 1) if (qdcount != 1)
{ {
*h_errnop = NO_RECOVERY; *h_errnop = NO_RECOVERY;
*errnop = ENOENT;
return NSS_STATUS_UNAVAIL; return NSS_STATUS_UNAVAIL;
} }
@ -390,6 +392,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
if (n >= MAXHOSTNAMELEN) if (n >= MAXHOSTNAMELEN)
{ {
*h_errnop = NO_RECOVERY; *h_errnop = NO_RECOVERY;
*errnop = ENOENT;
return NSS_STATUS_TRYAGAIN; return NSS_STATUS_TRYAGAIN;
} }
result->h_name = bp; result->h_name = bp;
@ -660,5 +663,6 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
} }
no_recovery: no_recovery:
*h_errnop = NO_RECOVERY; *h_errnop = NO_RECOVERY;
*errnop = ENOENT;
return NSS_STATUS_TRYAGAIN; return NSS_STATUS_TRYAGAIN;
} }

View File

@ -120,7 +120,7 @@ gaih_local (const char *name, const struct gaih_service *service,
struct utsname utsname; struct utsname utsname;
if ((name != NULL) || (req->ai_flags & AI_CANONNAME)) if ((name != NULL) || (req->ai_flags & AI_CANONNAME))
if (uname(&utsname)) if (uname (&utsname))
return -EAI_SYSTEM; return -EAI_SYSTEM;
if (name != NULL) if (name != NULL)
@ -132,7 +132,23 @@ gaih_local (const char *name, const struct gaih_service *service,
return GAIH_OKIFUNSPEC | -EAI_NONAME; return GAIH_OKIFUNSPEC | -EAI_NONAME;
} }
*pai = malloc (sizeof(struct addrinfo) + sizeof(struct sockaddr_un) if (req->ai_protocol || req->ai_socktype)
{
struct gaih_typeproto *tp = gaih_inet_typeproto;
for (tp++; tp->name &&
((req->ai_socktype != tp->socktype) || !req->ai_socktype) &&
((req->ai_protocol != tp->protocol) || !req->ai_protocol); tp++);
if (tp->name == NULL)
{
if (req->ai_socktype)
return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
else
return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
}
}
*pai = malloc (sizeof (struct addrinfo) + sizeof (struct sockaddr_un)
+ ((req->ai_flags & AI_CANONNAME) + ((req->ai_flags & AI_CANONNAME)
? (strlen(utsname.nodename) + 1): 0)); ? (strlen(utsname.nodename) + 1): 0));
if (*pai == NULL) if (*pai == NULL)
@ -143,8 +159,8 @@ gaih_local (const char *name, const struct gaih_service *service,
(*pai)->ai_family = AF_LOCAL; (*pai)->ai_family = AF_LOCAL;
(*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM; (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
(*pai)->ai_protocol = req->ai_protocol; (*pai)->ai_protocol = req->ai_protocol;
(*pai)->ai_addrlen = sizeof(struct sockaddr_un); (*pai)->ai_addrlen = sizeof (struct sockaddr_un);
(*pai)->ai_addr = (void *)(*pai) + sizeof(struct addrinfo); (*pai)->ai_addr = (void *) (*pai) + sizeof (struct addrinfo);
#if SALEN #if SALEN
((struct sockaddr_un *) (*pai)->ai_addr)->sun_len = ((struct sockaddr_un *) (*pai)->ai_addr)->sun_len =
@ -181,8 +197,9 @@ gaih_local (const char *name, const struct gaih_service *service,
} }
if (req->ai_flags & AI_CANONNAME) if (req->ai_flags & AI_CANONNAME)
strcpy ((*pai)->ai_canonname = (char *)(*pai) + sizeof(struct addrinfo) + (*pai)->ai_canonname = strcpy ((char *) *pai + sizeof (struct addrinfo)
sizeof(struct sockaddr_un), utsname.nodename); + sizeof (struct sockaddr_un),
utsname.nodename);
else else
(*pai)->ai_canonname = NULL; (*pai)->ai_canonname = NULL;
return 0; return 0;
@ -201,14 +218,12 @@ gaih_inet_serv (const char *servicename, struct gaih_typeproto *tp,
do do
{ {
tmpbuf = __alloca (tmpbuflen); tmpbuf = __alloca (tmpbuflen);
if (tmpbuf == NULL)
return -EAI_MEMORY;
r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen, r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
&s); &s);
if (r || s == NULL) if (r != 0 || s == NULL)
{ {
if (errno == ERANGE) if (r == ERANGE)
tmpbuflen *= 2; tmpbuflen *= 2;
else else
return GAIH_OKIFUNSPEC | -EAI_SERVICE; return GAIH_OKIFUNSPEC | -EAI_SERVICE;
@ -234,12 +249,10 @@ gaih_inet_serv (const char *servicename, struct gaih_typeproto *tp,
do { \ do { \
tmpbuflen *= 2; \ tmpbuflen *= 2; \
tmpbuf = __alloca (tmpbuflen); \ tmpbuf = __alloca (tmpbuflen); \
if (tmpbuf == NULL) \
return -EAI_MEMORY; \
rc = __gethostbyname2_r (name, _family, &th, tmpbuf, \ rc = __gethostbyname2_r (name, _family, &th, tmpbuf, \
tmpbuflen, &h, &herrno); \ tmpbuflen, &h, &herrno); \
} while (rc == ERANGE && herrno == NETDB_INTERNAL); \ } while (rc == ERANGE && herrno == NETDB_INTERNAL); \
if ((rc != 0) && (herrno == NETDB_INTERNAL)) \ if (rc != 0 && herrno == NETDB_INTERNAL) \
{ \ { \
__set_h_errno (herrno); \ __set_h_errno (herrno); \
return -EAI_SYSTEM; \ return -EAI_SYSTEM; \
@ -249,11 +262,7 @@ gaih_inet_serv (const char *servicename, struct gaih_typeproto *tp,
for (i = 0; h->h_addr_list[i]; i++) \ for (i = 0; h->h_addr_list[i]; i++) \
{ \ { \
if (*pat == NULL) \ if (*pat == NULL) \
{ \ *pat = __alloca (sizeof(struct gaih_addrtuple)); \
*pat = __alloca (sizeof(struct gaih_addrtuple)); \
if (*pat == NULL) \
return -EAI_MEMORY; \
} \
(*pat)->next = NULL; \ (*pat)->next = NULL; \
(*pat)->family = _family; \ (*pat)->family = _family; \
memcpy ((*pat)->addr, h->h_addr_list[i], \ memcpy ((*pat)->addr, h->h_addr_list[i], \
@ -261,6 +270,7 @@ gaih_inet_serv (const char *servicename, struct gaih_typeproto *tp,
pat = &((*pat)->next); \ pat = &((*pat)->next); \
} \ } \
} \ } \
no_data = rc != 0 && herrno == NO_DATA; \
} }
static int static int
@ -322,10 +332,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
} }
else else
{ {
st = __alloca (sizeof(struct gaih_servtuple)); st = __alloca (sizeof (struct gaih_servtuple));
if (st == NULL)
return -EAI_MEMORY;
st->next = NULL; st->next = NULL;
st->socktype = tp->socktype; st->socktype = tp->socktype;
st->protocol = tp->protocol; st->protocol = tp->protocol;
@ -335,45 +342,58 @@ gaih_inet (const char *name, const struct gaih_service *service,
if (name != NULL) if (name != NULL)
{ {
at = __alloca (sizeof(struct gaih_addrtuple)); at = __alloca (sizeof (struct gaih_addrtuple));
at->family = 0; at->family = AF_UNSPEC;
at->next = NULL; at->next = NULL;
if (req->ai_family == 0 || req->ai_family == AF_INET) if (inet_pton (AF_INET, name, at->addr) > 0)
if (inet_pton (AF_INET, name, at->addr) > 0) {
at->family = AF_INET; if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
at->family = AF_INET;
else
return -EAI_ADDRFAMILY;
}
if (!at->family && (req->ai_family == 0 || req->ai_family == AF_INET6)) if (at->family == AF_UNSPEC && inet_pton (AF_INET6, name, at->addr) > 0)
if (inet_pton (AF_INET6, name, at->addr) > 0) {
at->family = AF_INET6; if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
at->family = AF_INET6;
else
return -EAI_ADDRFAMILY;
}
if (at->family == AF_UNSPEC) if (at->family == AF_UNSPEC)
{ {
struct hostent *h; struct hostent *h;
struct gaih_addrtuple **pat = &at; struct gaih_addrtuple **pat = &at;
int no_data = 0;
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
gethosts (AF_INET6, struct in6_addr); gethosts (AF_INET6, struct in6_addr);
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET) if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
gethosts (AF_INET, struct in_addr); gethosts (AF_INET, struct in_addr);
if (no_data != 0)
/* We made requests but they turned out no data. The name
is known, though. */
return (GAIH_OKIFUNSPEC | -EAI_NODATA);
} }
if (at->family == AF_UNSPEC) if (at->family == AF_UNSPEC)
return (GAIH_OKIFUNSPEC | -EAI_NONAME); return (GAIH_OKIFUNSPEC | -EAI_NONAME);
} }
else else
{ {
struct gaih_addrtuple *atr; struct gaih_addrtuple *atr;
atr = at = __alloca (sizeof(struct gaih_addrtuple)); atr = at = __alloca (sizeof (struct gaih_addrtuple));
memset (at, 0, sizeof(struct gaih_addrtuple)); memset (at, '\0', sizeof (struct gaih_addrtuple));
if (req->ai_family == 0) if (req->ai_family == 0)
{ {
at->next = __alloca (sizeof(struct gaih_addrtuple)); at->next = __alloca (sizeof (struct gaih_addrtuple));
memset (at->next, 0, sizeof(struct gaih_addrtuple)); memset (at->next, '\0', sizeof (struct gaih_addrtuple));
} }
if (req->ai_family == 0 || req->ai_family == AF_INET6) if (req->ai_family == 0 || req->ai_family == AF_INET6)
@ -433,10 +453,9 @@ gaih_inet (const char *name, const struct gaih_service *service,
&h, &herrno); &h, &herrno);
} }
while ((rc != 0) && (herrno == NETDB_INTERNAL) while (rc == errno && herrno == NETDB_INTERNAL);
&& (errno == ERANGE));
if ((rc != 0) && (herrno == NETDB_INTERNAL)) if (rc != 0 && herrno == NETDB_INTERNAL)
{ {
__set_h_errno (herrno); __set_h_errno (herrno);
return -EAI_SYSTEM; return -EAI_SYSTEM;
@ -527,7 +546,7 @@ int
getaddrinfo (const char *name, const char *service, getaddrinfo (const char *name, const char *service,
const struct addrinfo *hints, struct addrinfo **pai) const struct addrinfo *hints, struct addrinfo **pai)
{ {
int i = 0, j = 0; int i = 0, j = 0, last_i = 0;
struct addrinfo *p = NULL, **end; struct addrinfo *p = NULL, **end;
struct gaih *g = gaih, *pg = NULL; struct gaih *g = gaih, *pg = NULL;
struct gaih_service gaih_service, *pservice; struct gaih_service gaih_service, *pservice;
@ -583,6 +602,11 @@ getaddrinfo (const char *name, const char *service,
i = g->gaih (name, pservice, hints, end); i = g->gaih (name, pservice, hints, end);
if (i != 0) if (i != 0)
{ {
/* EAI_NODATA is a more specific result as it says that
we found a result but it is not usable. */
if (last_i != (GAIH_OKIFUNSPEC | -EAI_NODATA))
last_i = i;
if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC)) if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC))
continue; continue;
@ -607,13 +631,13 @@ getaddrinfo (const char *name, const char *service,
return 0; return 0;
} }
if (pai == NULL && i == 0) if (pai == NULL && last_i == 0)
return 0; return 0;
if (p) if (p)
freeaddrinfo (p); freeaddrinfo (p);
return i ? -(i & GAIH_EAI) : EAI_NONAME; return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
} }
void void