Fix IPv6-only lookups through getaddrinfo
authorUlrich Drepper <drepper@gmail.com>
Tue, 21 Jun 2011 21:03:38 +0000 (17:03 -0400)
committerUlrich Drepper <drepper@gmail.com>
Tue, 21 Jun 2011 21:03:38 +0000 (17:03 -0400)
A recent patch introduced a problem where IPv6 lookups happily returned
IPv4 addresses.

ChangeLog
NEWS
sysdeps/posix/getaddrinfo.c

index 19807a9..abc4894 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 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
        branch using gethostbyname2 is only for AF_INET.  Optimize accordingly.
 
diff --git a/NEWS b/NEWS
index dd00b7b..9e6832c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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.
 See the end for copying conditions.
 
@@ -7,6 +7,10 @@ using `glibc' in the "product" field.
 \f
 Version 2.15
 
+* The following bugs are resolved with this release:
+
+  12885
+
 * New program pldd to list loaded object of a process
   Implemented by Ulrich Drepper.
 
index d68ac83..3a2737e 100644 (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)
                    {
+                     assert (!no_data);
+                     no_data = 1;
+
                      if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
                        canon = (*pat)->name;
 
                      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
                {