[PATCH] getnameinfo fixes
Jakub Jelinek
jakub@redhat.com
Mon Aug 28 10:09:00 GMT 2006
Hi!
http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=204122
complains that getnameinfo suffers similar problem like getaddrinfo used to
6 years ago, namely that EAI_AGAIN is not returned when it should.
While looking at it, I noticed e.g. struct hostent *h = NULL; if (h == NULL)
{ ... } bogosity, AF_INET loop not checking herrno == NETDB_INTERNAL and
when returning EAI_SYSTEM setting errno to the saved errno value from when
getnameinfo was entered (but the standard says that for EAI_SYSTEM errno
should contain the error code). I have also moved the error checking code
out of the loops, removing the need to duplicate the checks, all that
is needed to check in the loops is the NETDB_INTERNAL/ERANGE condition,
so that we can grow the buffer.
What I'm not 100% sure is what should we do in the herrno == TRY_AGAIN
case, when NI_NAMEREQD is not set in flags. The patch below will return
EAI_AGAIN for that, while previously it would return inet_ntop result.
2006-08-28 Jakub Jelinek <jakub@redhat.com>
* inet/getnameinfo.c (getnameinfo): For AF_INET, check errno
only if herrno is NETDB_INTERNAL. Handle errors other than
ERANGE outside of the loops, handle TRY_AGAIN.
--- libc/inet/getnameinfo.c.jj 2006-06-21 17:36:38.000000000 +0200
+++ libc/inet/getnameinfo.c 2006-08-28 11:47:44.000000000 +0200
@@ -203,48 +203,40 @@ getnameinfo (const struct sockaddr *sa,
if (!(flags & NI_NUMERICHOST))
{
struct hostent *h = NULL;
+ if (sa->sa_family == AF_INET6)
+ {
+ while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
+ sizeof(struct in6_addr),
+ AF_INET6, &th, tmpbuf, tmpbuflen,
+ &h, &herrno))
+ if (herrno == NETDB_INTERNAL && errno == ERANGE)
+ tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
+ else
+ break;
+ }
+ else
+ {
+ while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
+ sizeof(struct in_addr), AF_INET,
+ &th, tmpbuf, tmpbuflen,
+ &h, &herrno))
+ if (herrno == NETDB_INTERNAL && errno == ERANGE)
+ tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
+ else
+ break;
+ }
+
if (h == NULL)
{
- if (sa->sa_family == AF_INET6)
+ if (herrno == NETDB_INTERNAL)
{
- while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in6 *) sa)->sin6_addr),
- sizeof(struct in6_addr),
- AF_INET6, &th, tmpbuf, tmpbuflen,
- &h, &herrno))
- {
- if (herrno == NETDB_INTERNAL)
- {
- if (errno == ERANGE)
- tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
- 2 * tmpbuflen);
- else
- {
- __set_h_errno (herrno);
- __set_errno (serrno);
- return EAI_SYSTEM;
- }
- }
- else
- {
- break;
- }
- }
+ __set_h_errno (herrno);
+ return EAI_SYSTEM;
}
- else
+ if (herrno == TRY_AGAIN)
{
- while (__gethostbyaddr_r ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr),
- sizeof(struct in_addr), AF_INET,
- &th, tmpbuf, tmpbuflen,
- &h, &herrno))
- {
- if (errno == ERANGE)
- tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
- 2 * tmpbuflen);
- else
- {
- break;
- }
- }
+ __set_h_errno (herrno);
+ return EAI_AGAIN;
}
}
@@ -361,10 +353,7 @@ getnameinfo (const struct sockaddr *sa,
(const void *) &(((const struct sockaddr_in *) sa)->sin_addr),
host, hostlen);
if (c == NULL)
- {
- __set_errno (serrno);
- return EAI_SYSTEM;
- }
+ return EAI_SYSTEM;
}
ok = 1;
}
Jakub
More information about the Libc-hacker
mailing list