Improved IPv6 support.

This commit is contained in:
XMRig 2025-06-20 07:39:52 +07:00
parent e28d663d80
commit ec286c7fef
No known key found for this signature in database
GPG key ID: 446A53638BE94409
17 changed files with 246 additions and 272 deletions

View file

@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -18,90 +18,96 @@
#include <uv.h>
#include "base/net/dns/DnsRecords.h"
#include "base/net/dns/Dns.h"
const xmrig::DnsRecord &xmrig::DnsRecords::get(DnsRecord::Type prefered) const
namespace {
static size_t dns_records_count(const addrinfo *res, int &ai_family)
{
size_t ipv4 = 0;
size_t ipv6 = 0;
while (res != nullptr) {
if (res->ai_family == AF_INET) {
++ipv4;
}
if (res->ai_family == AF_INET6) {
++ipv6;
}
res = res->ai_next;
}
if (ai_family == AF_INET6 && !ipv6) {
ai_family = AF_INET;
}
switch (ai_family) {
case AF_UNSPEC:
return ipv4 + ipv6;
case AF_INET:
return ipv4;
case AF_INET6:
return ipv6;
default:
break;
}
return 0;
}
} // namespace
xmrig::DnsRecords::DnsRecords(const addrinfo *res, int ai_family)
{
size_t size = dns_records_count(res, ai_family);
if (!size) {
return;
}
m_records.reserve(size);
if (ai_family == AF_UNSPEC) {
while (res != nullptr) {
if (res->ai_family == AF_INET || res->ai_family == AF_INET6) {
m_records.emplace_back(res);
}
res = res->ai_next;
};
} else {
while (res != nullptr) {
if (res->ai_family == ai_family) {
m_records.emplace_back(res);
}
res = res->ai_next;
};
}
size = m_records.size();
if (size > 1) {
m_index = static_cast<size_t>(rand()) % size; // NOLINT(concurrency-mt-unsafe, cert-msc30-c, cert-msc50-cpp)
}
}
const xmrig::DnsRecord &xmrig::DnsRecords::get() const
{
static const DnsRecord defaultRecord;
if (isEmpty()) {
return defaultRecord;
}
const size_t ipv4 = m_ipv4.size();
const size_t ipv6 = m_ipv6.size();
if (ipv6 && (prefered == DnsRecord::AAAA || Dns::config().isIPv6() || !ipv4)) {
return m_ipv6[ipv6 == 1 ? 0 : static_cast<size_t>(rand()) % ipv6]; // NOLINT(concurrency-mt-unsafe, cert-msc30-c, cert-msc50-cpp)
}
if (ipv4) {
return m_ipv4[ipv4 == 1 ? 0 : static_cast<size_t>(rand()) % ipv4]; // NOLINT(concurrency-mt-unsafe, cert-msc30-c, cert-msc50-cpp)
const size_t size = m_records.size();
if (size > 0) {
return m_records[m_index++ % size];
}
return defaultRecord;
}
size_t xmrig::DnsRecords::count(DnsRecord::Type type) const
{
if (type == DnsRecord::A) {
return m_ipv4.size();
}
if (type == DnsRecord::AAAA) {
return m_ipv6.size();
}
return m_ipv4.size() + m_ipv6.size();
}
void xmrig::DnsRecords::clear()
{
m_ipv4.clear();
m_ipv6.clear();
}
void xmrig::DnsRecords::parse(addrinfo *res)
{
clear();
addrinfo *ptr = res;
size_t ipv4 = 0;
size_t ipv6 = 0;
while (ptr != nullptr) {
if (ptr->ai_family == AF_INET) {
++ipv4;
}
else if (ptr->ai_family == AF_INET6) {
++ipv6;
}
ptr = ptr->ai_next;
}
if (ipv4 == 0 && ipv6 == 0) {
return;
}
m_ipv4.reserve(ipv4);
m_ipv6.reserve(ipv6);
ptr = res;
while (ptr != nullptr) {
if (ptr->ai_family == AF_INET) {
m_ipv4.emplace_back(ptr);
}
else if (ptr->ai_family == AF_INET6) {
m_ipv6.emplace_back(ptr);
}
ptr = ptr->ai_next;
}
}