mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
Merge 4c53178256
into c5e44a0435
This commit is contained in:
commit
8534b1e0eb
1 changed files with 70 additions and 30 deletions
|
@ -36,6 +36,9 @@ namespace {
|
||||||
// will fail, so we skip that.
|
// will fail, so we skip that.
|
||||||
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 1400000)
|
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 1400000)
|
||||||
|
|
||||||
|
// Good for responses containing ~ 10,000-15,000 routes.
|
||||||
|
static constexpr ssize_t NETLINK_MAX_RESPONSE_SIZE{1'048'576};
|
||||||
|
|
||||||
std::optional<CNetAddr> QueryDefaultGatewayImpl(sa_family_t family)
|
std::optional<CNetAddr> QueryDefaultGatewayImpl(sa_family_t family)
|
||||||
{
|
{
|
||||||
// Create a netlink socket.
|
// Create a netlink socket.
|
||||||
|
@ -84,6 +87,10 @@ std::optional<CNetAddr> QueryDefaultGatewayImpl(sa_family_t family)
|
||||||
|
|
||||||
// Receive response.
|
// Receive response.
|
||||||
char response[4096];
|
char response[4096];
|
||||||
|
ssize_t total_bytes_read{0};
|
||||||
|
bool done{false};
|
||||||
|
bool multi_part{false};
|
||||||
|
while (!done) {
|
||||||
int64_t recv_result;
|
int64_t recv_result;
|
||||||
do {
|
do {
|
||||||
recv_result = sock->Recv(response, sizeof(response), 0);
|
recv_result = sock->Recv(response, sizeof(response), 0);
|
||||||
|
@ -93,10 +100,36 @@ std::optional<CNetAddr> QueryDefaultGatewayImpl(sa_family_t family)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
total_bytes_read += recv_result;
|
||||||
|
if (total_bytes_read > NETLINK_MAX_RESPONSE_SIZE) {
|
||||||
|
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "Netlink response exceeded size limit (%zu bytes, family=%d)\n", NETLINK_MAX_RESPONSE_SIZE, family);
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool processed_one{false};
|
||||||
for (nlmsghdr* hdr = (nlmsghdr*)response; NLMSG_OK(hdr, recv_result); hdr = NLMSG_NEXT(hdr, recv_result)) {
|
for (nlmsghdr* hdr = (nlmsghdr*)response; NLMSG_OK(hdr, recv_result); hdr = NLMSG_NEXT(hdr, recv_result)) {
|
||||||
rtmsg* r = (rtmsg*)NLMSG_DATA(hdr);
|
rtmsg* r = (rtmsg*)NLMSG_DATA(hdr);
|
||||||
int remaining_len = RTM_PAYLOAD(hdr);
|
int remaining_len = RTM_PAYLOAD(hdr);
|
||||||
|
|
||||||
|
processed_one = true;
|
||||||
|
if (hdr->nlmsg_flags & NLM_F_MULTI) {
|
||||||
|
multi_part = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->nlmsg_type == NLMSG_DONE) {
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr->nlmsg_type != RTM_NEWROUTE) {
|
||||||
|
continue; // Skip non-route messages
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only consider default routes (destination prefix length of 0).
|
||||||
|
if (r->rtm_dst_len != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Iterate over the attributes.
|
// Iterate over the attributes.
|
||||||
rtattr* rta_gateway = nullptr;
|
rtattr* rta_gateway = nullptr;
|
||||||
int scope_id = 0;
|
int scope_id = 0;
|
||||||
|
@ -122,6 +155,13 @@ std::optional<CNetAddr> QueryDefaultGatewayImpl(sa_family_t family)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we processed at least one message and multi flag not set, or if
|
||||||
|
// we received no valid messages, then we're done.
|
||||||
|
if ((processed_one && !multi_part) || !processed_one) {
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue