Changeset View
Changeset View
Standalone View
Standalone View
src/netaddress.cpp
Show First 20 Lines • Show All 398 Lines • ▼ Show 20 Lines | |||||
bool CNetAddr::GetIn6Addr(struct in6_addr *pipv6Addr) const { | bool CNetAddr::GetIn6Addr(struct in6_addr *pipv6Addr) const { | ||||
if (!IsIPv6()) { | if (!IsIPv6()) { | ||||
return false; | return false; | ||||
} | } | ||||
memcpy(pipv6Addr, ip, 16); | memcpy(pipv6Addr, ip, 16); | ||||
return true; | return true; | ||||
} | } | ||||
bool CNetAddr::HasLinkedIPv4() const { | |||||
return IsRoutable() && (IsIPv4() || IsRFC6145() || IsRFC6052() || | |||||
IsRFC3964() || IsRFC4380()); | |||||
} | |||||
uint32_t CNetAddr::GetLinkedIPv4() const { | |||||
if (IsIPv4() || IsRFC6145() || IsRFC6052()) { | |||||
// IPv4, mapped IPv4, SIIT translated IPv4: the IPv4 address is the last | |||||
// 4 bytes of the address | |||||
return ReadBE32(ip + 12); | |||||
} else if (IsRFC3964()) { | |||||
// 6to4 tunneled IPv4: the IPv4 address is in bytes 2-6 | |||||
return ReadBE32(ip + 2); | |||||
} else if (IsRFC4380()) { | |||||
// Teredo tunneled IPv4: the IPv4 address is in the last 4 bytes of the | |||||
// address, but bitflipped | |||||
return ~ReadBE32(ip + 12); | |||||
} | |||||
assert(false); | |||||
} | |||||
uint32_t CNetAddr::GetNetClass() const { | uint32_t CNetAddr::GetNetClass() const { | ||||
uint32_t net_class = NET_IPV6; | uint32_t net_class = NET_IPV6; | ||||
if (IsLocal()) { | if (IsLocal()) { | ||||
net_class = 255; | net_class = 255; | ||||
} | } | ||||
if (IsInternal()) { | if (IsInternal()) { | ||||
net_class = NET_INTERNAL; | net_class = NET_INTERNAL; | ||||
} else if (!IsRoutable()) { | } else if (!IsRoutable()) { | ||||
net_class = NET_UNROUTABLE; | net_class = NET_UNROUTABLE; | ||||
} else if (IsIPv4() || IsRFC6145() || IsRFC6052() || IsRFC3964() || | } else if (HasLinkedIPv4()) { | ||||
IsRFC4380()) { | |||||
net_class = NET_IPV4; | net_class = NET_IPV4; | ||||
} else if (IsTor()) { | } else if (IsTor()) { | ||||
net_class = NET_ONION; | net_class = NET_ONION; | ||||
} | } | ||||
return net_class; | return net_class; | ||||
} | } | ||||
uint32_t CNetAddr::GetMappedAS(const std::vector<bool> &asmap) const { | uint32_t CNetAddr::GetMappedAS(const std::vector<bool> &asmap) const { | ||||
uint32_t net_class = GetNetClass(); | uint32_t net_class = GetNetClass(); | ||||
if (asmap.size() == 0 || (net_class != NET_IPV4 && net_class != NET_IPV6)) { | if (asmap.size() == 0 || (net_class != NET_IPV4 && net_class != NET_IPV6)) { | ||||
return 0; // Indicates not found, safe because AS0 is reserved per | return 0; // Indicates not found, safe because AS0 is reserved per | ||||
// RFC7607. | // RFC7607. | ||||
} | } | ||||
std::vector<bool> ip_bits(128); | std::vector<bool> ip_bits(128); | ||||
if (HasLinkedIPv4()) { | |||||
// For lookup, treat as if it was just an IPv4 address (pchIPv4 prefix + | |||||
// IPv4 bits) | |||||
for (int8_t byte_i = 0; byte_i < 12; ++byte_i) { | |||||
for (uint8_t bit_i = 0; bit_i < 8; ++bit_i) { | |||||
ip_bits[byte_i * 8 + bit_i] = | |||||
(pchIPv4[byte_i] >> (7 - bit_i)) & 1; | |||||
} | |||||
} | |||||
uint32_t ipv4 = GetLinkedIPv4(); | |||||
for (int i = 0; i < 32; ++i) { | |||||
ip_bits[96 + i] = (ipv4 >> (31 - i)) & 1; | |||||
} | |||||
} else { | |||||
// Use all 128 bits of the IPv6 address otherwise | |||||
for (int8_t byte_i = 0; byte_i < 16; ++byte_i) { | for (int8_t byte_i = 0; byte_i < 16; ++byte_i) { | ||||
uint8_t cur_byte = GetByte(15 - byte_i); | uint8_t cur_byte = GetByte(15 - byte_i); | ||||
for (uint8_t bit_i = 0; bit_i < 8; ++bit_i) { | for (uint8_t bit_i = 0; bit_i < 8; ++bit_i) { | ||||
ip_bits[byte_i * 8 + bit_i] = (cur_byte >> (7 - bit_i)) & 1; | ip_bits[byte_i * 8 + bit_i] = (cur_byte >> (7 - bit_i)) & 1; | ||||
} | } | ||||
} | } | ||||
} | |||||
uint32_t mapped_as = Interpret(asmap, ip_bits); | uint32_t mapped_as = Interpret(asmap, ip_bits); | ||||
return mapped_as; | return mapped_as; | ||||
} | } | ||||
/** | /** | ||||
* Get the canonical identifier of our network 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 | * The groups are assigned in a way where it should be costly for an attacker to | ||||
Show All 18 Lines | if (asn != 0) { // Either asmap was empty, or address has non-asmappable net | ||||
} | } | ||||
return vchRet; | return vchRet; | ||||
} | } | ||||
vchRet.push_back(net_class); | vchRet.push_back(net_class); | ||||
int nStartByte = 0; | int nStartByte = 0; | ||||
int nBits = 16; | int nBits = 16; | ||||
// all local addresses belong to the same group | |||||
if (IsLocal()) { | if (IsLocal()) { | ||||
// all local addresses belong to the same group | |||||
nBits = 0; | nBits = 0; | ||||
} | } else if (IsInternal()) { | ||||
if (IsInternal()) { | |||||
// all internal-usage addresses get their own group | // all internal-usage addresses get their own group | ||||
nStartByte = sizeof(g_internal_prefix); | nStartByte = sizeof(g_internal_prefix); | ||||
nBits = (sizeof(ip) - sizeof(g_internal_prefix)) * 8; | nBits = (sizeof(ip) - sizeof(g_internal_prefix)) * 8; | ||||
} else if (!IsRoutable()) { | } else if (!IsRoutable()) { | ||||
// all other unroutable addresses belong to the same group | // all other unroutable addresses belong to the same group | ||||
nBits = 0; | nBits = 0; | ||||
} else if (IsIPv4() || IsRFC6145() || IsRFC6052()) { | } else if (HasLinkedIPv4()) { | ||||
// for IPv4 addresses, '1' + the 16 higher-order bits of the IP includes | // IPv4 addresses (and mapped IPv4 addresses) use /16 groups | ||||
// mapped IPv4, SIIT translated IPv4, and the well-known prefix | uint32_t ipv4 = GetLinkedIPv4(); | ||||
nStartByte = 12; | vchRet.push_back((ipv4 >> 24) & 0xFF); | ||||
} else if (IsRFC3964()) { | vchRet.push_back((ipv4 >> 16) & 0xFF); | ||||
// for 6to4 tunnelled addresses, use the encapsulated IPv4 address | |||||
nStartByte = 2; | |||||
} else if (IsRFC4380()) { | |||||
// for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 | |||||
// address | |||||
vchRet.push_back(GetByte(3) ^ 0xFF); | |||||
vchRet.push_back(GetByte(2) ^ 0xFF); | |||||
return vchRet; | return vchRet; | ||||
} else if (IsTor()) { | } else if (IsTor()) { | ||||
nStartByte = 6; | nStartByte = 6; | ||||
nBits = 4; | nBits = 4; | ||||
} else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && | } else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && | ||||
GetByte(13) == 0x04 && GetByte(12) == 0x70) { | GetByte(13) == 0x04 && GetByte(12) == 0x70) { | ||||
// for he.net, use /36 groups | // for he.net, use /36 groups | ||||
nBits = 36; | nBits = 36; | ||||
▲ Show 20 Lines • Show All 408 Lines • Show Last 20 Lines |