--- libapp/resolver.cpp.orig Tue Feb 13 00:55:08 2001 +++ libapp/resolver.cpp Thu Jan 8 00:10:40 2015 @@ -11,6 +11,7 @@ #include "parser.h" #include "app.h" +#include "Avl.h" #include "dbg.h" #include @@ -162,7 +163,7 @@ static char* inet_ntoa_rev( struct in_addr in ) static char host[29]; // aaa.bbb.ccc.ddd.in-addr.arpa\0 BYTE qa[4]; memcpy( qa, &in.s_addr, 4 ); - sprintf( host, "%u.%u.%u.%u.in-addr.arpa", qa[3], qa[2], qa[1], qa[0] ); + snprintf( host, sizeof(host), "%u.%u.%u.%u.in-addr.arpa", qa[3], qa[2], qa[1], qa[0] ); return host; } @@ -196,9 +197,7 @@ CResolver * CResolver::GetResolver( void ) bool CResolver::GetHost( CResolverResponse* pResponse, const CString& strHost ) { -dbgout( "CResolver::GetHost: query for %s", (CPCHAR)strHost ); - CHostInfo* pInfo; - + dbgout( "CResolver::GetHost: query for %s", (CPCHAR)strHost ); // Determine if this is a number or name bool bIsNumeric = true; CPCHAR p = strHost; @@ -224,16 +223,16 @@ dbgout( "CResolver::GetHost: query for %s", (CPCHAR)st } // First search for name as given - CHostInfo info( strHost ); - pInfo = m_treeHostInfo.Search( info ); - if( pInfo ) + CHostInfo pInfo = m_treeHostInfo[strHost]; + + if( pInfo.m_strName != "" ) { - if( pInfo->m_tExpire > time(NULL) ) + if( pInfo.m_tExpire > time(NULL) ) { - pResponse->GetHostDone( 0, strHost, pInfo->m_addr ); + pResponse->GetHostDone( 0, strHost, pInfo.m_addr ); return true; } - m_treeHostInfo.Delete( info ); + m_treeHostInfo.erase( strHost ); } // Not found - if it's unqualified, search the domain list @@ -254,15 +253,16 @@ dbgout( "CResolver::GetHost: query for %s", (CPCHAR)st strFQDN.Append( "." ); strFQDN.Append( *itr ); CHostInfo info( strFQDN ); - CHostInfo* pInfo = m_treeHostInfo.Search( info ); - if( pInfo ) + CHostInfo pInfo = m_treeHostInfo[strFQDN]; + + if ( pInfo.m_strName != "" ) { - if( pInfo->m_tExpire > time(NULL) ) + if( pInfo.m_tExpire > time(NULL) ) { - pResponse->GetHostDone( 0, strHost, pInfo->m_addr ); + pResponse->GetHostDone( 0, strHost, pInfo.m_addr ); return true; } - m_treeHostInfo.Delete( info ); + m_treeHostInfo.erase( strFQDN ); } itr++; } @@ -270,143 +270,162 @@ dbgout( "CResolver::GetHost: query for %s", (CPCHAR)st // Looks like we have to send a query CHostQuery query( strHost ); - CHostQuery* pQuery = m_treeHostQueries.Insert( query ); - if( ! pQuery ) + CHostQuery pQuery = (*m_treeHostQueries.insert( pair( strHost,query ) ).first).second; + + if ( pQuery.m_strHost != "" ) { - pQuery = m_treeHostQueries.Search( query ); - assert( pQuery ); - - pQuery->m_tExpire = time(NULL) + 4; - pQuery->m_tDelta = 4; + pQuery.m_tExpire = time(NULL) + 4; + pQuery.m_tDelta = 4; if( !strchr( strHost, '.' ) ) { // Unqualified - search the domain list CDomainList::Iterator itr( m_listDomains.Begin() ); assert( itr ); // should have caught this already - pQuery->m_strFQDN = strHost; - pQuery->m_strFQDN.Append( "." ); - pQuery->m_strFQDN.Append( *itr ); - pQuery->m_itrDomain = itr; + pQuery.m_strFQDN = strHost; + pQuery.m_strFQDN.Append( "." ); + pQuery.m_strFQDN.Append( *itr ); + pQuery.m_itrDomain = itr; } - pQuery->m_itrServer = m_listServers.Begin(); + pQuery.m_itrServer = m_listServers.Begin(); - SendQuery( *pQuery->m_itrServer, pQuery->m_strFQDN, RR_A ); + SendQuery( *pQuery.m_itrServer, pQuery.m_strFQDN, RR_A ); } + pQuery.AddResponse( *pResponse ); - pQuery->AddResponse( pResponse ); + // Speichern des geaenderten Objekts + m_treeHostQueries[strHost] = pQuery; return true; } bool CResolver::GetHost( CResolverResponse* pResponse, struct in_addr addr ) { -dbgout( "CResolver::GetHost: query for %s", inet_ntoa(addr) ); + dbgout( "CResolver::GetHost: query for %s", inet_ntoa(addr) ); CAddrInfo info( addr ); // See if we already have it - CAddrInfo* pInfo = m_treeAddrInfo.Search( info ); - if( pInfo ) + CAddrInfo pInfo = m_treeAddrInfo[addr]; + + if( pInfo.m_addr.s_addr != INADDR_NONE ) { - if( pInfo->m_tExpire > time(NULL) ) + if( pInfo.m_tExpire > time(NULL) ) { - pResponse->GetHostDone( 0, addr, pInfo->m_strName ); + pResponse->GetHostDone( 0, addr, pInfo.m_strName ); return true; } - m_treeAddrInfo.Delete( info ); + m_treeAddrInfo.erase( addr ); } // Nope, gotta send a query CAddrQuery query( addr ); - CAddrQuery* pQuery = m_treeAddrQueries.Insert( query ); - if( ! pQuery ) - { - pQuery = m_treeAddrQueries.Search( query ); - assert( pQuery ); + CAddrQuery pQuery = (*(m_treeAddrQueries.insert( pair( addr, query ) ).first)).second; - pQuery->m_tExpire = time(NULL) + 4; - pQuery->m_tDelta = 4; - pQuery->m_itrServer = m_listServers.Begin(); - SendQuery( *pQuery->m_itrServer, inet_ntoa_rev(addr), RR_PTR ); + if ( pQuery.m_addr.s_addr != INADDR_NONE ) + { + pQuery.m_tExpire = time(NULL) + 4; + pQuery.m_tDelta = 4; + pQuery.m_itrServer = m_listServers.Begin(); + SendQuery( *pQuery.m_itrServer, inet_ntoa_rev(addr), RR_PTR ); } + pQuery.AddResponse( *pResponse ); - pQuery->AddResponse( pResponse ); + // Speichern des geaenderten Objekts + m_treeAddrQueries[addr] = pQuery; return true; } -void CResolver::WalkHostTree( AvlNode* pNode ) +void CResolver::IterateHostMap() { - if( !pNode ) return; - WalkHostTree( pNode->Subtree(LEFT) ); - WalkHostTree( pNode->Subtree(RIGHT) ); - CHostQuery& rquery = pNode->Key(); - if( rquery.m_tExpire < time(NULL) ) + // Empty map + if ( m_treeHostQueries.empty() ) return; + + CHostQueryMap::iterator itr = m_treeHostQueries.begin(); + // Iterate over all hostname queries + while ( itr != m_treeHostQueries.end() ) { - // Timed out, next nameserver - rquery.m_itrServer++; - if( rquery.m_itrServer ) - { - rquery.m_tExpire = time(NULL)+4; - rquery.m_tDelta = 4; - SendQuery( *rquery.m_itrServer, rquery.m_strHost, RR_A ); - return; - } + CHostQuery rquery = (*itr).second; + if( rquery.m_tExpire < time(NULL) ) + { + dbgout("Nameserver timed out"); + // Timed out, next nameserver + rquery.m_itrServer++; + if( rquery.m_itrServer ) + { + rquery.m_tExpire = time(NULL)+4; + rquery.m_tDelta = 4; + SendQuery( *rquery.m_itrServer, rquery.m_strHost, RR_A ); + return; + } - // Exhausted server list, so bump the timeout and start over - rquery.m_tExpire += rquery.m_tDelta; - rquery.m_tDelta *= 2; - rquery.m_itrServer = m_listServers.Begin(); - if( rquery.m_tDelta > 30 ) - { - // Everything timed out - we're all alone, and it's getting dark! - struct in_addr addr; - addr.s_addr = INADDR_NONE; - CResolverResponseList::Iterator itr( rquery.m_listResponses.Begin() ); - while( itr ) - { - (*itr)->GetHostDone( EAGAIN, rquery.m_strHost, addr ); - itr++; - } - m_treeHostQueries.Delete( rquery ); - } + dbgout("No more name servers left. Starting over"); + // Exhausted server list, so bump the timeout and start over + rquery.m_tExpire += rquery.m_tDelta; + rquery.m_tDelta *= 2; + rquery.m_itrServer = m_listServers.Begin(); + if( rquery.m_tDelta > 30 ) + { + dbgout("Everything timed out!"); + // Everything timed out - we're all alone, and it's getting dark! + struct in_addr addr; + addr.s_addr = INADDR_NONE; + CResolverResponseList::iterator itr( rquery.m_listResponses.begin() ); + while( itr != rquery.m_listResponses.end() ) + { + (*itr)->GetHostDone( EAGAIN, rquery.m_strHost, addr ); + itr++; + } + m_treeHostQueries.erase( rquery.m_strHost ); + } + } + ++itr; } } -void CResolver::WalkAddrTree( AvlNode* pNode ) +void CResolver::IterateAddrMap() { - if( !pNode ) return; - WalkAddrTree( pNode->Subtree(LEFT) ); - WalkAddrTree( pNode->Subtree(RIGHT) ); - CAddrQuery& rquery = pNode->Key(); - if( rquery.m_tExpire < time(NULL) ) + if ( m_treeAddrQueries.empty() ) return; + + CAddrQueryMap::iterator itr = m_treeAddrQueries.begin(); + + // Iterate over all address queries + while ( itr != m_treeAddrQueries.end() ) { - // Timed out, next nameserver - rquery.m_itrServer++; - if( rquery.m_itrServer ) - { - rquery.m_tExpire = time(NULL)+4; - rquery.m_tDelta = 4; - SendQuery( *rquery.m_itrServer, inet_ntoa_rev(rquery.m_addr), RR_PTR ); - return; - } + CAddrQuery rquery = (*itr).second; + if( rquery.m_tExpire < time(NULL) ) + { + dbgout("Nameserver timed out"); + // Timed out, next nameserver + rquery.m_itrServer++; + if( rquery.m_itrServer ) + { + rquery.m_tExpire = time(NULL)+4; + rquery.m_tDelta = 4; + SendQuery( *rquery.m_itrServer, inet_ntoa_rev(rquery.m_addr), RR_PTR ); + return; + } - // Exhausted server list, so bump the timeout and start over - rquery.m_tExpire += rquery.m_tDelta; - rquery.m_tDelta *= 2; - rquery.m_itrServer = m_listServers.Begin(); - if( rquery.m_tDelta > 30 ) - { - // Everything timed out - we're all alone, and it's getting dark! - CString host; - CResolverResponseList::Iterator itr( rquery.m_listResponses.Begin() ); - while( itr ) - { - (*itr)->GetHostDone( EAGAIN, rquery.m_addr, host ); - itr++; - } - m_treeAddrQueries.Delete( rquery ); - } + dbgout("No more name servers left. Starting over"); + // Exhausted server list, so bump the timeout and start over + rquery.m_tExpire += rquery.m_tDelta; + rquery.m_tDelta *= 2; + rquery.m_itrServer = m_listServers.Begin(); + if( rquery.m_tDelta > 30 ) + { + dbgout("Everything timed out!"); + // Everything timed out - we're all alone, and it's getting dark! + CString host; + CResolverResponseList::iterator itr( rquery.m_listResponses.begin() ); + while( itr != rquery.m_listResponses.end() ) + { + (*itr)->GetHostDone( EAGAIN, rquery.m_addr, host ); + itr++; + } + m_treeAddrQueries.erase( rquery.m_addr ); + } + } + ++itr; } } @@ -415,12 +434,12 @@ void CResolver::OnTimer( void ) dbgout( "CResolver::OnTimer" ); // iterate through queries, remove stale ones and respond fail - WalkHostTree( m_treeHostQueries.GetRoot() ); - WalkAddrTree( m_treeAddrQueries.GetRoot() ); + IterateHostMap(); + IterateAddrMap(); - if( m_treeHostQueries.IsEmpty() && m_treeAddrQueries.IsEmpty() ) + if ( m_treeHostQueries.empty() && m_treeAddrQueries.empty() ) { -dbgout( "CResolver::OnTimer: no more queries" ); + dbgout( "CResolver::OnTimer: no more queries" ); m_sock.Close(); m_timer.Disable(); } @@ -433,7 +452,7 @@ void CResolver::OnConnectDone( int err ) void CResolver::OnReadReady( void ) { -dbgout( "CResolver::OnReadReady" ); + dbgout( "CResolver::OnReadReady" ); CBuffer buf; buf.SetSize( 513 ); if( !m_sock.Read( &buf ) ) @@ -498,9 +517,9 @@ dbgout( "CResolver::OnReadReady" ); if( qrhdr.qtype == RR_A ) { // Does not exist - try next domain - CHostQuery query( qrhdr.strHost ); - CHostQuery* pQuery = m_treeHostQueries.Search( query ); - if( ! pQuery ) + CHostQuery pQuery = m_treeHostQueries[qrhdr.strHost]; + + if( pQuery.m_strHost == "" ) { dbgout( "CResolver::OnReadReady: received rc=%u for unexpected host '%s'", rc, (CPCHAR)qrhdr.strHost ); @@ -508,29 +527,32 @@ dbgout( "CResolver::OnReadReady" ); } // If query was unqualified, bump the domain iterator - if( pQuery->m_itrDomain ) pQuery->m_itrDomain++; + if( pQuery.m_itrDomain ) pQuery.m_itrDomain++; - if( ! pQuery->m_itrDomain ) + if( ! pQuery.m_itrDomain ) { // Exhausted search list struct in_addr addr; addr.s_addr = INADDR_NONE; - CResolverResponseList::Iterator itr( pQuery->m_listResponses.Begin() ); - while( itr ) + CResolverResponseList::iterator itr( pQuery.m_listResponses.begin() ); + while( itr != pQuery.m_listResponses.end() ) { (*itr)->GetHostDone( ENOENT, qrhdr.strHost, addr ); itr++; } - m_treeHostQueries.Delete( query ); + m_treeHostQueries.erase( qrhdr.strHost ); } else { - pQuery->m_strFQDN = pQuery->m_strHost; - pQuery->m_strFQDN.Append( "." ); - pQuery->m_strFQDN.Append( *pQuery->m_itrDomain ); - pQuery->m_itrDomain++; + pQuery.m_strFQDN = pQuery.m_strHost; + pQuery.m_strFQDN.Append( "." ); + pQuery.m_strFQDN.Append( *pQuery.m_itrDomain ); + pQuery.m_itrDomain++; //XXX: reset query's server iterator here? - SendQuery( *pQuery->m_itrServer, pQuery->m_strFQDN, RR_A ); + SendQuery( *pQuery.m_itrServer, pQuery.m_strFQDN, RR_A ); + + // Speichern des geaenderten Objekts + m_treeHostQueries[qrhdr.strHost] = pQuery; } } else if( qrhdr.qtype == RR_PTR ) @@ -538,9 +560,9 @@ dbgout( "CResolver::OnReadReady" ); struct in_addr addr; if( inet_aton_rev( qrhdr.strHost, &addr ) ) { - CAddrQuery query( addr ); - CAddrQuery* pQuery = m_treeAddrQueries.Search( query ); - if( ! pQuery ) + CAddrQuery pQuery = m_treeAddrQueries[addr]; + + if( pQuery.m_addr.s_addr == INADDR_NONE ) { dbgout( "CResolver::OnReadReady: received rc=%u for unexpected host '%s'", rc, (CPCHAR)qrhdr.strHost ); @@ -548,13 +570,13 @@ dbgout( "CResolver::OnReadReady" ); } CString host; - CResolverResponseList::Iterator itr( pQuery->m_listResponses.Begin() ); - while( itr ) + CResolverResponseList::iterator itr( pQuery.m_listResponses.begin() ); + while( itr != pQuery.m_listResponses.end() ) { (*itr)->GetHostDone( ENOENT, addr, host ); itr++; } - m_treeAddrQueries.Delete( query ); + m_treeAddrQueries.erase( addr ); } } else @@ -607,9 +629,9 @@ dbgout( "CResolver::OnReadReady" ); // Ignore authority and additional RR's - if( m_treeHostQueries.IsEmpty() && m_treeAddrQueries.IsEmpty() ) + if( m_treeHostQueries.empty() && m_treeAddrQueries.empty() ) { -dbgout( "CResolver::OnReadReady: no more queries" ); + dbgout( "CResolver::OnReadReady: no more queries" ); m_sock.Close(); m_timer.Disable(); } @@ -656,7 +678,7 @@ dbgout( "CResolver::SendQuery: host %s", (CPCHAR)strHo } if( CTimer::Repeating != m_timer.GetMode() ) { -dbgout( "CResolver::SendQuery: setting timer" ); + dbgout( "CResolver::SendQuery: setting timer" ); m_timer.SetRepeating( 2*1000 ); } @@ -688,59 +710,67 @@ dbgout( "CResolver::SendQuery: setting timer" ); void CResolver::AddHostEntry( time_t tExpire, const CString& strHost, struct in_addr addr ) { -dbgout( "AddHostEntry: host %s = %s", (CPCHAR)strHost, inet_ntoa(addr) ); - // Add host to our host tree - m_treeHostInfo.Insert( CHostInfo( tExpire, strHost, addr ) ); + dbgout( "AddHostEntry: host %s = %s", (CPCHAR)strHost, inet_ntoa(addr) ); + // Add host to our host map + m_treeHostInfo[strHost] = CHostInfo( tExpire, strHost, addr); - // Add addr to our addr tree - m_treeAddrInfo.Insert( CAddrInfo( tExpire, addr, strHost ) ); + // Add addr to our addr map + m_treeAddrInfo[addr] = CAddrInfo( tExpire, addr, strHost ); // See if anyone is waiting for this host CHostQuery queryHost( strHost ); - CHostQuery* pHostQuery = m_treeHostQueries.Search( queryHost ); - if( pHostQuery ) + CHostQuery pHostQuery; + + CHostQueryMap::iterator hqitr = m_treeHostQueries.find( strHost ); + + if ( hqitr != m_treeHostQueries.end() ) { -dbgout( "\tfound host query in tree, calling responses" ); - CResolverResponseList::Iterator itr( pHostQuery->m_listResponses.Begin() ); - while( itr ) + pHostQuery = (*hqitr).second; + dbgout( "\tfound host query in tree, calling responses" ); + CResolverResponseList::iterator itr( pHostQuery.m_listResponses.begin() ); + while( itr != pHostQuery.m_listResponses.end() ) { + dbgout("Calling GetHost done for host=%s and address=%s", (CPCHAR) strHost, inet_ntoa(addr)); (*itr)->GetHostDone( 0, strHost, addr ); itr++; } - m_treeHostQueries.Delete( queryHost ); + m_treeHostQueries.erase( strHost ); } CPCHAR pdot; if( (pdot = strchr( strHost, '.' )) ) { // Perhaps someone is waiting on the unqualified name queryHost.m_strHost.Set( strHost, pdot - (CPCHAR)strHost ); - pHostQuery = m_treeHostQueries.Search( queryHost ); - if( pHostQuery ) + hqitr = m_treeHostQueries.find( queryHost.m_strHost ); + + if ( hqitr != m_treeHostQueries.end() ) { -dbgout( "\tfound bare host query in tree, calling responses" ); - CResolverResponseList::Iterator itr( pHostQuery->m_listResponses.Begin() ); - while( itr ) + pHostQuery = (*hqitr).second; + dbgout( "\tfound bare host query in tree, calling responses" ); + CResolverResponseList::iterator itr( pHostQuery.m_listResponses.begin() ); + while( itr != pHostQuery.m_listResponses.end() ) { (*itr)->GetHostDone( 0, strHost, addr ); itr++; } - m_treeHostQueries.Delete( queryHost ); + m_treeHostQueries.erase( queryHost.m_strHost ); } } // See if anyone is waiting for this addr - CAddrQuery queryAddr( addr ); - CAddrQuery* pAddrQuery = m_treeAddrQueries.Search( queryAddr ); - if( pAddrQuery ) + CAddrQueryMap::iterator adritr = m_treeAddrQueries.find( addr ); + + if ( adritr != m_treeAddrQueries.end() ) { -dbgout( "\tfound addr query in tree, calling responses" ); - CResolverResponseList::Iterator itr( pAddrQuery->m_listResponses.Begin() ); - while( itr ) + CAddrQuery pAddrQuery = (*adritr).second; + dbgout( "\tfound addr query in tree, calling responses" ); + CResolverResponseList::iterator itr( pAddrQuery.m_listResponses.begin() ); + while( itr != pAddrQuery.m_listResponses.end() ) { (*itr)->GetHostDone( 0, addr, strHost ); itr++; } - m_treeAddrQueries.Delete( queryAddr ); + m_treeAddrQueries.erase( addr ); } } @@ -953,7 +983,7 @@ bool CResolver::EncodeName( CPCHAR szName, PBYTE& rpbu { CPCHAR pLabel = szName; BYTE nLabelLen = 0; - BYTE nOverLen = min( 64, rlen-1 ); + BYTE nOverLen = MIN( 64, rlen-1 ); while( *szName && '.' != *szName && nLabelLen < nOverLen ) { nLabelLen++; @@ -1012,15 +1042,18 @@ bool CResolver::ParseAnswerHeader( dns_rr_hdr* phdr, c bool CResolver::DecodeName( PCHAR pname, const CBuffer& buf, size_t& rpos ) { - CPBYTE pbuf = buf.GetBuffer(); - size_t buflen = buf.GetSize(); + const CPBYTE pbuf = buf.GetBuffer(); + const size_t buflen = buf.GetSize(); size_t pos = rpos; size_t namelen = 0; + size_t iteration = 0; assert( buflen > 0 && buflen <= 512 && pos < buflen ); bool bHasPtr = false; while( pbuf[pos] ) { + if( iteration++ >= buflen ) return false; + UINT8 len = pbuf[pos]; if( !(len & 0xC0) ) { @@ -1041,7 +1074,7 @@ bool CResolver::DecodeName( PCHAR pname, const CBuffer if( (len & 0xC0) != 0xC0 || pos > buflen-2 ) return false; pos = (UINT16)(pbuf[pos] & 0x3F)*256 + (UINT16)(pbuf[pos+1]); if( pos >= buflen-1 ) return false; - rpos += 2; + if( !bHasPtr ) rpos += 2; bHasPtr = true; } }