|
|
|
@ -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) {
|
|
|
|
|