diff options
-rw-r--r-- | src/netaddress.cpp | 121 | ||||
-rw-r--r-- | src/netaddress.h | 8 |
2 files changed, 119 insertions, 10 deletions
diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 58e45c2c02..6ee2d8a4b3 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -14,6 +14,11 @@ static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43}; // 0xFD + sha256("bitcoin")[0:5] static const unsigned char g_internal_prefix[] = { 0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24 }; +/** + * Construct an unspecified IPv6 network address (::/128). + * + * @note This address is considered invalid by CNetAddr::IsValid() + */ CNetAddr::CNetAddr() { memset(ip, 0, sizeof(ip)); @@ -40,6 +45,20 @@ void CNetAddr::SetRaw(Network network, const uint8_t *ip_in) } } +/** + * Try to make this a dummy address that maps the specified name into IPv6 like + * so: (0xFD + %sha256("bitcoin")[0:5]) + %sha256(name)[0:10]. Such dummy + * addresses have a prefix of fd6b:88c0:8724::/48 and are guaranteed to not be + * publicly routable as it falls under RFC4193's fc00::/7 subnet allocated to + * unique-local addresses. + * + * CAddrMan uses these fake addresses to keep track of which DNS seeds were + * used. + * + * @returns Whether or not the operation was successful. + * + * @see CNetAddr::IsInternal(), CNetAddr::IsRFC4193() + */ bool CNetAddr::SetInternal(const std::string &name) { if (name.empty()) { @@ -52,6 +71,16 @@ bool CNetAddr::SetInternal(const std::string &name) return true; } +/** + * Try to make this a dummy address that maps the specified onion address into + * IPv6 using OnionCat's range and encoding. Such dummy addresses have a prefix + * of fd87:d87e:eb43::/48 and are guaranteed to not be publicly routable as they + * fall under RFC4193's fc00::/7 subnet allocated to unique-local addresses. + * + * @returns Whether or not the operation was successful. + * + * @see CNetAddr::IsTor(), CNetAddr::IsRFC4193() + */ bool CNetAddr::SetSpecial(const std::string &strName) { if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") { @@ -175,6 +204,12 @@ bool CNetAddr::IsRFC4843() const return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10); } +/** + * @returns Whether or not this is a dummy address that maps an onion address + * into IPv6. + * + * @see CNetAddr::SetSpecial(const std::string &) + */ bool CNetAddr::IsTor() const { return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0); @@ -194,6 +229,16 @@ bool CNetAddr::IsLocal() const return false; } +/** + * @returns Whether or not this network address is a valid address that @a could + * be used to refer to an actual host. + * + * @note A valid address may or may not be publicly routable on the global + * internet. As in, the set of valid addreses is a superset of the set of + * publicly routable addresses. + * + * @see CNetAddr::IsRoutable() + */ bool CNetAddr::IsValid() const { // Cleanup 3-byte shifted addresses caused by garbage in size field @@ -233,11 +278,25 @@ bool CNetAddr::IsValid() const return true; } +/** + * @returns Whether or not this network address is publicly routable on the + * global internet. + * + * @note A routable address is always valid. As in, the set of routable addreses + * is a subset of the set of valid addresses. + * + * @see CNetAddr::IsValid() + */ bool CNetAddr::IsRoutable() const { return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal() || IsInternal()); } +/** + * @returns Whether or not this is a dummy address that maps a name into IPv6. + * + * @see CNetAddr::SetInternal(const std::string &) + */ bool CNetAddr::IsInternal() const { return memcmp(ip, g_internal_prefix, sizeof(g_internal_prefix)) == 0; @@ -299,6 +358,16 @@ bool operator<(const CNetAddr& a, const CNetAddr& b) return (memcmp(a.ip, b.ip, 16) < 0); } +/** + * Try to get our IPv4 address. + * + * @param[out] pipv4Addr The in_addr struct to which to copy. + * + * @returns Whether or not the operation was successful, in particular, whether + * or not our address was an IPv4 address. + * + * @see CNetAddr::IsIPv4() + */ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const { if (!IsIPv4()) @@ -307,6 +376,16 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const return true; } +/** + * Try to get our IPv6 address. + * + * @param[out] pipv6Addr The in6_addr struct to which to copy. + * + * @returns Whether or not the operation was successful, in particular, whether + * or not our address was an IPv6 address. + * + * @see CNetAddr::IsIPv6() + */ bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const { if (!IsIPv6()) { @@ -316,8 +395,16 @@ bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const return true; } -// get canonical identifier of an address' group -// no two connections will be attempted to addresses with the same group +/** + * Get the canonical identifier of our network group + * + * The groups are assigned in a way where it should be costly for an attacker to + * obtain addresses with many different group identifiers, even if it is cheap + * to obtain addresses with the same identifier. + * + * @note No two connections will be attempted to addresses with the same network + * group. + */ std::vector<unsigned char> CNetAddr::GetGroup() const { std::vector<unsigned char> vchRet; @@ -379,12 +466,15 @@ std::vector<unsigned char> CNetAddr::GetGroup() const nBits = 32; vchRet.push_back(nClass); + + // push our ip onto vchRet byte by byte... while (nBits >= 8) { vchRet.push_back(GetByte(15 - nStartByte)); nStartByte++; nBits -= 8; } + // ...for the last byte, push nBits and for the rest of the byte push 1's if (nBits > 0) vchRet.push_back(GetByte(15 - nStartByte) | ((1 << (8 - nBits)) - 1)); @@ -526,6 +616,18 @@ bool operator<(const CService& a, const CService& b) return static_cast<CNetAddr>(a) < static_cast<CNetAddr>(b) || (static_cast<CNetAddr>(a) == static_cast<CNetAddr>(b) && a.port < b.port); } +/** + * Obtain the IPv4/6 socket address this represents. + * + * @param[out] paddr The obtained socket address. + * @param[in,out] addrlen The size, in bytes, of the address structure pointed + * to by paddr. The value that's pointed to by this + * parameter might change after calling this function if + * the size of the corresponding address structure + * changed. + * + * @returns Whether or not the operation was successful. + */ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const { if (IsIPv4()) { @@ -556,13 +658,16 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const return false; } +/** + * @returns An identifier unique to this service's address and port number. + */ std::vector<unsigned char> CService::GetKey() const { std::vector<unsigned char> vKey; vKey.resize(18); memcpy(vKey.data(), ip, 16); - vKey[16] = port / 0x100; - vKey[17] = port & 0x0FF; + vKey[16] = port / 0x100; // most significant byte of our port + vKey[17] = port & 0x0FF; // least significant byte of our port return vKey; } @@ -641,6 +746,10 @@ CSubNet::CSubNet(const CNetAddr &addr): network = addr; } +/** + * @returns True if this subnet is valid, the specified address is valid, and + * the specified address belongs in this subnet. + */ bool CSubNet::Match(const CNetAddr &addr) const { if (!valid || !addr.IsValid()) @@ -651,6 +760,10 @@ bool CSubNet::Match(const CNetAddr &addr) const return true; } +/** + * @returns The number of 1-bits in the prefix of the specified subnet mask. If + * the specified subnet mask is not a valid one, -1. + */ static inline int NetmaskBits(uint8_t x) { switch(x) { diff --git a/src/netaddress.h b/src/netaddress.h index ca435d17dc..8230e40606 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -48,10 +48,6 @@ class CNetAddr void SetRaw(Network network, const uint8_t *data); public: - /** - * Transform an arbitrary string into a non-routable ipv6 address. - * Useful for mapping resolved addresses back to their source. - */ bool SetInternal(const std::string& name); bool SetSpecial(const std::string &strName); // for Tor addresses @@ -69,8 +65,8 @@ class CNetAddr bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32) bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28) bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64) - bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96) - bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) + bool IsRFC6052() const; // IPv6 well-known prefix for IPv4-embedded address (64:FF9B::/96) + bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) (actually defined in RFC2765) bool IsTor() const; bool IsLocal() const; bool IsRoutable() const; |