mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 23:09:44 -04:00
Merge bitcoin/bitcoin#21756: Avoid calling getnameinfo
when formatting IPv6 addresses in CNetAddr::ToStringIP
54548bae80
net: Avoid calling getnameinfo when formatting IPv6 addresses in CNetAddr::ToStringIP (practicalswift)c10f27fdb2
net: Make IPv6ToString do zero compression as described in RFC 5952 (practicalswift) Pull request description: Avoid calling `getnameinfo` when formatting IPv6 addresses in `CNetAddr::ToStringIP`. Fixes #21466. Fixes #21967. The IPv4 case was fixed in #21564. ACKs for top commit: laanwj: Code review ACK54548bae80
vasild: ACK54548bae80
Tree-SHA512: 8404e458b29efdb7bf78b91adc075d05e0385969d1532cccaa2c7cb69cd77411c42d95fcefc4000137b9f2076fe395731c7d9844b7d42b58a6d3bec69eed6fce
This commit is contained in:
commit
7b87fca930
1 changed files with 48 additions and 20 deletions
|
@ -556,11 +556,12 @@ static std::string IPv4ToString(Span<const uint8_t> a)
|
||||||
return strprintf("%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
|
return strprintf("%u.%u.%u.%u", a[0], a[1], a[2], a[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return an IPv6 address text representation with zero compression as described in RFC 5952
|
||||||
|
// ("A Recommendation for IPv6 Address Text Representation").
|
||||||
static std::string IPv6ToString(Span<const uint8_t> a)
|
static std::string IPv6ToString(Span<const uint8_t> a)
|
||||||
{
|
{
|
||||||
assert(a.size() == ADDR_IPV6_SIZE);
|
assert(a.size() == ADDR_IPV6_SIZE);
|
||||||
// clang-format off
|
const std::array groups{
|
||||||
return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
|
|
||||||
ReadBE16(&a[0]),
|
ReadBE16(&a[0]),
|
||||||
ReadBE16(&a[2]),
|
ReadBE16(&a[2]),
|
||||||
ReadBE16(&a[4]),
|
ReadBE16(&a[4]),
|
||||||
|
@ -568,8 +569,44 @@ static std::string IPv6ToString(Span<const uint8_t> a)
|
||||||
ReadBE16(&a[8]),
|
ReadBE16(&a[8]),
|
||||||
ReadBE16(&a[10]),
|
ReadBE16(&a[10]),
|
||||||
ReadBE16(&a[12]),
|
ReadBE16(&a[12]),
|
||||||
ReadBE16(&a[14]));
|
ReadBE16(&a[14]),
|
||||||
// clang-format on
|
};
|
||||||
|
|
||||||
|
// The zero compression implementation is inspired by Rust's std::net::Ipv6Addr, see
|
||||||
|
// https://github.com/rust-lang/rust/blob/cc4103089f40a163f6d143f06359cba7043da29b/library/std/src/net/ip.rs#L1635-L1683
|
||||||
|
struct ZeroSpan {
|
||||||
|
size_t start_index{0};
|
||||||
|
size_t len{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find longest sequence of consecutive all-zero fields. Use first zero sequence if two or more
|
||||||
|
// zero sequences of equal length are found.
|
||||||
|
ZeroSpan longest, current;
|
||||||
|
for (size_t i{0}; i < groups.size(); ++i) {
|
||||||
|
if (groups[i] != 0) {
|
||||||
|
current = {i + 1, 0};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
current.len += 1;
|
||||||
|
if (current.len > longest.len) {
|
||||||
|
longest = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string r;
|
||||||
|
r.reserve(39);
|
||||||
|
for (size_t i{0}; i < groups.size(); ++i) {
|
||||||
|
// Replace the longest sequence of consecutive all-zero fields with two colons ("::").
|
||||||
|
if (longest.len >= 2 && i >= longest.start_index && i < longest.start_index + longest.len) {
|
||||||
|
if (i == longest.start_index) {
|
||||||
|
r += "::";
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
r += strprintf("%s%x", ((!r.empty() && r.back() != ':') ? ":" : ""), groups[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CNetAddr::ToStringIP() const
|
std::string CNetAddr::ToStringIP() const
|
||||||
|
@ -578,15 +615,6 @@ std::string CNetAddr::ToStringIP() const
|
||||||
case NET_IPV4:
|
case NET_IPV4:
|
||||||
return IPv4ToString(m_addr);
|
return IPv4ToString(m_addr);
|
||||||
case NET_IPV6: {
|
case NET_IPV6: {
|
||||||
CService serv(*this, 0);
|
|
||||||
struct sockaddr_storage sockaddr;
|
|
||||||
socklen_t socklen = sizeof(sockaddr);
|
|
||||||
if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) {
|
|
||||||
char name[1025] = "";
|
|
||||||
if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name,
|
|
||||||
sizeof(name), nullptr, 0, NI_NUMERICHOST))
|
|
||||||
return std::string(name);
|
|
||||||
}
|
|
||||||
return IPv6ToString(m_addr);
|
return IPv6ToString(m_addr);
|
||||||
}
|
}
|
||||||
case NET_ONION:
|
case NET_ONION:
|
||||||
|
|
Loading…
Add table
Reference in a new issue