summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-09-19 22:12:22 +0000
committerUlrich Drepper <drepper@redhat.com>2007-09-19 22:12:22 +0000
commite1db0493fdc908aae2a597c82dcd9fbaff14e9dc (patch)
tree50be4774a038514edb5b3d678f96417191c3289e
parentc3266dc0d85ed519ff40d1738aadf7b1280af3ba (diff)
downloadglibc-e1db0493fdc908aae2a597c82dcd9fbaff14e9dc.tar.gz
* sysdeps/posix/getaddrinfo.c (getaddrinfo): Avoid unnecessary
open/close when determining source addresses.
-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);