bool CNetAddr::IsIPv6() const { return (!IsIPv4() && !IsTor() && !IsInternal()); }
bool CNetAddr::IsRFC5737() const { return IsIPv4() && ((GetByte(3) == 192 && GetByte(2) == 0 && GetByte(1) == 2) || (GetByte(3) == 198 && GetByte(2) == 51 && GetByte(1) == 100) || (GetByte(3) == 203 && GetByte(2) == 0 && GetByte(1) == 113)); }
// get canonical identifier of an address' group // no two connections will be attempted to addresses with the same group std::vector<unsigned char> CNetAddr::GetGroup() const { std::vector<unsigned char> vchRet; int nClass = NET_IPV6; int nStartByte = 0; int nBits = 16; // all local addresses belong to the same group if (IsLocal()) { nClass = 255; nBits = 0; } // all internal-usage addresses get their own group if (IsInternal()) { nClass = NET_INTERNAL; nStartByte = sizeof(g_internal_prefix); nBits = (sizeof(ip) - sizeof(g_internal_prefix)) * 8; } // all other unroutable addresses belong to the same group else if (!IsRoutable()) { nClass = NET_UNROUTABLE; nBits = 0; } // for IPv4 addresses, '1' + the 16 higher-order bits of the IP // includes mapped IPv4, SIIT translated IPv4, and the well-known prefix else if (IsIPv4() || IsRFC6145() || IsRFC6052()) { nClass = NET_IPV4; nStartByte = 12; } // for 6to4 tunnelled addresses, use the encapsulated IPv4 address else if (IsRFC3964()) { nClass = NET_IPV4; nStartByte = 2; } // for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address else if (IsRFC4380()) { vchRet.push_back(NET_IPV4); vchRet.push_back(GetByte(3) ^ 0xFF); vchRet.push_back(GetByte(2) ^ 0xFF); return vchRet; } else if (IsTor()) { nClass = NET_TOR; nStartByte = 6; nBits = 4; } // for he.net, use /36 groups else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70) nBits = 36; // for the rest of the IPv6 network, use /32 groups else nBits = 32; vchRet.push_back(nClass); while (nBits >= 8) { vchRet.push_back(GetByte(15 - nStartByte)); nStartByte++; nBits -= 8; } if (nBits > 0) vchRet.push_back(GetByte(15 - nStartByte) | ((1 << (8 - nBits)) - 1)); return vchRet; }
bool CNetAddr::IsRFC6598() const { return IsIPv4() && GetByte(3) == 100 && GetByte(2) >= 64 && GetByte(2) <= 127; }
bool CNetAddr::IsRFC3927() const { return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254); }
bool CNetAddr::IsRFC2544() const { return IsIPv4() && GetByte(3) == 198 && (GetByte(2) == 18 || GetByte(2) == 19); }
bool CNetAddr::IsMulticast() const { return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0) || (GetByte(15) == 0xFF); }
const char* sockAddrBase::ToString(bool includePort /*true*/) const { in_port_t port = includePort ? Port() : 0; if (IsIPv4()) { if (port == 0) return Ip4ToString(getIPv4Storage()->sin_addr); else return Ip4ToString(getIPv4Storage()->sin_addr, port); } else if (IsIPv6()) { const sockaddr_in6 *storage = getIPv6Storage(); if (storage->sin6_scope_id == 0 && !port) { // Just IPv6 address char *buffer; size_t bufsize = GetSmallTLSBuffer(&buffer); if (!bufsize) return "<memerror>"; if (!inet_ntop(AF_INET6, &storage->sin6_addr, buffer, bufsize)) return "<Invalid Address>"; return buffer; } else { // composite address char ifNameBuf[IF_NAMESIZE]; char addrStrBuf[INET6_ADDRSTRLEN]; const char *ifName = NULL; const char *addrStr = NULL; if (storage->sin6_scope_id) { ifName = if_indextoname(storage->sin6_scope_id, ifNameBuf); if (!ifName) ifName = "???"; } addrStr = inet_ntop(AF_INET6, &storage->sin6_addr, addrStrBuf, sizeof(addrStrBuf)); if (!addrStr) addrStr = "<Invalid IPv6>"; if (port) { if (ifName) return FormatShortStr("[%s%%%s]:%d", addrStr, ifName, (int)port); else return FormatShortStr("[%s]:%d", addrStr, (int)port); } else { if (ifName) return FormatShortStr("%s%%%s", addrStr, ifName); else { LogVerify(false); // should never happen return FormatShortStr("%s", addrStr); } } } } else return "<Invalid Address>"; }