diff --git a/src/main.cpp b/src/main.cpp index f9691a5d5..5f16378b4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2418,6 +2418,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } // Store the new addresses + vector vAddrOk; int64 nNow = GetAdjustedTime(); int64 nSince = nNow - 10 * 60; BOOST_FOREACH(CAddress& addr, vAddr) @@ -2427,6 +2428,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60) addr.nTime = nNow - 5 * 24 * 60 * 60; pfrom->AddAddressKnown(addr); + bool fReachable = IsReachable(addr); if (addr.nTime > nSince && !pfrom->fGetAddr && vAddr.size() <= 10 && addr.IsRoutable()) { // Relay to a limited number of other nodes @@ -2451,13 +2453,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) hashKey = Hash(BEGIN(hashKey), END(hashKey)); mapMix.insert(make_pair(hashKey, pnode)); } - int nRelayNodes = 2; + int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s) for (multimap::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) ((*mi).second)->PushAddress(addr); } } + // Do not store addresses outside our network + if (fReachable) + vAddrOk.push_back(addr); } - addrman.Add(vAddr, pfrom->addr, 2 * 60 * 60); + addrman.Add(vAddrOk, pfrom->addr, 2 * 60 * 60); if (vAddr.size() < 1000) pfrom->fGetAddr = false; if (pfrom->fOneShot) diff --git a/src/net.cpp b/src/net.cpp index 75c8bbaba..d407e6642 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -45,8 +45,9 @@ bool OpenNetworkConnection(const CAddress& addrConnect, const char *strDest = NU bool fClient = false; static bool fUseUPnP = false; uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK); -CCriticalSection cs_mapLocalHost; -map mapLocalHost; +static CCriticalSection cs_mapLocalHost; +static map mapLocalHost; +static bool vfReachable[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; uint64 nLocalHostNonce = 0; array vnThreadsRunning; @@ -214,6 +215,9 @@ bool AddLocal(const CNetAddr& addr, int nScore) { LOCK(cs_mapLocalHost); mapLocalHost[addr] = std::max(nScore, mapLocalHost[addr]) + (mapLocalHost.count(addr) ? 1 : 0); + enum Network net = addr.GetNetwork(); + vfReachable[net] = true; + if (net == NET_IPV6) vfReachable[NET_IPV4] = true; } AdvertizeLocal(); @@ -243,6 +247,12 @@ bool IsLocal(const CNetAddr& addr) return mapLocalHost.count(addr) > 0; } +// check whether a given address is in a network we can probably connect to +bool IsReachable(const CNetAddr& addr) +{ + LOCK(cs_mapLocalHost); + return vfReachable[addr.GetNetwork()]; +} bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet) { diff --git a/src/net.h b/src/net.h index a00dd1b8c..63f871204 100644 --- a/src/net.h +++ b/src/net.h @@ -58,8 +58,10 @@ bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE); bool SeenLocal(const CNetAddr& addr); bool IsLocal(const CNetAddr& addr); bool GetLocal(CNetAddr &addr, const CNetAddr *paddrPeer = NULL); +bool IsReachable(const CNetAddr &addr); CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); + enum { MSG_TX = 1, diff --git a/src/netbase.cpp b/src/netbase.cpp index 37e6120e7..4c852f5ee 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -25,6 +25,14 @@ int nConnectTimeout = 5000; static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; +enum Network ParseNetwork(std::string net) { + if (net == "ipv4") return NET_IPV4; + if (net == "ipv6") return NET_IPV6; + if (net == "tor") return NET_TOR; + if (net == "i2p") return NET_I2P; + return NET_UNROUTABLE; +} + bool static LookupIntern(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions, bool fAllowLookup) { vIP.clear(); @@ -688,6 +696,23 @@ bool CNetAddr::IsRoutable() const return IsValid() && !(IsRFC1918() || IsRFC3927() || IsRFC4862() || (IsRFC4193() && !IsOnionCat() && !IsGarliCat()) || IsRFC4843() || IsLocal()); } +enum Network CNetAddr::GetNetwork() const +{ + if (!IsRoutable()) + return NET_UNROUTABLE; + + if (IsIPv4()) + return NET_IPV4; + + if (IsOnionCat()) + return NET_TOR; + + if (IsGarliCat()) + return NET_I2P; + + return NET_IPV6; +} + std::string CNetAddr::ToStringIP() const { if (IsIPv4()) diff --git a/src/netbase.h b/src/netbase.h index 1b6d8d59b..998f8eaf1 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -17,6 +17,19 @@ extern int nConnectTimeout; #undef SetPort #endif +enum Network +{ + NET_UNROUTABLE, + NET_IPV4, + NET_IPV6, + NET_TOR, + NET_I2P, + + NET_MAX +}; + +enum Network ParseNetwork(std::string net); + /** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */ class CNetAddr { @@ -48,6 +61,7 @@ class CNetAddr bool IsRoutable() const; bool IsValid() const; bool IsMulticast() const; + enum Network GetNetwork() const; std::string ToString() const; std::string ToStringIP() const; int GetByte(int n) const;