about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--NEWS32
-rw-r--r--sysdeps/posix/getaddrinfo.c47
3 files changed, 75 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index ee41c348bf..f4de7596a4 100644
--- 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 e8168363b5..0c5080025c 100644
--- 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.
 
+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.
+
 Version 2.6
 
 * New Linux interfaces: epoll_pwait, sched_getcpu.
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index adb3c4f96a..b668936095 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -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);