-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Jv convert ipv4 mapped ipv6 to ipv4 #1906
base: master
Are you sure you want to change the base?
Changes from all commits
955bf47
616ed45
6ff422b
1b25e8a
5bbed5b
2ecb5df
c57f611
5d2b933
d44451d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -40,12 +40,22 @@ bool ContainsPrivateNetwork(Address::Family family, NRadixTree tree) { | |||||
return tree.IsAnyIPNetSubset(family, private_networks_tree) || private_networks_tree.IsAnyIPNetSubset(family, tree); | ||||||
} | ||||||
|
||||||
void ConnectionTracker::UpdateConnectionNoLock(const Connection& conn, const ConnStatus& status) { | ||||||
Connection ipv4Conn = conn.ConvertToIPv4(); | ||||||
EmplaceOrUpdateNoLock(ipv4Conn, status); | ||||||
} | ||||||
|
||||||
void ConnectionTracker::UpdateConnection(const Connection& conn, int64_t timestamp, bool added) { | ||||||
WITH_LOCK(mutex_) { | ||||||
EmplaceOrUpdateNoLock(conn, ConnStatus(timestamp, added)); | ||||||
} | ||||||
} | ||||||
|
||||||
void ConnectionTracker::UpdateEndpointNoLock(const ContainerEndpoint& endpoint, const ConnStatus& status) { | ||||||
ContainerEndpoint ipv4Endpoint = endpoint.ConvertToIPv4(); | ||||||
EmplaceOrUpdateNoLock(ipv4Endpoint, status); | ||||||
} | ||||||
|
||||||
void ConnectionTracker::Update( | ||||||
const std::vector<Connection>& all_conns, | ||||||
const std::vector<ContainerEndpoint>& all_listen_endpoints, | ||||||
|
@@ -63,7 +73,7 @@ void ConnectionTracker::Update( | |||||
|
||||||
// Insert (or mark as active) all current connections and listen endpoints. | ||||||
for (const auto& curr_conn : all_conns) { | ||||||
EmplaceOrUpdateNoLock(curr_conn, new_status); | ||||||
UpdateConnectionNoLock(curr_conn, new_status); | ||||||
} | ||||||
for (const auto& curr_endpoint : all_listen_endpoints) { | ||||||
EmplaceOrUpdateNoLock(curr_endpoint, new_status); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,7 +84,9 @@ class CollectorStats; | |
|
||
class ConnectionTracker { | ||
public: | ||
void UpdateConnectionNoLock(const Connection& conn, const ConnStatus& status); | ||
void UpdateConnection(const Connection& conn, int64_t timestamp, bool added); | ||
void UpdateEndpointNoLock(const ContainerEndpoint& endpoint, const ConnStatus& status); | ||
void AddConnection(const Connection& conn, int64_t timestamp) { | ||
Comment on lines
+87
to
90
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should keep the |
||
UpdateConnection(conn, timestamp, true); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,7 +52,54 @@ class Address { | |
std::memcpy(data_.data(), data.data(), Length(family)); | ||
} | ||
|
||
Address(Family family, const std::array<uint64_t, kU64MaxLen>& data) : data_(data), family_(family) {} | ||
// bool IsIPv4MappedIPv6(const Family& family, const std::array<uint64_t, kU64MaxLen>& data) const { | ||
// if (family != Family::IPV6) { | ||
// return false; | ||
// } | ||
|
||
// const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data.data()); | ||
|
||
// // First 80 bits, 10 bytes, should be 0 if this is IPv4-Mapped IPv6 | ||
// for (int i = 0; i < 10; i++) { | ||
// if (bytes[i] != 0) { | ||
// return false; | ||
// } | ||
// } | ||
|
||
// // Next 2 bytes should be 0xFF if this is IPv4-Mapped IPv6 | ||
// if (bytes[10] != 0xFF || bytes[11] != 0xFF) { | ||
// return false; | ||
// } | ||
|
||
// return true; | ||
//} | ||
|
||
bool IsIPv4MappedIPv6(const Family& family, const std::array<uint64_t, kU64MaxLen>& data) const { | ||
if (family != Family::IPV6) { | ||
return false; | ||
} | ||
|
||
// In IPv4-mapped IPv6 the first 80 bits are zeros and the next 16 bits are ones | ||
// data[0] is 64 bits and therefore is all zeros. The next 16 bits which are the | ||
// first 16 bits of data[1] need to be 0. The next 16 bits of data[1] need to be | ||
// ones in order for the data to represent IPv4-mapped IPv6 | ||
return data[0] == 0 && (data[1] & 0xFFFFFFFF00000000ULL) == 0x0000FFFF00000000ULL; | ||
} | ||
|
||
Address(Family family, const std::array<uint64_t, kU64MaxLen>& data, bool convertIPv4MappedIPv6 = true) { | ||
if (convertIPv4MappedIPv6 && IsIPv4MappedIPv6(family, data)) { | ||
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data.data()); | ||
uint32_t ipv4 = htonl(static_cast<uint32_t>(bytes[12]) << 24 | | ||
static_cast<uint32_t>(bytes[13]) << 16 | | ||
static_cast<uint32_t>(bytes[14]) << 8 | | ||
static_cast<uint32_t>(bytes[15])); | ||
std::memcpy(data_.data(), &ipv4, sizeof(ipv4)); | ||
family_ = Family::IPV4; | ||
} else { | ||
family_ = family; | ||
data_ = data; | ||
} | ||
} | ||
|
||
// Constructs an IPv4 address given a uint32_t containing the IPv4 address in *network* byte order. | ||
explicit Address(uint32_t ipv4) : data_({htonll(static_cast<uint64_t>(ntohl(ipv4)) << 32), 0}), family_(Family::IPV4) {} | ||
|
@@ -63,6 +110,29 @@ class Address { | |
std::memcpy(data_.data(), &ipv6[0], sizeof(data_)); | ||
} | ||
|
||
bool IsIPv4MappedIPv6(const uint32_t (&ipv6)[4]) const { | ||
//// In IPv4-mapped IPv6 the first 80 bits are zeros and the next 16 bits are ones | ||
//// data[0] is 64 bits and therefore is all zeros. The next 16 bits which are the | ||
//// first 16 bits of data[1] need to be 0. The next 16 bits of data[1] need to be | ||
//// ones in order for the data to represent IPv4-mapped IPv6 | ||
return ipv6[0] == 0 && ipv6[1] == 0 && ipv6[2] == 0x0000FFFF; | ||
} | ||
|
||
// uint32_t ConvertIPv6DataToIPv4Data( | ||
|
||
//// Constructs an IPv6 address from 4 network-encoded uint32_ts, in network order (high to low) | ||
////explicit Address(const uint32_t (&ipv6)[4], bool convertIPv4MappedIPv6 = true) { | ||
// explicit Address(const uint32_t (&ipv6)[4]) { | ||
// static_assert(sizeof(data_) == sizeof(ipv6)); | ||
// if (IsIPv4MappedIPv6(ipv6)) { | ||
// family_(Family::IPV4); | ||
// //std::memcpy(data_.data(), &ipv6[0], sizeof(data_)); | ||
// } else { | ||
// family_(Family::IPV6); | ||
// std::memcpy(data_.data(), &ipv6[0], sizeof(data_)); | ||
// } | ||
// } | ||
|
||
// Constructs an IPv6 address from 2 network-encoded uint64_ts, in network order (high, low). | ||
Address(uint64_t ipv6_high, uint64_t ipv6_low) : data_({ipv6_high, ipv6_low}), family_(Family::IPV6) {} | ||
|
||
|
@@ -137,6 +207,36 @@ class Address { | |
} | ||
} | ||
|
||
bool IsIPv4MappedIPv6() const { | ||
if (family_ != Family::IPV6) { | ||
return false; | ||
} | ||
|
||
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data_.data()); | ||
|
||
// First 80 bits, 10 bytes, should be 0 if this is IPv4-Mapped IPv6 | ||
for (int i = 0; i < 10; i++) { | ||
if (bytes[i] != 0) { | ||
return false; | ||
} | ||
} | ||
|
||
// Next 2 bytes should be 0xFF if this is IPv4-Mapped IPv6 | ||
if (bytes[10] != 0xFF || bytes[11] != 0xFF) { | ||
return false; | ||
} | ||
Comment on lines
+215
to
+227
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For performance reasons, what about declaring a global const IPNet with the /96 mapped prefix, and using |
||
|
||
return true; | ||
} | ||
|
||
Address ConvertToIPv4() const { | ||
// Extract the last 32 bits of the IPv6 address, which is the IPv4 address part. | ||
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data_.data()); | ||
|
||
// Last 4 bytes of the IPv6 address hold the IPv4 address | ||
return Address(bytes[12], bytes[13], bytes[14], bytes[15]); | ||
} | ||
|
||
private: | ||
friend std::ostream& operator<<(std::ostream& os, const Address& addr) { | ||
int af = (addr.family_ == Family::IPV4) ? AF_INET : AF_INET6; | ||
|
@@ -262,6 +362,16 @@ class IPNet { | |
return address_ > that.address_; | ||
} | ||
|
||
bool IsIPv4MappedIPv6() const { | ||
return address_.IsIPv4MappedIPv6(); | ||
} | ||
|
||
IPNet ConvertToIPv4() const { | ||
Address ipv4Address = address_.ConvertToIPv4(); | ||
size_t bits = bits_ - 96; // 96 = 128 - 32 | ||
return IPNet(ipv4Address, bits, is_addr_); | ||
} | ||
|
||
private: | ||
friend std::ostream& operator<<(std::ostream& os, const IPNet& net) { | ||
return os << net.address_ << "/" << net.bits_; | ||
|
@@ -299,6 +409,15 @@ class Endpoint { | |
return port_ == 0 && network_.IsNull(); | ||
} | ||
|
||
bool IsIPv4MappedIPv6() const { | ||
return network_.IsIPv4MappedIPv6(); | ||
} | ||
|
||
Endpoint ConvertToIPv4() const { | ||
IPNet network = network_.ConvertToIPv4(); | ||
return Endpoint(network, port_); | ||
} | ||
|
||
private: | ||
friend std::ostream& operator<<(std::ostream& os, const Endpoint& ep) { | ||
// This is an individual IP address. | ||
|
@@ -358,6 +477,14 @@ class ContainerEndpoint { | |
|
||
size_t Hash() const { return HashAll(container_, endpoint_, l4proto_); } | ||
|
||
ContainerEndpoint ConvertToIPv4() const { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The name is misleading as it suggests that the result is always IPv4 |
||
if (endpoint_.IsIPv4MappedIPv6()) { | ||
Endpoint ep = endpoint_.ConvertToIPv4(); | ||
return ContainerEndpoint(container_, ep, l4proto_, originator_); | ||
} | ||
return *this; | ||
} | ||
|
||
private: | ||
std::string container_; | ||
Endpoint endpoint_; | ||
|
@@ -389,6 +516,31 @@ class Connection { | |
|
||
size_t Hash() const { return HashAll(container_, local_, remote_, flags_); } | ||
|
||
Connection ConvertToIPv4() const { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change the name to |
||
bool localMapped = local_.IsIPv4MappedIPv6(); | ||
bool remoteMapped = remote_.IsIPv4MappedIPv6(); | ||
|
||
if (!localMapped && !remoteMapped) { | ||
return *this; | ||
} | ||
|
||
Endpoint local; | ||
if (localMapped) { | ||
local = local_.ConvertToIPv4(); | ||
} else { | ||
local = local_; | ||
} | ||
|
||
Endpoint remote; | ||
if (remoteMapped) { | ||
remote = remote_.ConvertToIPv4(); | ||
} else { | ||
remote = remote_; | ||
} | ||
|
||
return Connection(container_, local, remote, l4proto(), is_server()); | ||
} | ||
|
||
private: | ||
std::string container_; | ||
Endpoint local_; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ipv4Conn
is misleading, as as the result can be v6There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I know. I should have called it something else or left a comment to remind myself to change the name.