Skip to content

Commit 6337254

Browse files
authored
Merge pull request #59 from admitrievsky/fix-root-servers
Fix root servers query handling
2 parents bd15741 + 204cf81 commit 6337254

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

aiodnsresolver.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ class DnsRecordDoesNotExist(DnsError):
9999
pass
100100

101101

102+
class DnsNoMatchingAnswers(DnsRecordDoesNotExist):
103+
pass
104+
105+
102106
class DnsPointerLoop(DnsError):
103107
pass
104108

@@ -153,7 +157,7 @@ def pack_name(name):
153157
return b''.join(
154158
bytes((len(part),)) + part
155159
for part in name.split(b'.')
156-
) + b'\0'
160+
) + b'\0' if name else b'\0'
157161

158162
def pack_resource(record):
159163
rdata = \
@@ -589,11 +593,12 @@ async def req():
589593
last_exception = DnsResponseCode(res.rcode)
590594
set_timeout_cause(last_exception)
591595
logger.debug('Error from %s', addr_port)
592-
elif name_error or (not cname_answers and not qtype_answers):
593-
# a name error can be returned by some non-authoritative
594-
# servers on not-existing, contradicting RFC 1035
596+
elif name_error:
595597
logger.debug('Record not found from %s', addr_port)
596598
raise DnsRecordDoesNotExist()
599+
elif not cname_answers and not qtype_answers:
600+
logger.debug('No answers from %s', addr_port)
601+
raise DnsNoMatchingAnswers()
597602
else:
598603
return cname_answers, qtype_answers
599604

test.py

+16-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
TYPES,
2222
DnsCnameChainTooLong,
2323
DnsError,
24+
DnsNoMatchingAnswers,
2425
DnsRecordDoesNotExist,
2526
DnsSocketError,
2627
DnsTimeout,
@@ -1772,6 +1773,18 @@ async def test_localhost_aaaa(self):
17721773
self.assertEqual(str(res[0]), '::1')
17731774
self.assertEqual(res[0].expires_at, loop.time())
17741775

1776+
@async_test
1777+
async def test_root_servers_queries(self):
1778+
# Upstream DNS server should return NOERROR status with an empty `A` records set.
1779+
# The default Github's does not do this, so we need to switch to Google's server.
1780+
self.addCleanup(patch_open(upstream_ip='8.8.8.8'))
1781+
1782+
resolve, _ = Resolver()
1783+
with self.assertRaises(DnsNoMatchingAnswers):
1784+
await resolve('', TYPES.A)
1785+
with self.assertRaises(DnsNoMatchingAnswers):
1786+
await resolve('root-servers.net', TYPES.A)
1787+
17751788

17761789
class TestMemoizedMutex(unittest.TestCase):
17771790
@async_test
@@ -1808,11 +1821,11 @@ async def func():
18081821
self.assertEqual(await task3, 42)
18091822

18101823

1811-
def patch_open():
1824+
def patch_open(upstream_ip='127.0.0.1'):
18121825
def mock_open(file_name, _):
18131826
lines = \
1814-
['127.0.0.1 localhost'] if file_name == '/etc/hosts' else \
1815-
['nameserver 127.0.0.1']
1827+
[f'{upstream_ip} localhost'] if file_name == '/etc/hosts' else \
1828+
[f'nameserver {upstream_ip}']
18161829

18171830
context_manager = MagicMock()
18181831
context_manager.__enter__.return_value = lines

0 commit comments

Comments
 (0)