From 1fb0039732ed13fb0b7f892fb851b9ce770e0791 Mon Sep 17 00:00:00 2001 From: imaginos Date: Fri, 28 Mar 2008 05:09:48 +0000 Subject: [PATCH] reverse the order of dns lookup on bind vs dns lookup on remote host. this also does a check on each ip returned by getaddrinfo to be sure its able to connect to that host git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@994 726aef4b-f618-498e-8847-2d620e286838 --- Csocket.cpp | 56 ++++++++++++++++++++++++++++++++++++----------------- Csocket.h | 34 +++++++++++++++++--------------- 2 files changed, 56 insertions(+), 34 deletions(-) diff --git a/Csocket.cpp b/Csocket.cpp index 46eeac8d..d113b4e7 100644 --- a/Csocket.cpp +++ b/Csocket.cpp @@ -28,7 +28,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * -* $Revision: 1.68 $ +* $Revision: 1.70 $ */ #include "Csocket.h" @@ -186,6 +186,7 @@ int GetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockA hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; + int iRet = getaddrinfo( sHostname.c_str(), NULL, &hints, &res ); if( iRet == EAI_AGAIN ) return( EAGAIN ); @@ -203,9 +204,24 @@ int GetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockA if( ( pRes->ai_socktype != SOCK_STREAM ) || ( pRes->ai_protocol != IPPROTO_TCP ) ) #endif /* __sun work around broken impl of getaddrinfo */ continue; - + if( ( csSockAddr.GetAFRequire() != CSSockAddr::RAF_ANY ) && ( pRes->ai_family != csSockAddr.GetAFRequire() ) ) continue; // they requested a special type, so be certain we woop past anything unwanted + if( csSockAddr.GetAFRequire() == CSSockAddr::RAF_ANY ) + { + // this is a quick check to see if we can connect to this type of outside port (ipv6 or ipv4) + // this doesn't do an actual connection (man connect), but its a great way to validate a possible connection canidate + bool bContinue = false; + int iTestFD = socket( pRes->ai_family, SOCK_DGRAM, IPPROTO_IP ); + if( iTestFD >= 0 ) + { + if( connect( iTestFD, pRes->ai_addr, pRes->ai_addrlen ) != 0 ) + bContinue = true; // skip this one, we can't use it + } + close( iTestFD ); + if( bContinue ) + continue; + } if( pRes->ai_family == AF_INET ) { @@ -267,7 +283,9 @@ int GetAddrInfo( const CS_STRING & sHostname, Csock *pSock, CSSockAddr & csSockA } freeaddrinfo( res ); if( pUseAddr ) // the data pointed to here is invalid now, but the pointer itself is a good test + { return( 0 ); + } } #endif /* ! HAVE_IPV6 */ return( ETIMEDOUT ); @@ -651,7 +669,6 @@ void Csock::Copy( const Csock & cCopy ) m_sCipherType = cCopy.m_sCipherType; m_sParentName = cCopy.m_sParentName; m_sSend = cCopy.m_sSend; - m_sSSLBuffer = cCopy.m_sSSLBuffer; m_sPemPass = cCopy.m_sPemPass; m_sLocalIP = cCopy.m_sLocalIP; m_sRemoteIP = cCopy.m_sRemoteIP; @@ -672,6 +689,8 @@ void Csock::Copy( const Csock & cCopy ) m_bIsIPv6 = cCopy.m_bIsIPv6; #ifdef HAVE_LIBSSL + m_sSSLBuffer = cCopy.m_sSSLBuffer; + FREE_SSL(); FREE_CTX(); // be sure to remove anything that was already here m_ssl = cCopy.m_ssl; @@ -772,18 +791,6 @@ bool Csock::Connect( const CS_STRING & sBindHost, bool bSkipSetup ) m_sBindHost = sBindHost; if ( !bSkipSetup ) { - int iDNSRet = ETIMEDOUT; - while( true ) - { - iDNSRet = DNSLookup( DNS_VHOST ); - if ( iDNSRet == EAGAIN ) - continue; - - break; - } - if ( iDNSRet != 0 ) - return( false ); - if ( !sBindHost.empty() ) { // try to bind 3 times, otherwise exit failure @@ -805,6 +812,19 @@ bool Csock::Connect( const CS_STRING & sBindHost, bool bSkipSetup ) return( false ); } } + + int iDNSRet = ETIMEDOUT; + while( true ) + { + iDNSRet = DNSLookup( DNS_VHOST ); + if ( iDNSRet == EAGAIN ) + continue; + + break; + } + if ( iDNSRet != 0 ) + return( false ); + } // set it none blocking @@ -2040,7 +2060,7 @@ int Csock::DNSLookup( EDNSLType eDNSLType ) if ( m_sBindHost.empty() ) { if ( m_eConState != CST_OK ) - m_eConState = CST_BINDVHOST; + m_eConState = CST_VHOSTDNS; return( 0 ); } @@ -2095,7 +2115,7 @@ int Csock::DNSLookup( EDNSLType eDNSLType ) } if ( m_eConState != CST_OK ) - m_eConState = ( ( eDNSLType == DNS_VHOST ) ? CST_BINDVHOST : CST_VHOSTDNS ); + m_eConState = ( ( eDNSLType == DNS_VHOST ) ? CST_VHOSTDNS : CST_CONNECT ); if( !CreateSocksFD() ) return( ETIMEDOUT ); @@ -2134,7 +2154,7 @@ int Csock::DNSLookup( EDNSLType eDNSLType ) if ( iRet == 0 ) { if ( m_eConState != CST_OK ) - m_eConState = ( ( eDNSLType == DNS_VHOST ) ? CST_BINDVHOST : CST_VHOSTDNS ); + m_eConState = ( ( eDNSLType == DNS_VHOST ) ? CST_VHOSTDNS : CST_CONNECT ); m_iDNSTryCount = 0; return( 0 ); } diff --git a/Csocket.h b/Csocket.h index b3e5a711..33f2e078 100644 --- a/Csocket.h +++ b/Csocket.h @@ -28,7 +28,7 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * -* $Revision: 1.182 $ +* $Revision: 1.184 $ */ // note to compile with win32 need to link to winsock2, using gcc its -lws2_32 @@ -83,7 +83,7 @@ #include #include -#include "main.h" // require this as a general rule, most projects have a defines.h or the like +#include "main.h" #ifndef CS_STRING # ifdef _HAS_CSTRING_ @@ -520,8 +520,8 @@ public: { CST_START = 0, CST_DNS = CST_START, - CST_VHOSTDNS = 1, - CST_BINDVHOST = 2, + CST_BINDVHOST = 1, + CST_VHOSTDNS = 2, CST_CONNECT = 3, CST_OK = 4 }; @@ -1012,7 +1012,7 @@ private: bool m_bssl, m_bIsConnected, m_bBLOCK, m_bFullsslAccept; bool m_bsslEstablished, m_bEnableReadLine, m_bRequireClientCert, m_bPauseRead; CS_STRING m_shostname, m_sbuffer, m_sSockName, m_sPemFile, m_sCipherType, m_sParentName; - CS_STRING m_sSend, m_sSSLBuffer, m_sPemPass, m_sLocalIP, m_sRemoteIP; + CS_STRING m_sSend, m_sPemPass, m_sLocalIP, m_sRemoteIP; ECloseType m_eCloseType; unsigned long long m_iMaxMilliSeconds, m_iLastSendTime, m_iBytesRead, m_iBytesWritten, m_iStartTime; @@ -1023,6 +1023,7 @@ private: time_t m_iLastCheckTimeoutTime; #ifdef HAVE_LIBSSL + CS_STRING m_sSSLBuffer; SSL *m_ssl; SSL_CTX *m_ssl_ctx; SSL_METHOD *m_ssl_method; @@ -1408,20 +1409,10 @@ public: continue; if ( pcSock->GetConState() == T::CST_DNS ) - { - if ( pcSock->DNSLookup( T::DNS_DEST ) == ETIMEDOUT ) - { - pcSock->SockError( EDOM ); - DelSock( a-- ); - continue; - } - } - - if ( pcSock->GetConState() == T::CST_VHOSTDNS ) { if ( pcSock->DNSLookup( T::DNS_VHOST ) == ETIMEDOUT ) { - pcSock->SockError( EADDRNOTAVAIL ); + pcSock->SockError( EDOM ); DelSock( a-- ); continue; } @@ -1437,6 +1428,17 @@ public: } } + if ( pcSock->GetConState() == T::CST_VHOSTDNS ) + { + if ( pcSock->DNSLookup( T::DNS_DEST ) == ETIMEDOUT ) + { + pcSock->SockError( EADDRNOTAVAIL ); + DelSock( a-- ); + continue; + } + } + + if ( pcSock->GetConState() == T::CST_CONNECT ) { if ( !pcSock->Connect( pcSock->GetBindHost(), true ) )