DNS::HostMap DNS::resolve( const std::string& service, const std::string& proto, const std::string& domain, const LogSink& logInstance ) { const std::string dname = "_" + service + "._" + proto + "." + domain; bool error = false; DNS::HostMap servers; DNS_RECORD* pRecord; if( DnsQuery( dname.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &pRecord, NULL ) == ERROR_SUCCESS ) { DNS_RECORD* pRec = pRecord; do { if( pRec->wType == DNS_TYPE_SRV ) { servers[pRec->Data.SRV.pNameTarget] = pRec->Data.SRV.wPort; } pRec = pRec->pNext; } while( pRec != NULL ); DnsRecordListFree( pRecord, DnsFreeRecordList ); } else error = true; if( error || !servers.size() ) { servers = defaultHostMap( domain, logInstance ); } return servers; }
void ConnectionSOCKS5Proxy::handleConnect( const ConnectionBase* /*connection*/ ) { if( m_connection ) { std::string server = m_server; int port = m_port; if( port == -1 ) { DNS::HostMap servers = DNS::resolve( m_server, m_logInstance ); if( servers.size() ) { server = (*(servers.begin())).first; port = (*(servers.begin())).second; } } m_logInstance.log( LogLevelDebug, LogAreaClassConnectionSOCKS5Proxy, "attempting to negotiate socks5 proxy connection" ); bool auth = !m_proxyUser.empty() && !m_proxyPassword.empty(); char *d = new char[auth ? 4 : 3]; d[0] = 0x05; // SOCKS version 5 if( auth ) { d[1] = 0x02; // two methods d[3] = 0x02; // method: username/password auth } else d[1] = 0x01; // one method d[2] = 0x00; // method: no auth if( !send( std::string( d, auth ? 4 : 3 ) ) ) { cleanup(); if( m_handler ) m_handler->handleDisconnect( this, ConnIoError ); } delete[] d; } }
DNS::HostMap DNS::resolve( const std::string& service, const std::string& proto, const std::string& domain, const LogSink& logInstance ) { const std::string dname = "_" + service + "._" + proto + "." + domain; bool error = false; DNS::HostMap servers; DNS_RECORD* pRecord = NULL; DNS_STATUS status = DnsQuery_UTF8( dname.c_str(), DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &pRecord, NULL ); if( status == ERROR_SUCCESS ) { // NOTE: DnsQuery_UTF8 and DnsQuery_A really should have been defined with // PDNS_RECORDA instead of PDNS_RECORD, since that's what it is (even with _UNICODE defined). // We'll correct for that mistake with a cast. DNS_RECORDA* pRec = (DNS_RECORDA*)pRecord; do { if( pRec->wType == DNS_TYPE_SRV ) { servers[pRec->Data.SRV.pNameTarget] = pRec->Data.SRV.wPort; } pRec = pRec->pNext; } while( pRec != NULL ); DnsRecordListFree( pRecord, DnsFreeRecordList ); } else { logInstance.warn( LogAreaClassDns, "DnsQuery_UTF8() failed: " + util::int2string( status ) ); error = true; } if( error || !servers.size() ) { servers = defaultHostMap( domain, logInstance ); } return servers; }
void ConnectionSOCKS5Proxy::negotiate() { m_s5state = S5StateNegotiating; char *d = new char[m_ip ? 10 : 6 + m_server.length() + 1]; int pos = 0; d[pos++] = 0x05; // SOCKS version 5 d[pos++] = 0x01; // command CONNECT d[pos++] = 0x00; // reserved int port = m_port; std::string server = m_server; if( m_ip ) // IP address { d[pos++] = 0x01; // IPv4 address std::string s; int j = server.length(); int l = 0; for( int k = 0; k < j && l < 4; ++k ) { if( server[k] != '.' ) s += server[k]; if( server[k] == '.' || k == j-1 ) { d[pos++] = atoi( s.c_str() ) & 0x0FF; s = ""; ++l; } } } else // hostname { if( port == -1 ) { DNS::HostMap servers = DNS::resolve( m_server, m_logInstance ); if( servers.size() ) { server = (*(servers.begin())).first; port = (*(servers.begin())).second; } } d[pos++] = 0x03; // hostname d[pos++] = m_server.length(); strncpy( d + pos, m_server.c_str(), m_server.length() ); pos += m_server.length(); } int nport = htons( port ); d[pos++] = nport; d[pos++] = nport >> 8; #ifndef _WIN32_WCE std::ostringstream oss; oss << "requesting socks5 proxy connection to " << server << ":" << port; m_logInstance.log( LogLevelDebug, LogAreaClassConnectionSOCKS5Proxy, oss.str() ); #endif if( !send( std::string( d, pos ) ) ) { cleanup(); m_handler->handleDisconnect( this, ConnIoError ); } delete[] d; }