From a6a5bb7c204130dd4f3ced74446798eb67ea6472 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 2 May 2011 15:34:42 +0200 Subject: Support for name lookups in -connect and -addnode * A new option -dns is introduced that enables name lookups in -connect and -addnode, which is not enabled by default, as it may be considered a security issue. * A Lookup function is added that supports retrieving one or more addresses based on a host name * CAddress constructors (optionally) support name lookups. * The different places in the source code that did name lookups are refactored to use NameLookup or CAddress instead (dns seeding, irc server lookup, getexternalip, ...). * Removed ToStringLog() from CAddress, and switched to ToString(), since it was empty. --- src/net.cpp | 158 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 109 insertions(+), 49 deletions(-) (limited to 'src/net.cpp') diff --git a/src/net.cpp b/src/net.cpp index a403655660..b7cf973d41 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -29,8 +29,9 @@ bool OpenNetworkConnection(const CAddress& addrConnect); // Global state variables // bool fClient = false; +bool fAllowDNS = false; uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK); -CAddress addrLocalHost(0, 0, nLocalServices); +CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices); CNode* pnodeLocalHost = NULL; uint64 nLocalHostNonce = 0; array vnThreadsRunning; @@ -47,7 +48,7 @@ map mapAlreadyAskedFor; // Settings int fUseProxy = false; -CAddress addrProxy("127.0.0.1:9050"); +CAddress addrProxy("127.0.0.1",9050); @@ -92,7 +93,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet) if (fProxy) { - printf("proxy connecting %s\n", addrConnect.ToStringLog().c_str()); + printf("proxy connecting %s\n", addrConnect.ToString().c_str()); char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user"; memcpy(pszSocks4IP + 2, &addrConnect.port, 2); memcpy(pszSocks4IP + 4, &addrConnect.ip, 4); @@ -118,14 +119,81 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet) printf("ERROR: Proxy returned error %d\n", pchRet[1]); return false; } - printf("proxy connected %s\n", addrConnect.ToStringLog().c_str()); + printf("proxy connected %s\n", addrConnect.ToString().c_str()); } hSocketRet = hSocket; return true; } +// portDefault is in host order +bool Lookup(const char *pszName, vector& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort) +{ + vaddr.clear(); + int port = portDefault; + char psz[256]; + char *pszHost = psz; + strlcpy(psz, pszName, sizeof(psz)); + if (fAllowPort) + { + char* pszColon = strrchr(psz+1,':'); + char *pszPortEnd = NULL; + int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0; + if (pszColon && pszPortEnd && pszPortEnd[0] == 0) + { + if (psz[0] == '[' && pszColon[-1] == ']') + { + // Future: enable IPv6 colon-notation inside [] + pszHost = psz+1; + pszColon[-1] = 0; + } + else + pszColon[0] = 0; + port = portParsed; + if (port < 0 || port > USHRT_MAX) + port = USHRT_MAX; + } + } + + struct in_addr addrIP; + if (inet_aton(pszHost, &addrIP)) + { + // valid IP address passed + vaddr.push_back(CAddress(addrIP.s_addr, port, nServices)); + return true; + } + + if (!fAllowLookup) + return false; + + struct hostent* phostent = gethostbyname(pszHost); + if (!phostent) + return false; + + if (phostent->h_addrtype != AF_INET) + return false; + char** ppAddr = phostent->h_addr_list; + while (*ppAddr != NULL && vaddr.size() != nMaxSolutions) + { + CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices); + if (addr.IsValid()) + vaddr.push_back(addr); + ppAddr++; + } + + return (vaddr.size() > 0); +} + +// portDefault is in host order +bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort) +{ + vector vaddr; + bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort); + if (fRet) + addr = vaddr[0]; + return fRet; +} bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet) { @@ -161,7 +229,7 @@ bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const cha strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r")); while (strLine.size() > 0 && isspace(strLine[strLine.size()-1])) strLine.resize(strLine.size()-1); - CAddress addr(strLine.c_str()); + CAddress addr(strLine,0,true); printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str()); if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable()) return false; @@ -192,13 +260,13 @@ bool GetMyExternalIP(unsigned int& ipRet) // if (nHost == 1) { - addrConnect = CAddress("91.198.22.70:80"); // checkip.dyndns.org + addrConnect = CAddress("91.198.22.70",80); // checkip.dyndns.org if (nLookup == 1) { - struct hostent* phostent = gethostbyname("checkip.dyndns.org"); - if (phostent && phostent->h_addr_list && phostent->h_addr_list[0]) - addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(80)); + CAddress addrIP("checkip.dyndns.org", 80, true); + if (addrIP.IsValid()) + addrConnect = addrIP; } pszGet = "GET / HTTP/1.1\r\n" @@ -211,13 +279,13 @@ bool GetMyExternalIP(unsigned int& ipRet) } else if (nHost == 2) { - addrConnect = CAddress("74.208.43.192:80"); // www.showmyip.com + addrConnect = CAddress("74.208.43.192", 80); // www.showmyip.com if (nLookup == 1) { - struct hostent* phostent = gethostbyname("www.showmyip.com"); - if (phostent && phostent->h_addr_list && phostent->h_addr_list[0]) - addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(80)); + CAddress addrIP("www.showmyip.com", 80, true); + if (addrIP.IsValid()) + addrConnect = addrIP; } pszGet = "GET /simple/ HTTP/1.1\r\n" @@ -283,7 +351,7 @@ bool AddAddress(CAddress addr, int64 nTimePenalty) if (it == mapAddresses.end()) { // New address - printf("AddAddress(%s)\n", addr.ToStringLog().c_str()); + printf("AddAddress(%s)\n", addr.ToString().c_str()); mapAddresses.insert(make_pair(addr.GetKey(), addr)); CAddrDB().WriteAddress(addr); return true; @@ -479,7 +547,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout) /// debug print printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n", - addrConnect.ToStringLog().c_str(), + addrConnect.ToString().c_str(), (double)(addrConnect.nTime - GetAdjustedTime())/3600.0, (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0); @@ -491,7 +559,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout) if (ConnectSocket(addrConnect, hSocket)) { /// debug print - printf("connected %s\n", addrConnect.ToStringLog().c_str()); + printf("connected %s\n", addrConnect.ToString().c_str()); // Set to nonblocking #ifdef __WXMSW__ @@ -528,7 +596,7 @@ void CNode::CloseSocketDisconnect() { if (fDebug) printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); - printf("disconnecting node %s\n", addr.ToStringLog().c_str()); + printf("disconnecting node %s\n", addr.ToString().c_str()); closesocket(hSocket); hSocket = INVALID_SOCKET; } @@ -715,7 +783,7 @@ void ThreadSocketHandler2(void* parg) } else { - printf("accepted connection %s\n", addr.ToStringLog().c_str()); + printf("accepted connection %s\n", addr.ToString().c_str()); CNode* pnode = new CNode(hSocket, addr, true); pnode->AddRef(); CRITICAL_BLOCK(cs_vNodes) @@ -892,7 +960,7 @@ void ThreadMapPort2(void* parg) printf("ThreadMapPort started\n"); char port[6]; - sprintf(port, "%d", ntohs(GetDefaultPort())); + sprintf(port, "%d", GetDefaultPort()); const char * rootdescurl = 0; const char * multicastif = 0; @@ -984,17 +1052,17 @@ void DNSAddressSeed() printf("Loading addresses from DNS seeds (could take a while)\n"); for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) { - struct hostent* phostent = gethostbyname(strDNSSeed[seed_idx]); - if (!phostent) - continue; - - for (int host = 0; phostent->h_addr_list[host] != NULL; host++) { - CAddress addr(*(unsigned int*)phostent->h_addr_list[host], - GetDefaultPort(), NODE_NETWORK); - addr.nTime = 0; - if (addr.IsValid() && addr.GetByte(3) != 127) { - AddAddress(addr); - found++; + vector vaddr; + if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, true)) + { + foreach (CAddress& addr, vaddr) + { + if (addr.GetByte(3) != 127) + { + addr.nTime = 0; + AddAddress(addr); + found++; + } } } } @@ -1080,7 +1148,7 @@ void ThreadOpenConnections2(void* parg) { foreach(string strAddr, mapMultiArgs["-connect"]) { - CAddress addr(strAddr, NODE_NETWORK); + CAddress addr(strAddr, fAllowDNS); if (addr.IsValid()) OpenNetworkConnection(addr); for (int i = 0; i < 10 && i < nLoop; i++) @@ -1098,7 +1166,7 @@ void ThreadOpenConnections2(void* parg) { foreach(string strAddr, mapMultiArgs["-addnode"]) { - CAddress addr(strAddr, NODE_NETWORK); + CAddress addr(strAddr, fAllowDNS); if (addr.IsValid()) { OpenNetworkConnection(addr); @@ -1209,7 +1277,7 @@ void ThreadOpenConnections2(void* parg) // Randomize the order in a deterministic way, putting the standard port first int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60); - if (addr.port != GetDefaultPort()) + if (addr.port != htons(GetDefaultPort())) nRandomizer += 2 * 60 * 60; // Last seen Base retry frequency @@ -1369,7 +1437,7 @@ bool BindListenPort(string& strError) { strError = ""; int nOne = 1; - addrLocalHost.port = GetDefaultPort(); + addrLocalHost.port = htons(GetDefaultPort()); #ifdef __WXMSW__ // Initialize Windows Sockets @@ -1421,7 +1489,7 @@ bool BindListenPort(string& strError) memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sin_family = AF_INET; sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer - sockaddr.sin_port = GetDefaultPort(); + sockaddr.sin_port = htons(GetDefaultPort()); if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR) { int nErr = WSAGetLastError(); @@ -1448,29 +1516,21 @@ bool BindListenPort(string& strError) void StartNode(void* parg) { if (pnodeLocalHost == NULL) - pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices)); + pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices)); #ifdef __WXMSW__ // Get local host ip char pszHostName[1000] = ""; if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) { - struct hostent* phostent = gethostbyname(pszHostName); - if (phostent) - { - // Take the first IP that isn't loopback 127.x.x.x - for (int i = 0; phostent->h_addr_list[i] != NULL; i++) - printf("host ip %d: %s\n", i, CAddress(*(unsigned int*)phostent->h_addr_list[i]).ToStringIP().c_str()); - for (int i = 0; phostent->h_addr_list[i] != NULL; i++) - { - CAddress addr(*(unsigned int*)phostent->h_addr_list[i], GetDefaultPort(), nLocalServices); - if (addr.IsValid() && addr.GetByte(3) != 127) + vector vaddr; + if (NameLookup(pszHostName, vaddr, nLocalServices)) + foreach (const CAddress &addr, vaddr) + if (addr.GetByte(3) != 127) { addrLocalHost = addr; break; } - } - } } #else // Get local host ip @@ -1491,7 +1551,7 @@ void StartNode(void* parg) printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP); // Take the first IP that isn't loopback 127.x.x.x - CAddress addr(*(unsigned int*)&s4->sin_addr, GetDefaultPort(), nLocalServices); + CAddress addr(*(unsigned int*)&s4->sin_addr, 0, nLocalServices); if (addr.IsValid() && addr.GetByte(3) != 127) { addrLocalHost = addr; -- cgit v1.2.3