Use ASNs for mapped IPv4 addresses correctly
This commit is contained in:
1 parent
6f8c937312
commit
38c2395d7a
2 files changed
+61
-41
No files matched your search
+56
-41
@@ -401,6 +401,26 @@ bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
|
|||||||
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()) {
|
||||||
@@ -410,7 +430,7 @@ uint32_t CNetAddr::GetNetClass() const {
|
|||||||
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() || IsRFC4380()) {
|
} else if (HasLinkedIPv4()) {
|
||||||
net_class = NET_IPV4;
|
net_class = NET_IPV4;
|
||||||
} else if (IsTor()) {
|
} else if (IsTor()) {
|
||||||
net_class = NET_ONION;
|
net_class = NET_ONION;
|
||||||
@@ -424,10 +444,24 @@ uint32_t CNetAddr::GetMappedAS(const std::vector<bool> &asmap) const {
|
|||||||
return 0; // Indicates not found, safe because AS0 is reserved per RFC7607.
|
return 0; // Indicates not found, safe because AS0 is reserved per RFC7607.
|
||||||
}
|
}
|
||||||
std::vector<bool> ip_bits(128);
|
std::vector<bool> ip_bits(128);
|
||||||
for (int8_t byte_i = 0; byte_i < 16; ++byte_i) {
|
if (HasLinkedIPv4()) {
|
||||||
uint8_t cur_byte = GetByte(15 - byte_i);
|
// For lookup, treat as if it was just an IPv4 address (pchIPv4 prefix + IPv4 bits)
|
||||||
for (uint8_t bit_i = 0; bit_i < 8; ++bit_i) {
|
for (int8_t byte_i = 0; byte_i < 12; ++byte_i) {
|
||||||
ip_bits[byte_i * 8 + bit_i] = (cur_byte >> (7 - bit_i)) & 1;
|
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) {
|
||||||
|
uint8_t cur_byte = GetByte(15 - byte_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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint32_t mapped_as = Interpret(asmap, ip_bits);
|
uint32_t mapped_as = Interpret(asmap, ip_bits);
|
||||||
@@ -463,51 +497,32 @@ std::vector<unsigned char> CNetAddr::GetGroup(const std::vector<bool> &asmap) co
|
|||||||
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()) {
|
||||||
// all internal-usage addresses get their own group
|
// all internal-usage addresses get their own group
|
||||||
if (IsInternal())
|
|
||||||
{
|
|
||||||
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()) {
|
||||||
// all other unroutable addresses belong to the same group
|
// all other unroutable addresses belong to the same group
|
||||||
else if (!IsRoutable())
|
|
||||||
{
|
|
||||||
nBits = 0;
|
nBits = 0;
|
||||||
}
|
} else if (HasLinkedIPv4()) {
|
||||||
// for IPv4 addresses, '1' + the 16 higher-order bits of the IP
|
// IPv4 addresses (and mapped IPv4 addresses) use /16 groups
|
||||||
// includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
|
uint32_t ipv4 = GetLinkedIPv4();
|
||||||
else if (IsIPv4() || IsRFC6145() || IsRFC6052())
|
vchRet.push_back((ipv4 >> 24) & 0xFF);
|
||||||
{
|
vchRet.push_back((ipv4 >> 16) & 0xFF);
|
||||||
nStartByte = 12;
|
|
||||||
}
|
|
||||||
// for 6to4 tunnelled addresses, use the encapsulated IPv4 address
|
|
||||||
else if (IsRFC3964())
|
|
||||||
{
|
|
||||||
nStartByte = 2;
|
|
||||||
}
|
|
||||||
// for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address
|
|
||||||
else if (IsRFC4380())
|
|
||||||
{
|
|
||||||
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 && GetByte(13) == 0x04 && GetByte(12) == 0x70) {
|
||||||
// for he.net, use /36 groups
|
// for he.net, use /36 groups
|
||||||
else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
|
|
||||||
nBits = 36;
|
nBits = 36;
|
||||||
// for the rest of the IPv6 network, use /32 groups
|
} else {
|
||||||
else
|
// for the rest of the IPv6 network, use /32 groups
|
||||||
nBits = 32;
|
nBits = 32;
|
||||||
|
}
|
||||||
|
|
||||||
// push our ip onto vchRet byte by byte...
|
// push our ip onto vchRet byte by byte...
|
||||||
while (nBits >= 8)
|
while (nBits >= 8)
|
||||||
|
|||||||
@@ -80,6 +80,11 @@ class CNetAddr
|
|||||||
bool GetInAddr(struct in_addr* pipv4Addr) const;
|
bool GetInAddr(struct in_addr* pipv4Addr) const;
|
||||||
uint32_t GetNetClass() const;
|
uint32_t GetNetClass() const;
|
||||||
|
|
||||||
|
//! For IPv4, mapped IPv4, SIIT translated IPv4, Teredo, 6to4 tunneled addresses, return the relevant IPv4 address as a uint32.
|
||||||
|
uint32_t GetLinkedIPv4() const;
|
||||||
|
//! Whether this address has a linked IPv4 address (see GetLinkedIPv4()).
|
||||||
|
bool HasLinkedIPv4() const;
|
||||||
|
|
||||||
// The AS on the BGP path to the node we use to diversify
|
// The AS on the BGP path to the node we use to diversify
|
||||||
// peers in AddrMan bucketing based on the AS infrastructure.
|
// peers in AddrMan bucketing based on the AS infrastructure.
|
||||||
// The ip->AS mapping depends on how asmap is constructed.
|
// The ip->AS mapping depends on how asmap is constructed.
|
||||||
|
|||||||
Reference in new issue
Block a user