diff options
author | Pascal Junck <pjunck@openoffice.org> | 2004-11-03 07:03:28 +0000 |
---|---|---|
committer | Pascal Junck <pjunck@openoffice.org> | 2004-11-03 07:03:28 +0000 |
commit | e5a69b854d8b5f7060a0af8f2e3a38c6ccd3f00c (patch) | |
tree | f827043a983322881d3cbb1b6da83e78456ef5cf /ucbhelper | |
parent | 43c5c4945ace3252361bd5e096ecbd8115f38c66 (diff) |
INTEGRATION: CWS ipv6ooo2 (1.3.90); FILE MERGED
2004/10/13 07:45:52 kso 1.3.90.2: #i33615# - Never call freeaddrinfo with a null pointer.
2004/10/11 15:45:07 kso 1.3.90.1: #i33615# - IPv6 support.
Diffstat (limited to 'ucbhelper')
-rw-r--r-- | ucbhelper/source/client/proxydecider.cxx | 205 |
1 files changed, 195 insertions, 10 deletions
diff --git a/ucbhelper/source/client/proxydecider.cxx b/ucbhelper/source/client/proxydecider.cxx index 1284b4333a4d..c1ce0925cda3 100644 --- a/ucbhelper/source/client/proxydecider.cxx +++ b/ucbhelper/source/client/proxydecider.cxx @@ -2,9 +2,9 @@ * * $RCSfile: proxydecider.cxx,v $ * - * $Revision: 1.3 $ + * $Revision: 1.4 $ * - * last change: $Author: vg $ $Date: 2003-07-01 14:57:56 $ + * last change: $Author: pjunck $ $Date: 2004-11-03 08:03:28 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -63,8 +63,12 @@ TODO ************************************************************************** +- remove resolveHostName function once OSL supports IPv6 + *************************************************************************/ +#define OSL_DOES_NOT_SUPPORT_IPV6 1 + #include <utility> #include <vector> @@ -74,9 +78,11 @@ #ifndef _RTL_REF_HXX_ #include <rtl/ref.hxx> #endif +#ifndef OSL_DOES_NOT_SUPPORT_IPV6 #ifndef _OSL_SOCKET_HXX_ #include <osl/socket.hxx> #endif +#endif #ifndef _RTL_USTRBUF_HXX_ #include <rtl/ustrbuf.hxx> #endif @@ -110,6 +116,124 @@ using namespace ucbhelper; #define FTP_PROXY_NAME_KEY "ooInetFTPProxyName" #define FTP_PROXY_PORT_KEY "ooInetFTPProxyPort" +#ifdef OSL_DOES_NOT_SUPPORT_IPV6 + +//========================================================================= + +#ifdef WIN32 +#include <winsock2.h> +#include <ws2tcpip.h> +#else +#include <netdb.h> +#include <unistd.h> +#endif + +namespace +{ + +rtl::OUString queryCanonicalHostName( const rtl::OUString & rHostName ) +{ + rtl::OUString aResult; + + struct addrinfo hints = { 0 }; + hints.ai_socktype = SOCK_STREAM; + + /* + AI_CANONNAME + If the nodename parameter is not a NULL pointer, the function searches + for the specified node's canonical name. + + Upon successful completion, the ai_canonname member of the first + addrinfo structure in the linked list points to a null-terminated + string containing the canonical name of the specified nodename. + + If the canonical name is not available or if AI_CANONNAME is not set, + the ai_canonname member refers to the nodename parameter or a string + with the same contents. The ai_flags field contents are undefined. + */ + hints.ai_flags = AI_CANONNAME; + + struct addrinfo * result = 0; + + if ( rHostName.indexOf( ':' ) != -1 ) + { +#ifdef AI_NUMERICHOST /* added in the RFC2553 API */ + hints.ai_flags |= AI_NUMERICHOST; +#endif + hints.ai_family = AF_INET6; + } + else + { +/* To avoid doing AAAA queries unless absolutely necessary, either use + * AI_ADDRCONFIG where available, or a run-time check for working IPv6 + * support; the latter is only known to work on Linux. */ + +#ifdef AI_ADDRCONFIG /* added in the RFC3493 API */ + hints.ai_flags |= AI_ADDRCONFIG; + hints.ai_family = AF_UNSPEC; +#else + +/* On Linux kernels, IPv6 is typically built as a loadable module, and + * socket(AF_INET6, ...) will fail if this module is not loaded, so + * the slow AAAA lookups can be avoided for this common case. */ + +#ifdef LINUX + enum ipv6_state { unknown, disabled, enabled }; + static ipv6_state ipv6 = unknown; + if ( ipv6 == unknown ) + { + osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ); + if ( ipv6 == unknown ) + { + int fd = socket( AF_INET6, SOCK_STREAM, 0 ); + if ( fd < 0 ) + { + ipv6 = disabled; + } + else + { + ipv6 = enabled; + close( fd ); + } + } + } + + OSL_ENSURE( ipv6 != unknown, "ipv6 state unknown!" ); + hints.ai_family = ( ipv6 == disabled ) ? AF_INET : AF_UNSPEC; +#else + hints.ai_family = AF_UNSPEC; +#endif /* LINUX */ + +#endif /* AI_ADDRCONFIG */ + } + + rtl::OString aHostName( + rtl::OUStringToOString( rHostName, RTL_TEXTENCODING_UTF8 ) ); + int err = getaddrinfo( aHostName.getStr(), NULL, &hints, &result ); + + if ( err == 0 ) + { + // We're only interested in the canonical name, which is always + // returned in the ai_canonname field of the first addrinfo in + // the linked list of results. + aResult = rtl::OStringToOUString( + rtl::OString( result->ai_canonname ), RTL_TEXTENCODING_UTF8 ); + } + else + { + aResult = rHostName; + } + + if ( result != 0 ) + freeaddrinfo( result ); + + return aResult; +} + +} // namespace + +#endif /* OSL_DOES_NOT_SUPPORT_IPV6 */ + //========================================================================= namespace ucbhelper { @@ -473,7 +597,22 @@ bool InternetProxyDecider_Impl::shouldUseProxy( const rtl::OUString & rHost, sal_Int32 nPort, bool bUseFullyQualified ) const { - rtl::OUStringBuffer aBuffer( rHost ); + rtl::OUStringBuffer aBuffer; + + if ( ( rHost.indexOf( ':' ) != -1 ) && + ( rHost[ 0 ] != sal_Unicode( '[' ) ) ) + { + // host is given as numeric IPv6 address + aBuffer.appendAscii( "[" ); + aBuffer.append( rHost ); + aBuffer.appendAscii( "]" ); + } + else + { + // host is given either as numeric IPv4 address or non-numeric hostname + aBuffer.append( rHost ); + } + aBuffer.append( sal_Unicode( ':' ) ); aBuffer.append( rtl::OUString::valueOf( nPort ) ); const rtl::OUString aHostAndPort( aBuffer.makeStringAndClear() ); @@ -528,23 +667,41 @@ const InternetProxyServer & InternetProxyDecider_Impl::getProxy( // Second, try match against full qualified hostname - #104401# ////////////////////////////////////////////////////////////////// + rtl::OUString aHost; + + if ( ( rHost[ 0 ] == sal_Unicode( '[' ) ) && + ( rHost.getLength() > 1 ) ) + { + // host is given as numeric IPv6 address. name resolution + // functions need hostname without square brackets. + aHost = rHost.copy( 1, rHost.getLength() - 2 ); + } + else + { + aHost = rHost; + } + // This might be quite expensive (DNS lookup). - const osl::SocketAddr aAddr( rHost, nPort ); +#ifdef OSL_DOES_NOT_SUPPORT_IPV6 + rtl::OUString aFullyQualifiedHost( + queryCanonicalHostName( aHost ).toAsciiLowerCase() ); +#else + const osl::SocketAddr aAddr( aHost, nPort ); rtl::OUString aFullyQualifiedHost( aAddr.getHostname().toAsciiLowerCase() ); - +#endif // Error resolving name? -> fallback. if ( !aFullyQualifiedHost.getLength() ) - aFullyQualifiedHost = rHost; + aFullyQualifiedHost = aHost; - if ( aFullyQualifiedHost != rHost ) + if ( aFullyQualifiedHost != aHost ) { if ( !shouldUseProxy( aFullyQualifiedHost, nPort, false ) ) return m_aEmptyProxy; } ////////////////////////////////////////////////////////////////// - // Third, try match of fully qualified entries in no-proxy lit + // Third, try match of fully qualified entries in no-proxy list // against full qualified hostname // // Example: @@ -704,7 +861,16 @@ void InternetProxyDecider_Impl::setNoProxyList( { rtl::OUString aServer; rtl::OUString aPort; - sal_Int32 nColonPos = aToken.indexOf( ':' ); + + // numerical IPv6 address? + bool bIPv6Address = false; + sal_Int32 nClosedBracketPos = aToken.indexOf( ']' ); + if ( nClosedBracketPos == -1 ) + nClosedBracketPos = 0; + else + bIPv6Address = true; + + sal_Int32 nColonPos = aToken.indexOf( ':', nClosedBracketPos ); if ( nColonPos == -1 ) { // No port given, server pattern equals current token @@ -736,12 +902,31 @@ void InternetProxyDecider_Impl::setNoProxyList( // entry specifies exactly one non-fully qualified server // name. + // remove square brackets from host name in case it's + // a numerical IPv6 address. + if ( bIPv6Address ) + aServer = aServer.copy( 1, aServer.getLength() - 2 ); + // This might be quite expensive (DNS lookup). +#ifdef OSL_DOES_NOT_SUPPORT_IPV6 + rtl::OUString aTmp + = queryCanonicalHostName( aServer ).toAsciiLowerCase(); +#else const osl::SocketAddr aAddr( aServer, 0 ); rtl::OUString aTmp = aAddr.getHostname().toAsciiLowerCase(); +#endif if ( aTmp != aServer.toAsciiLowerCase() ) { - aFullyQualifiedHost.append( aTmp ); + if ( bIPv6Address ) + { + aFullyQualifiedHost.appendAscii( "[" ); + aFullyQualifiedHost.append( aTmp ); + aFullyQualifiedHost.appendAscii( "]" ); + } + else + { + aFullyQualifiedHost.append( aTmp ); + } aFullyQualifiedHost.appendAscii( ":" ); aFullyQualifiedHost.append( aPort ); } |