mirror of
https://github.com/espressif/openthread.git
synced 2026-09-05 16:50:05 +00:00
[posix] update Posix::Resolver to support RDNSS-discovered recursive DNS servers (#11342)
Key Changes: * Server Prioritization: RDNSS-discovered servers are prioritized based on their advertised lifetime. Servers with longer lifetimes are preferred. * Recursive DNS Server List: The resolver maintains a list of recursive DNS servers, which now includes servers learned via RDNSS. * DNS Query Integration: The resolver uses the RDNSS-learned servers when forwarding DNS queries upstream. * Border Routing Integration: The RDNSS callback is registered to the border routing module. Minor Changes: * The unused function `Transaction *GetTransaction(int aFd)` is removed.
This commit is contained in:
@@ -421,6 +421,15 @@ void platformSpinelManagerUpdateFdSet(otSysMainloopContext *aContext);
|
||||
*/
|
||||
void platformResolverInit(void);
|
||||
|
||||
/**
|
||||
* Sets up platform resolver.
|
||||
*
|
||||
* @note This function is called after OpenThread instance is created.
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
*/
|
||||
void platformResolverSetUp(void);
|
||||
|
||||
/**
|
||||
* Updates the file descriptor sets with file descriptors used by the resolver.
|
||||
*
|
||||
|
||||
+148
-44
@@ -27,9 +27,11 @@
|
||||
*/
|
||||
|
||||
#include "resolver.hpp"
|
||||
#include "ip6_utils.hpp"
|
||||
|
||||
#include "platform-posix.h"
|
||||
|
||||
#include <openthread/border_routing.h>
|
||||
#include <openthread/logging.h>
|
||||
#include <openthread/message.h>
|
||||
#include <openthread/nat64.h>
|
||||
@@ -39,6 +41,7 @@
|
||||
#include <openthread/platform/time.h>
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/debug.hpp"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
@@ -48,11 +51,14 @@
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
|
||||
|
||||
using namespace ot::Posix::Ip6Utils;
|
||||
|
||||
namespace {
|
||||
constexpr char kResolvConfFullPath[] = "/etc/resolv.conf";
|
||||
constexpr char kNameserverItem[] = "nameserver";
|
||||
@@ -71,6 +77,15 @@ void Resolver::Init(void)
|
||||
LoadDnsServerListFromConf();
|
||||
}
|
||||
|
||||
void Resolver::Setup(void)
|
||||
{
|
||||
OT_ASSERT(gInstance != nullptr);
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
otBorderRoutingSetRdnssAddrCallback(gInstance, &Resolver::BorderRoutingRdnssCallback, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Resolver::TryRefreshDnsServerList(void)
|
||||
{
|
||||
uint64_t now = otPlatTimeGet();
|
||||
@@ -129,16 +144,120 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
void Resolver::BorderRoutingRdnssCallback(void *aResolver)
|
||||
{
|
||||
static_cast<Resolver *>(aResolver)->BorderRoutingRdnssCallback();
|
||||
}
|
||||
|
||||
void Resolver::BorderRoutingRdnssCallback(void)
|
||||
{
|
||||
otBorderRoutingPrefixTableIterator iterator;
|
||||
otBorderRoutingRdnssAddrEntry entry;
|
||||
otBorderRoutingRdnssAddrEntry rdnssEntries[kMaxRecursiveServerCount + 1];
|
||||
otIp6Address rdnssServers[kMaxRecursiveServerCount];
|
||||
uint32_t numEntries = 0;
|
||||
|
||||
otBorderRoutingPrefixTableInitIterator(gInstance, &iterator);
|
||||
|
||||
while (otBorderRoutingGetNextRdnssAddrEntry(gInstance, &iterator, &entry) == OT_ERROR_NONE)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
// Check if the entry address is already in the list.
|
||||
for (; i < numEntries; ++i)
|
||||
{
|
||||
if (otIp6IsAddressEqual(&entry.mAddress, &rdnssEntries[i].mAddress))
|
||||
{
|
||||
rdnssEntries[i].mLifetime = OT_MAX(rdnssEntries[i].mLifetime, entry.mLifetime);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the address is not a duplicate, add the entry to the entry list.
|
||||
if (i == numEntries)
|
||||
{
|
||||
rdnssEntries[numEntries++] = entry;
|
||||
|
||||
std::sort(rdnssEntries, rdnssEntries + numEntries,
|
||||
[](const otBorderRoutingRdnssAddrEntry &a, const otBorderRoutingRdnssAddrEntry &b) {
|
||||
bool result = false;
|
||||
|
||||
if (a.mLifetime != b.mLifetime)
|
||||
{
|
||||
result = a.mLifetime > b.mLifetime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If lifetimes are equal, prefer the one with the larger numeric values
|
||||
for (uint8_t j = 0; j < sizeof(otIp6Address); j++)
|
||||
{
|
||||
if (a.mAddress.mFields.m8[j] != b.mAddress.mFields.m8[j])
|
||||
{
|
||||
result = a.mAddress.mFields.m8[j] > b.mAddress.mFields.m8[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
numEntries = OT_MIN(numEntries, kMaxRecursiveServerCount);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < numEntries; i++)
|
||||
{
|
||||
rdnssServers[i] = rdnssEntries[i].mAddress;
|
||||
}
|
||||
|
||||
SetRecursiveDnsServerList(rdnssServers, numEntries);
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
otError Resolver::SendQueryToServer(Transaction *aTxn,
|
||||
const otIp6Address &aServerAddress,
|
||||
const char *aPacket,
|
||||
uint16_t aLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otIp4Address ip4Addr;
|
||||
sockaddr_in serverAddr4;
|
||||
sockaddr_in6 serverAddr6;
|
||||
|
||||
if (otIp4FromIp4MappedIp6Address(&aServerAddress, &ip4Addr) == OT_ERROR_NONE)
|
||||
{
|
||||
memcpy(&serverAddr4.sin_addr.s_addr, &ip4Addr, sizeof(otIp4Address));
|
||||
serverAddr4.sin_family = AF_INET;
|
||||
serverAddr4.sin_port = htons(53);
|
||||
|
||||
VerifyOrExit(sendto(aTxn->mUdpFd4, aPacket, aLength, MSG_DONTWAIT, reinterpret_cast<sockaddr *>(&serverAddr4),
|
||||
sizeof(serverAddr4)) > 0,
|
||||
error = OT_ERROR_NO_ROUTE);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&serverAddr6.sin6_addr, &aServerAddress, sizeof(otIp6Address));
|
||||
serverAddr6.sin6_family = AF_INET6;
|
||||
serverAddr6.sin6_port = htons(53);
|
||||
|
||||
VerifyOrExit(sendto(aTxn->mUdpFd6, aPacket, aLength, MSG_DONTWAIT, reinterpret_cast<sockaddr *>(&serverAddr6),
|
||||
sizeof(serverAddr6)) > 0,
|
||||
error = OT_ERROR_NO_ROUTE);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Resolver::Query(otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery)
|
||||
{
|
||||
char packet[kMaxDnsMessageSize];
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint16_t length = otMessageGetLength(aQuery);
|
||||
otIp4Address ip4Addr;
|
||||
sockaddr_in serverAddr4;
|
||||
sockaddr_in6 serverAddr6;
|
||||
|
||||
Transaction *txn = nullptr;
|
||||
Transaction *txn = nullptr;
|
||||
|
||||
VerifyOrExit(length <= kMaxDnsMessageSize, error = OT_ERROR_NO_BUFS);
|
||||
VerifyOrExit(otMessageRead(aQuery, 0, &packet, sizeof(packet)) == length, error = OT_ERROR_NO_BUFS);
|
||||
@@ -147,32 +266,24 @@ void Resolver::Query(otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery)
|
||||
VerifyOrExit(txn != nullptr, error = OT_ERROR_NO_BUFS);
|
||||
TryRefreshDnsServerList();
|
||||
|
||||
for (uint32_t i = 0; i < mRecursiveDnsServerCount; i++)
|
||||
{
|
||||
SuccessOrExit(error = SendQueryToServer(txn, mRecursiveDnsServerList[i], packet, length));
|
||||
|
||||
LogInfo("Forwarded DNS query %p to %s", static_cast<void *>(aTxn),
|
||||
Ip6AddressString(&mRecursiveDnsServerList[i]).AsCString());
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mUpstreamDnsServerCount; i++)
|
||||
{
|
||||
if (otIp4FromIp4MappedIp6Address(&mUpstreamDnsServerList[i], &ip4Addr) == OT_ERROR_NONE)
|
||||
{
|
||||
memcpy(&serverAddr4.sin_addr.s_addr, &ip4Addr, sizeof(otIp4Address));
|
||||
SuccessOrExit(error = SendQueryToServer(txn, mUpstreamDnsServerList[i], packet, length));
|
||||
|
||||
serverAddr4.sin_family = AF_INET;
|
||||
serverAddr4.sin_port = htons(53);
|
||||
|
||||
VerifyOrExit(sendto(txn->mUdpFd4, packet, length, MSG_DONTWAIT, reinterpret_cast<sockaddr *>(&serverAddr4),
|
||||
sizeof(serverAddr4)) > 0,
|
||||
error = OT_ERROR_NO_ROUTE);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&serverAddr6.sin6_addr, &mUpstreamDnsServerList[i], sizeof(otIp6Address));
|
||||
|
||||
serverAddr6.sin6_family = AF_INET6;
|
||||
serverAddr6.sin6_port = htons(53);
|
||||
|
||||
VerifyOrExit(sendto(txn->mUdpFd6, packet, length, MSG_DONTWAIT, reinterpret_cast<sockaddr *>(&serverAddr6),
|
||||
sizeof(serverAddr6)) > 0,
|
||||
error = OT_ERROR_NO_ROUTE);
|
||||
}
|
||||
LogInfo("Forwarded DNS query %p to %s", static_cast<void *>(aTxn),
|
||||
Ip6AddressString(&mUpstreamDnsServerList[i]).AsCString());
|
||||
}
|
||||
LogInfo("Forwarded DNS query %p to %d server(s).", static_cast<void *>(aTxn), mUpstreamDnsServerCount);
|
||||
|
||||
LogInfo("Forwarded DNS query %p to %d server(s).", static_cast<void *>(aTxn),
|
||||
mRecursiveDnsServerCount + mUpstreamDnsServerCount);
|
||||
|
||||
exit:
|
||||
if (error != OT_ERROR_NONE)
|
||||
@@ -184,7 +295,6 @@ exit:
|
||||
CloseTransaction(txn);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Resolver::Cancel(otPlatDnsUpstreamQuery *aTxn)
|
||||
@@ -265,22 +375,6 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
Resolver::Transaction *Resolver::GetTransaction(int aFd)
|
||||
{
|
||||
Transaction *ret = nullptr;
|
||||
|
||||
for (Transaction &txn : mUpstreamTransaction)
|
||||
{
|
||||
if (txn.mThreadTxn != nullptr && (txn.mUdpFd4 == aFd || txn.mUdpFd6 == aFd))
|
||||
{
|
||||
ret = &txn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Resolver::Transaction *Resolver::GetTransaction(otPlatDnsUpstreamQuery *aThreadTxn)
|
||||
{
|
||||
Transaction *ret = nullptr;
|
||||
@@ -364,6 +458,14 @@ void Resolver::SetUpstreamDnsServers(const otIp6Address *aUpstreamDnsServers, ui
|
||||
LogInfo("Set upstream DNS server list, count: %d", mUpstreamDnsServerCount);
|
||||
}
|
||||
|
||||
void Resolver::SetRecursiveDnsServerList(const otIp6Address *aRecursiveDnsServers, uint32_t aNumServers)
|
||||
{
|
||||
mRecursiveDnsServerCount = OT_MIN(aNumServers, static_cast<uint32_t>(kMaxRecursiveServerCount));
|
||||
memcpy(mRecursiveDnsServerList, aRecursiveDnsServers, mRecursiveDnsServerCount * sizeof(otIp6Address));
|
||||
|
||||
LogInfo("Set recursive DNS server list, count: %d", mRecursiveDnsServerCount);
|
||||
}
|
||||
|
||||
int Resolver::CreateUdpSocket(sa_family_t aFamily)
|
||||
{
|
||||
int fd = -1;
|
||||
@@ -392,6 +494,8 @@ void platformResolverProcess(const otSysMainloopContext *aContext) { gResolver.P
|
||||
|
||||
void platformResolverUpdateFdSet(otSysMainloopContext *aContext) { gResolver.UpdateFdSet(*aContext); }
|
||||
|
||||
void platformResolverSetUp(void) { gResolver.Setup(); }
|
||||
|
||||
void platformResolverInit(void) { gResolver.Init(); }
|
||||
|
||||
void otPlatDnsStartUpstreamQuery(otInstance *aInstance, otPlatDnsUpstreamQuery *aTxn, const otMessage *aQuery)
|
||||
|
||||
@@ -50,12 +50,20 @@ public:
|
||||
constexpr static ssize_t kMaxDnsMessageSize = 512;
|
||||
constexpr static ssize_t kMaxUpstreamTransactionCount = 16;
|
||||
constexpr static ssize_t kMaxUpstreamServerCount = 3;
|
||||
constexpr static ssize_t kMaxRecursiveServerCount = 3;
|
||||
|
||||
/**
|
||||
* Initialize the upstream DNS resolver.
|
||||
*/
|
||||
void Init(void);
|
||||
|
||||
/**
|
||||
* Sets up the upstream DNS resolver.
|
||||
*
|
||||
* @note This method is called after OpenThread instance is created.
|
||||
*/
|
||||
void Setup(void);
|
||||
|
||||
/**
|
||||
* Sends the query to the upstream.
|
||||
*
|
||||
@@ -101,6 +109,15 @@ public:
|
||||
*/
|
||||
void SetUpstreamDnsServers(const otIp6Address *aUpstreamDnsServers, uint32_t aNumServers);
|
||||
|
||||
/**
|
||||
* Sets the list of recursive DNS servers.
|
||||
*
|
||||
* @param[in] aRecursiveDnsServers A pointer to the list of IPv6 recursive DNS server addresses.
|
||||
* @param[in] aNumServers The number of recursive DNS servers.
|
||||
*
|
||||
*/
|
||||
void SetRecursiveDnsServerList(const otIp6Address *aRecursiveDnsServers, uint32_t aNumServers);
|
||||
|
||||
private:
|
||||
static constexpr uint64_t kDnsServerListNullCacheTimeoutMs = 1 * 60 * 1000; // 1 minute
|
||||
static constexpr uint64_t kDnsServerListCacheTimeoutMs = 10 * 60 * 1000; // 10 minutes
|
||||
@@ -114,20 +131,31 @@ private:
|
||||
|
||||
static int CreateUdpSocket(sa_family_t aFamily);
|
||||
|
||||
Transaction *GetTransaction(int aFd);
|
||||
Transaction *GetTransaction(otPlatDnsUpstreamQuery *aThreadTxn);
|
||||
Transaction *AllocateTransaction(otPlatDnsUpstreamQuery *aThreadTxn);
|
||||
|
||||
void ForwardResponse(otPlatDnsUpstreamQuery *aThreadTxn, int aFd);
|
||||
void CloseTransaction(Transaction *aTxn);
|
||||
void TryRefreshDnsServerList(void);
|
||||
void LoadDnsServerListFromConf(void);
|
||||
otError SendQueryToServer(Transaction *aTxn,
|
||||
const otIp6Address &aServerAddress,
|
||||
const char *aPacket,
|
||||
uint16_t aLength);
|
||||
void ForwardResponse(otPlatDnsUpstreamQuery *aThreadTxn, int aFd);
|
||||
void CloseTransaction(Transaction *aTxn);
|
||||
void TryRefreshDnsServerList(void);
|
||||
void LoadDnsServerListFromConf(void);
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
static void BorderRoutingRdnssCallback(void *aResolver);
|
||||
void BorderRoutingRdnssCallback(void);
|
||||
#endif
|
||||
|
||||
bool mIsResolvConfEnabled = OPENTHREAD_POSIX_CONFIG_RESOLV_CONF_ENABLED_INIT;
|
||||
uint32_t mUpstreamDnsServerCount = 0;
|
||||
otIp6Address mUpstreamDnsServerList[kMaxUpstreamServerCount];
|
||||
uint64_t mUpstreamDnsServerListFreshness = 0;
|
||||
|
||||
uint32_t mRecursiveDnsServerCount = 0;
|
||||
otIp6Address mRecursiveDnsServerList[kMaxRecursiveServerCount];
|
||||
|
||||
Transaction mUpstreamTransaction[kMaxUpstreamTransactionCount];
|
||||
};
|
||||
|
||||
|
||||
@@ -237,6 +237,10 @@ void platformSetUp(otPlatformConfig *aPlatformConfig)
|
||||
platformNetifSetUp();
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE
|
||||
platformResolverSetUp();
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
||||
ot::Posix::Udp::Get().SetUp();
|
||||
#endif
|
||||
|
||||
@@ -39,29 +39,23 @@ import shlex
|
||||
# a record resolved by BIND9 server.
|
||||
#
|
||||
# Topology:
|
||||
# ----------------(eth)--------------------
|
||||
# | |
|
||||
# BR (Leader) DNS SERVER
|
||||
# ----------------(eth)----------------------------------
|
||||
# | | |
|
||||
# BR (Leader) DNS SERVER 1 DNS SERVER 2
|
||||
# |
|
||||
# ROUTER
|
||||
#
|
||||
|
||||
BR = 1
|
||||
ROUTER = 2
|
||||
DNS_SERVER = 3
|
||||
DNS_SERVER_1 = 3
|
||||
DNS_SERVER_2 = 4
|
||||
|
||||
TEST_DOMAIN = 'test.domain'
|
||||
TEST_DOMAIN_IP6_ADDRESSES = {'2001:db8::1'}
|
||||
TEST_DOMAIN_1 = 'test.domain.resolv'
|
||||
TEST_DOMAIN_IP6_ADDRESSES_1 = {'2001:db8::1'}
|
||||
|
||||
TEST_DOMAIN_BIND_CONF = f'''
|
||||
zone "{TEST_DOMAIN}" {{ type master; file "/etc/bind/db.test.domain"; }};
|
||||
'''
|
||||
|
||||
TEST_DOMAIN_BIND_ZONE = f'''
|
||||
$TTL 24h
|
||||
@ IN SOA {TEST_DOMAIN} test.{TEST_DOMAIN}. ( 20230330 86400 300 604800 3600 )
|
||||
@ IN NS {TEST_DOMAIN}.
|
||||
''' + '\n'.join(f'@ IN AAAA {addr}' for addr in TEST_DOMAIN_IP6_ADDRESSES)
|
||||
TEST_DOMAIN_2 = 'test.domain.rdnss'
|
||||
TEST_DOMAIN_IP6_ADDRESSES_2 = {'2001:db8::2'}
|
||||
|
||||
|
||||
class UpstreamDns(thread_cert.TestCase):
|
||||
@@ -77,8 +71,12 @@ class UpstreamDns(thread_cert.TestCase):
|
||||
'name': 'Router',
|
||||
'version': '1.4',
|
||||
},
|
||||
DNS_SERVER: {
|
||||
'name': 'DNS Server',
|
||||
DNS_SERVER_1: {
|
||||
'name': 'DNS Server 1',
|
||||
'is_host': True
|
||||
},
|
||||
DNS_SERVER_2: {
|
||||
'name': 'DNS Server 2',
|
||||
'is_host': True
|
||||
},
|
||||
}
|
||||
@@ -86,19 +84,15 @@ class UpstreamDns(thread_cert.TestCase):
|
||||
def test(self):
|
||||
br = self.nodes[BR]
|
||||
router = self.nodes[ROUTER]
|
||||
dns_server = self.nodes[DNS_SERVER]
|
||||
dns_server_1 = self.nodes[DNS_SERVER_1]
|
||||
dns_server_2 = self.nodes[DNS_SERVER_2]
|
||||
|
||||
self._start_dns_server(dns_server)
|
||||
dns_server_addr = dns_server.get_ether_addrs(ipv4=True, ipv6=False)[0]
|
||||
self._start_dns_server(dns_server_1, TEST_DOMAIN_1, TEST_DOMAIN_IP6_ADDRESSES_1)
|
||||
self._start_dns_server(dns_server_2, TEST_DOMAIN_2, TEST_DOMAIN_IP6_ADDRESSES_2)
|
||||
|
||||
# Disable the bind9 service on the BR otherwise bind9 may respond to Thread devices' DNS queries
|
||||
br.bash('service bind9 stop')
|
||||
|
||||
# Update BR's /etc/resolv.conf and force BR to reload it
|
||||
br.bash(shlex.join(['echo', 'nameserver ' + dns_server_addr]) + ' > /etc/resolv.conf')
|
||||
br.stop_otbr_service()
|
||||
br.start_otbr_service()
|
||||
|
||||
br.start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual('leader', br.get_state())
|
||||
@@ -115,26 +109,45 @@ class UpstreamDns(thread_cert.TestCase):
|
||||
self.simulator.go(10)
|
||||
router.srp_client_enable_auto_start_mode()
|
||||
|
||||
# verify the server can forward the DNS query to upstream server.
|
||||
self._verify_upstream_dns(br, router)
|
||||
|
||||
def _verify_upstream_dns(self, br, ed):
|
||||
upstream_dns_enabled = br.dns_upstream_query_state
|
||||
if not upstream_dns_enabled:
|
||||
br.dns_upstream_query_state = True
|
||||
br.dns_upstream_query_state = True
|
||||
self.assertTrue(br.dns_upstream_query_state)
|
||||
|
||||
resolved_names = ed.dns_resolve(TEST_DOMAIN)
|
||||
self.assertEqual(len(resolved_names), len(TEST_DOMAIN_IP6_ADDRESSES))
|
||||
for record in resolved_names:
|
||||
self.assertIn(ipaddress.IPv6Address(record[0]).compressed, TEST_DOMAIN_IP6_ADDRESSES)
|
||||
# Update BR's /etc/resolv.conf with the address of DNS server 1 and force BR to reload it
|
||||
dns_server_addr_1 = dns_server_1.get_ether_addrs(ipv4=True, ipv6=False)[0]
|
||||
br.bash(shlex.join(['echo', 'nameserver ' + dns_server_addr_1]) + ' > /etc/resolv.conf')
|
||||
br.stop_otbr_service()
|
||||
br.start_otbr_service()
|
||||
|
||||
# Publish RDNSS with the address of DNS server 2 through RA
|
||||
dns_server_addr_2 = dns_server_2.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]
|
||||
br.start_rdnss_radvd_service(dns_server_addr_2)
|
||||
|
||||
self.simulator.go(10)
|
||||
# verify the server can forward the DNS query to the two upstream servers.
|
||||
resolved_addresses_1 = set(
|
||||
ipaddress.IPv6Address(record[0]).compressed for record in router.dns_resolve(TEST_DOMAIN_1))
|
||||
self.assertEqual(resolved_addresses_1, TEST_DOMAIN_IP6_ADDRESSES_1)
|
||||
|
||||
resolved_addresses_2 = set(
|
||||
ipaddress.IPv6Address(record[0]).compressed for record in router.dns_resolve(TEST_DOMAIN_2))
|
||||
self.assertEqual(resolved_addresses_2, TEST_DOMAIN_IP6_ADDRESSES_2)
|
||||
|
||||
def _start_dns_server(self, dns_server, test_domain, test_domain_ip6_addresses):
|
||||
test_domain_bind_conf = f'''
|
||||
zone "{test_domain}" {{ type master; file "/etc/bind/db.test.domain"; }};
|
||||
'''
|
||||
|
||||
test_domain_bind_zone = f'''
|
||||
$TTL 24h
|
||||
@ IN SOA {test_domain} test.{test_domain}. ( 20230330 86400 300 604800 3600 )
|
||||
@ IN NS {test_domain}.
|
||||
''' + '\n'.join(f'@ IN AAAA {addr}' for addr in test_domain_ip6_addresses)
|
||||
|
||||
def _start_dns_server(self, dns_server):
|
||||
dns_server.start(start_radvd=False)
|
||||
dns_server.bash('service bind9 stop')
|
||||
|
||||
dns_server.bash(shlex.join(['echo', TEST_DOMAIN_BIND_CONF]) + ' >> /etc/bind/named.conf.local')
|
||||
dns_server.bash(shlex.join(['echo', TEST_DOMAIN_BIND_ZONE]) + ' >> /etc/bind/db.test.domain')
|
||||
dns_server.bash(shlex.join(['echo', test_domain_bind_conf]) + ' >> /etc/bind/named.conf.local')
|
||||
dns_server.bash(shlex.join(['echo', test_domain_bind_zone]) + ' >> /etc/bind/db.test.domain')
|
||||
|
||||
dns_server.bash('service bind9 start')
|
||||
|
||||
|
||||
@@ -4145,6 +4145,28 @@ EOF
|
||||
""" % (prefix,))
|
||||
self._start_radvd_and_verify()
|
||||
|
||||
def start_rdnss_radvd_service(self, dns_server_address):
|
||||
self.bash(f"""cat >/etc/radvd.conf <<EOF
|
||||
interface eth0
|
||||
{{
|
||||
AdvSendAdvert on;
|
||||
|
||||
AdvReachableTime 20;
|
||||
AdvRetransTimer 20;
|
||||
AdvDefaultLifetime 180;
|
||||
MinRtrAdvInterval 120;
|
||||
MaxRtrAdvInterval 180;
|
||||
AdvDefaultPreference low;
|
||||
|
||||
RDNSS {dns_server_address}
|
||||
{{
|
||||
AdvRDNSSLifetime 1800;
|
||||
}};
|
||||
}};
|
||||
EOF
|
||||
""")
|
||||
self._start_radvd_and_verify()
|
||||
|
||||
def stop_radvd_service(self):
|
||||
self.bash('service radvd stop')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user