diff options
author | Ulrich Drepper <drepper@redhat.com> | 2007-09-19 22:12:22 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2007-09-19 22:12:22 +0000 |
commit | e1db0493fdc908aae2a597c82dcd9fbaff14e9dc (patch) | |
tree | 50be4774a038514edb5b3d678f96417191c3289e | |
parent | c3266dc0d85ed519ff40d1738aadf7b1280af3ba (diff) | |
download | glibc-e1db0493fdc908aae2a597c82dcd9fbaff14e9dc.tar.gz |
* sysdeps/posix/getaddrinfo.c (getaddrinfo): Avoid unnecessary
open/close when determining source addresses.
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | NEWS | 32 | ||||
-rw-r--r-- | sysdeps/posix/getaddrinfo.c | 47 |
3 files changed, 75 insertions, 7 deletions
@@ -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. @@ -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); |