Skip to content
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

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
12 changes: 11 additions & 1 deletion collector/lib/ConnTracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Copy link
Contributor

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 v6

Copy link
Contributor Author

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.

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,
Expand All @@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
EmplaceOrUpdateNoLock(curr_endpoint, new_status);
UpdateEndpointNoLock(curr_endpoint, new_status);

Expand Down
2 changes: 2 additions & 0 deletions collector/lib/ConnTracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should keep the NoLock methods in the private scope. I suggest that we move the ones previously laying in the public section as well.

UpdateConnection(conn, timestamp, true);
}
Expand Down
82 changes: 82 additions & 0 deletions collector/lib/NetworkConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,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
Copy link
Contributor

Choose a reason for hiding this comment

The 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 .Contains(addr) ?


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;
Expand Down Expand Up @@ -262,6 +292,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_;
Expand Down Expand Up @@ -299,6 +339,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.
Expand Down Expand Up @@ -358,6 +407,14 @@ class ContainerEndpoint {

size_t Hash() const { return HashAll(container_, endpoint_, l4proto_); }

ContainerEndpoint ConvertToIPv4() const {
Copy link
Contributor

Choose a reason for hiding this comment

The 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 std::move(*this);
}

private:
std::string container_;
Endpoint endpoint_;
Expand Down Expand Up @@ -389,6 +446,31 @@ class Connection {

size_t Hash() const { return HashAll(container_, local_, remote_, flags_); }

Connection ConvertToIPv4() const {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the name to ConvertToIPv4IfNeeded

bool localMapped = local_.IsIPv4MappedIPv6();
bool remoteMapped = remote_.IsIPv4MappedIPv6();

if (!localMapped && !remoteMapped) {
return std::move(*this);
}

Endpoint local;
if (localMapped) {
local = local_.ConvertToIPv4();
} else {
local = std::move(local_);
}

Endpoint remote;
if (localMapped) {
remote = remote_.ConvertToIPv4();
} else {
remote = std::move(remote_);
}

return Connection(container_, local, remote, l4proto(), is_server());
}

private:
std::string container_;
Endpoint local_;
Expand Down
Loading