Fix IPv6-only lookups through getaddrinfo

A recent patch introduced a problem where IPv6 lookups happily returned
IPv4 addresses.
This commit is contained in:
Ulrich Drepper 2011-06-21 17:03:38 -04:00
parent c5e3c2ae59
commit c0244a9ded
3 changed files with 40 additions and 4 deletions

View File

@ -1,5 +1,9 @@
2011-06-21 Ulrich Drepper <drepper@gmail.com> 2011-06-21 Ulrich Drepper <drepper@gmail.com>
[BZ #12885]
* sysdeps/posix/getaddrinfo.c (gaih_inet): When looking up only IPv6
addresses using gethostbyname4_r ignore IPv4 addresses.
* sysdeps/posix/getaddrinfo.c (gaih_inet): After the last change the * sysdeps/posix/getaddrinfo.c (gaih_inet): After the last change the
branch using gethostbyname2 is only for AF_INET. Optimize accordingly. branch using gethostbyname2 is only for AF_INET. Optimize accordingly.

6
NEWS
View File

@ -1,4 +1,4 @@
GNU C Library NEWS -- history of user-visible changes. 2011-6-15 GNU C Library NEWS -- history of user-visible changes. 2011-6-21
Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc. Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc.
See the end for copying conditions. See the end for copying conditions.
@ -7,6 +7,10 @@ using `glibc' in the "product" field.
Version 2.15 Version 2.15
* The following bugs are resolved with this release:
12885
* New program pldd to list loaded object of a process * New program pldd to list loaded object of a process
Implemented by Ulrich Drepper. Implemented by Ulrich Drepper.

View File

@ -871,16 +871,44 @@ gaih_inet (const char *name, const struct gaih_service *service,
} }
} }
no_inet6_data = no_data;
if (status == NSS_STATUS_SUCCESS) if (status == NSS_STATUS_SUCCESS)
{ {
assert (!no_data);
no_data = 1;
if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL) if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
canon = (*pat)->name; canon = (*pat)->name;
while (*pat != NULL) while (*pat != NULL)
pat = &((*pat)->next); {
if ((*pat)->family == AF_INET
&& req->ai_family == AF_INET6
&& (req->ai_flags & AI_V4MAPPED) != 0)
{
uint32_t *pataddr = (*pat)->addr;
(*pat)->family = AF_INET6;
pataddr[3] = pataddr[0];
pataddr[2] = htonl (0xffff);
pataddr[1] = 0;
pataddr[0] = 0;
pat = &((*pat)->next);
no_data = 0;
}
else if ((*pat)->family == AF_UNSPEC
|| (*pat)->family == req->ai_family)
{
pat = &((*pat)->next);
no_data = 0;
if (req->ai_family == AF_INET6)
got_ipv6 = true;
}
else
*pat = ((*pat)->next);
}
} }
no_inet6_data = no_data;
} }
else else
{ {