* sysdeps/posix/getaddrinfo.c (getaddrinfo): Avoid unnecessary
authorUlrich Drepper <drepper@redhat.com>
Wed, 19 Sep 2007 22:12:22 +0000 (22:12 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 19 Sep 2007 22:12:22 +0000 (22:12 +0000)
open/close when determining source addresses.

ChangeLog
NEWS
sysdeps/posix/getaddrinfo.c

index ee41c34..f4de759 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2007-09-19  Ulrich Drepper  <drepper@redhat.com>
 
+       * sysdeps/posix/getaddrinfo.c (getaddrinfo): Avoid unnecessary
+       open/close when determining source addresses.
+
        * crypt/Makefile (libcrypt-routines): Add sha256-crypt, sha256,
        sha512-crypt, and sha512.
        (tests): Add sha256test, sha256c-test, sha512test, and sha512c-test.
diff --git a/NEWS b/NEWS
index e816836..0c50800 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,10 +1,40 @@
-GNU C Library NEWS -- history of user-visible changes.  2007-4-25
+GNU C Library NEWS -- history of user-visible changes.  2007-9-19
 Copyright (C) 1992-2006, 2007 Free Software Foundation, Inc.
 See the end for copying conditions.
 
 Please send GNU C library bug reports via <http://sources.redhat.com/bugzilla/>
 using `glibc' in the "product" field.
 \f
+Version 2.7
+
+* More checking functions: fread, fread_unlocked, open*, mq_open.
+  Implemented by Jakub Jelinek and Ulrich Drepper.
+
+* Extend fortification to C++.  Implemented by Jakub Jelinek.
+
+* Implement 'm' modifier for scanf.  Add stricter C99/SUS compliance
+  by not recognizing 'a' as a modifier when those specs are requested.
+  Implemented by Jakub Jelinek.
+
+* PPC optimizations to math and string functions.
+  Implemented by Steven Munroe.
+
+* New interfaces: mkostemp, mkostemp64.  Like mkstemp* but allow additonal
+  options to be passed.  Implemented by Ulrich Drepper.
+
+* More CPU set manipulation functions.  Implemented by Ulrich Drepper.
+
+* Handle private futexes in the NPTL implementation.
+  Implemented by Jakub Jelinek and Ulrich Drepper.
+
+* Add support for O_CLOEXEC.  Implement in Hurd.  Use throughout libc.
+  Implemented by Roland McGrath and Ulrich Drepper.
+
+* Linux/x86-64 vDSO support.  Implemented by Ulrich Drepper.
+
+* SHA-256 and SHA-512 based password encryption.
+  Implemented by Ulrich Drepper.
+\f
 Version 2.6
 
 * New Linux interfaces: epoll_pwait, sched_getcpu.
index adb3c4f..b668936 100644 (file)
@@ -1944,6 +1944,9 @@ getaddrinfo (const char *name, const char *service,
       if (in6ai != NULL)
        qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
 
+      int fd = -1;
+      int af = AF_UNSPEC;
+
       for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
        {
          results[i].dest_addr = q;
@@ -1968,7 +1971,21 @@ getaddrinfo (const char *name, const char *service,
                 want connect() to connect to the other side.  If we
                 cannot determine the source address remember this
                 fact.  */
-             int fd = __socket (q->ai_family, SOCK_DGRAM, IPPROTO_IP);
+             if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
+               {
+                 if (fd != -1)
+                 close_retry:
+                   close (fd);
+                 af = q->ai_family;
+                 fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
+               }
+             else
+               {
+                 /* Reset the connection.  */
+                 struct sockaddr sa = { .sa_family = AF_UNSPEC };
+                 __connect (fd, &sa, sizeof (sa));
+               }
+
              socklen_t sl = sizeof (results[i].source_addr);
              if (fd != -1
                  && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
@@ -1979,9 +1996,9 @@ getaddrinfo (const char *name, const char *service,
                  results[i].source_addr_len = sl;
                  results[i].got_source_addr = true;
 
-                 if (q->ai_family == PF_INET6 && in6ai != NULL)
+                 if (q->ai_family == AF_INET6 && in6ai != NULL)
                    {
-                     /* See whether the source address is the list of
+                     /* See whether the source address is on the list of
                         deprecated or temporary addresses.  */
                      struct in6addrinfo tmp;
                      struct sockaddr_in6 *sin6p
@@ -1994,14 +2011,29 @@ getaddrinfo (const char *name, const char *service,
                      if (found != NULL)
                        results[i].source_addr_flags = found->flags;
                    }
+                 else if (q->ai_family == AF_INET && af == AF_INET6)
+                   {
+                     /* We have to convert the address.  The socket is
+                        IPv6 and the request is for IPv4.  */
+                     struct sockaddr_in6 *sin6
+                       = (struct sockaddr_in6 *) &results[i].source_addr;
+                     struct sockaddr_in *sin
+                       = (struct sockaddr_in *) &results[i].source_addr;
+                     assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
+                     memcpy (&sin->sin_addr,
+                             &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
+                     results[i].source_addr_len = INADDRSZ;
+                     sin->sin_family = AF_INET;
+                   }
                }
+             else if (errno == EAFNOSUPPORT && af == AF_INET6
+                      && q->ai_family == AF_INET)
+               /* This could mean IPv6 sockets are IPv6-only.  */
+               goto close_retry;
              else
                /* Just make sure that if we have to process the same
                   address again we do not copy any memory.  */
                results[i].source_addr_len = 0;
-
-             if (fd != -1)
-               close_not_cancel_no_status (fd);
            }
 
          /* Remember the canonical name.  */
@@ -2013,6 +2045,9 @@ getaddrinfo (const char *name, const char *service,
            }
        }
 
+      if (fd != -1)
+       close_not_cancel_no_status (fd);
+
       /* We got all the source addresses we can get, now sort using
         the information.  */
       qsort (results, nresults, sizeof (results[0]), rfc3484_sort);