[posix] bind the resolver's UDP socket to the infra network interface (#10864)

This commit fixes an issue in DNS recursive resolver that it didn't
bind its socket to the infra network interface. This may cause the DNS
message to be sent on an unexpected network interface, depending on
the routing table of the platform.

This commit also updates the test case `test_upstream_dns.py` to make
the upstream DNS server run on a different node. Previously the
upstream DNS server ran on the same node as the BR which is a
limitation of this test case.
This commit is contained in:
Handa Wang
2024-10-29 07:54:55 -07:00
committed by GitHub
parent 005c5cefc2
commit d88b63d192
5 changed files with 72 additions and 27 deletions
@@ -41,14 +41,14 @@ import shlex
# Topology:
# ----------------(eth)--------------------
# | |
# BR (Leader) HOST
# BR (Leader) DNS SERVER
# |
# ROUTER
#
BR = 1
ROUTER = 2
HOST = 3
DNS_SERVER = 3
TEST_DOMAIN = 'test.domain'
TEST_DOMAIN_IP6_ADDRESSES = {'2001:db8::1'}
@@ -70,17 +70,15 @@ class UpstreamDns(thread_cert.TestCase):
TOPOLOGY = {
BR: {
'name': 'BR',
'allowlist': [ROUTER],
'is_otbr': True,
'version': '1.4',
},
ROUTER: {
'name': 'Router',
'allowlist': [BR],
'version': '1.4',
},
HOST: {
'name': 'Host',
DNS_SERVER: {
'name': 'DNS Server',
'is_host': True
},
}
@@ -88,27 +86,25 @@ class UpstreamDns(thread_cert.TestCase):
def test(self):
br = self.nodes[BR]
router = self.nodes[ROUTER]
host = self.nodes[HOST]
dns_server = self.nodes[DNS_SERVER]
host.start(start_radvd=False)
self.simulator.go(5)
self._start_dns_server(dns_server)
dns_server_addr = dns_server.get_ether_addrs(ipv4=True, ipv6=False)[0]
# 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()
# When feature flag is enabled, NAT64 might be disabled by default. So
# ensure NAT64 is enabled here.
self.simulator.go(config.LEADER_STARTUP_DELAY)
self.assertEqual('leader', br.get_state())
# When feature flag is enabled, NAT64 might be disabled by default. So
# ensure NAT64 is enabled here.
br.nat64_set_enabled(True)
br.srp_server_set_enabled(True)
br.bash('service bind9 stop')
br.bash(shlex.join(['echo', TEST_DOMAIN_BIND_CONF]) + ' >> /etc/bind/named.conf.local')
br.bash(shlex.join(['echo', TEST_DOMAIN_BIND_ZONE]) + ' >> /etc/bind/db.test.domain')
br.bash('service bind9 start')
router.start()
self.simulator.go(config.ROUTER_STARTUP_DELAY)
self.assertEqual('router', router.get_state())
@@ -130,6 +126,15 @@ class UpstreamDns(thread_cert.TestCase):
for record in resolved_names:
self.assertIn(ipaddress.IPv6Address(record[0]).compressed, 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('service bind9 start')
if __name__ == '__main__':
unittest.main()
+16 -8
View File
@@ -3818,19 +3818,27 @@ class LinuxHost():
self.bash(f'ip link set {self.ETH_DEV} down')
def get_ether_addrs(self):
output = self.bash(f'ip -6 addr list dev {self.ETH_DEV}')
def get_ether_addrs(self, ipv4=False, ipv6=True):
output = self.bash(f'ip addr list dev {self.ETH_DEV}')
addrs = []
for line in output:
# line example: "inet6 fe80::42:c0ff:fea8:903/64 scope link"
# line examples:
# "inet6 fe80::42:c0ff:fea8:903/64 scope link"
# "inet 192.168.9.1/24 brd 192.168.9.255 scope global eth0"
line = line.strip().split()
if line and line[0] == 'inet6':
addr = line[1]
if '/' in addr:
addr = addr.split('/')[0]
addrs.append(addr)
if not line or not line[0].startswith('inet'):
continue
if line[0] == 'inet' and not ipv4:
continue
if line[0] == 'inet6' and not ipv6:
continue
addr = line[1]
if '/' in addr:
addr = addr.split('/')[0]
addrs.append(addr)
logging.debug('%s: get_ether_addrs: %r', self, addrs)
return addrs