bool IPAddress::operator<(const IPAddress& ha) const { if (AddressFamily != ha.AddressFamily) return (int)get_AddressFamily() < (int)ha.get_AddressFamily(); switch ((int)get_AddressFamily()) { case AF_INET: return memcmp(&m_sin.sin_addr, &ha.m_sin.sin_addr, 4) < 0; case AF_INET6: return memcmp(&m_sin6.sin6_addr, &ha.m_sin6.sin6_addr, 16) < 0; default: Throw(ExtErr::UnknownHostAddressType); } }
size_t IPAddress::GetHashCode() const { size_t r = std::hash<uint16_t>()((uint16_t)get_AddressFamily()); switch ((int)get_AddressFamily()) { case AF_INET: r += std::hash<uint32_t>()(*(uint32_t*)&m_sin.sin_addr); break; case AF_INET6: r += hash_value(Span((const uint8_t*)&m_sin6.sin6_addr, 16)); break; default: Throw(ExtErr::UnknownHostAddressType); } return r; }
size_t IPAddress::GetHashCode() const { size_t r = std::hash<uint16_t>()((uint16_t)get_AddressFamily()); switch ((int)get_AddressFamily()) { case AF_DOMAIN_NAME: r += std::hash<String>()(m_domainname); break; case AF_INET: r += std::hash<uint32_t>()(*(uint32_t*)&m_sin.sin_addr); break; case AF_INET6: r += hash_value(ConstBuf(&m_sin6.sin6_addr, 16)); break; default: Throw(ExtErr::UnknownHostAddressType); } return r; }
String IPAddress::ToString() const { switch ((int)get_AddressFamily()) { case AF_INET: return HostToStr(ntohl(m_sin.sin_addr.s_addr)); case AF_INET6: { char buf[INET6_ADDRSTRLEN]; if (!::inet_ntop((int)get_AddressFamily(), (void*)&m_sin6.sin6_addr, buf, sizeof buf)) return "<#IPv6 address>"; //!!!? XP fails if IPv6 not installed //was CCheck(-1); return buf; } #if UCFG_USE_POSIX && !defined(__FreeBSD__) case AF_PACKET: return ":AF_PACKET:"; #endif default: return "Address Family "+Convert::ToString((int)get_AddressFamily()); } }
IPAddress& IPAddress::operator=(const IPAddress& ha) { AddressFamily = ha.AddressFamily; uint16_t port = m_sin.sin_port; memcpy(&m_sin6, &ha.m_sin6, sizeof m_sin6); switch ((int)get_AddressFamily()) { case AF_INET: case AF_INET6: m_sin.sin_port = port; } return _self; }
bool IPAddress::operator==(const IPAddress& ha) const { if (AddressFamily != ha.AddressFamily) return false; switch ((int)get_AddressFamily()) { case AF_INET: return *(int32_t*)&m_sin.sin_addr == *(int32_t*)&ha.m_sin.sin_addr; case AF_INET6: return !memcmp(&m_sin6.sin6_addr, &ha.m_sin6.sin6_addr, 16); default: Throw(ExtErr::UnknownHostAddressType); } }
Blob IPAddress::GetAddressBytes() const { int size = FamilySize(AddressFamily); if (!size) Throw(ExtErr::UnknownHostAddressType); switch ((int)get_AddressFamily()) { case AF_INET: return Blob(&m_sin.sin_addr, 4); case AF_INET6: return Blob(&m_sin6.sin6_addr, 16); default: Throw(ExtErr::UnknownHostAddressType); } }
uint32_t IPAddress::GetIP() const { uint32_t nhost; switch ((int)get_AddressFamily()) { case AF_DOMAIN_NAME: if ((nhost = inet_addr(m_domainname)) != INADDR_NONE) return ntohl(nhost); return Dns::GetHostEntry(m_domainname).AddressList[0].GetIP(); case AF_INET: nhost = ntohl(m_sin.sin_addr.s_addr); break; default: Throw(ExtErr::UnknownHostAddressType); } return nhost; }
bool IPAddress::IsGlobal() const { switch ((int)get_AddressFamily()) { case AF_INET: { uint32_t hip = ntohl(m_sin.sin_addr.s_addr); return hip != 0 && (hip & 0xFF000000) != 0x7F000000 // 127.x.x.x && (hip & 0xFFFF0000) != 0xC0A80000 // 192.168.x.x && (hip & 0xFFF00000) != 0xAC100000 // 172.16.x.x && (hip & 0xFF000000) != 0x0A000000 // 10.x.x.x && (hip & 0xFFFF0000) != 0xA9FE0000; // 169.254.x.x (RFC 3927) } break; case AF_INET6: { uint16_t fam = *(uint8_t*)&m_sin6.sin6_addr; return fam > 0 && fam<0xFC; } default: Throw(E_FAIL); } }
bool IPAddress::get_IsIPv6Teredo() const { return (int)get_AddressFamily() == AF_INET6 && *(uint32_t*)&m_sin6.sin6_addr == htonl(0x20010000); }
bool IPAddress::get_IsIPv4MappedToIPv6() const { return (int)get_AddressFamily() == AF_INET6 && !memcmp(&m_sin6.sin6_addr, "\xFF\xFF" "0000000000", 12); }
void IPAddress::Normalize() { //!!!TODO for IPv6 if ((int)get_AddressFamily() == AF_DOMAIN_NAME) operator=(IPAddress(htonl(GetIP()))); }