Skip to content

Commit 768a23c

Browse files
authored
Add support for writing NSEC records (python-zeroconf#971)
1 parent e8d8401 commit 768a23c

2 files changed

Lines changed: 46 additions & 1 deletion

File tree

tests/test_protocol.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,35 @@ def test_parse_own_packet_question(self):
5454
generated.add_question(r.DNSQuestion("testname.local.", const._TYPE_SRV, const._CLASS_IN))
5555
r.DNSIncoming(generated.packets()[0])
5656

57+
def test_parse_own_packet_nsec(self):
58+
answer = r.DNSNsec(
59+
'eufy HomeBase2-2464._hap._tcp.local.',
60+
const._TYPE_NSEC,
61+
const._CLASS_IN | const._CLASS_UNIQUE,
62+
const._DNS_OTHER_TTL,
63+
'eufy HomeBase2-2464._hap._tcp.local.',
64+
[const._TYPE_TXT, const._TYPE_SRV],
65+
)
66+
67+
generated = r.DNSOutgoing(const._FLAGS_QR_RESPONSE)
68+
generated.add_answer_at_time(answer, 0)
69+
parsed = r.DNSIncoming(generated.packets()[0])
70+
assert answer in parsed.answers
71+
72+
# Types > 255 should be ignored
73+
answer_invalid_types = r.DNSNsec(
74+
'eufy HomeBase2-2464._hap._tcp.local.',
75+
const._TYPE_NSEC,
76+
const._CLASS_IN | const._CLASS_UNIQUE,
77+
const._DNS_OTHER_TTL,
78+
'eufy HomeBase2-2464._hap._tcp.local.',
79+
[const._TYPE_TXT, const._TYPE_SRV, 1000],
80+
)
81+
generated = r.DNSOutgoing(const._FLAGS_QR_RESPONSE)
82+
generated.add_answer_at_time(answer_invalid_types, 0)
83+
parsed = r.DNSIncoming(generated.packets()[0])
84+
assert answer in parsed.answers
85+
5786
def test_parse_own_packet_response(self):
5887
generated = r.DNSOutgoing(const._FLAGS_QR_RESPONSE)
5988
generated.add_answer_at_time(

zeroconf/_dns.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,9 +458,25 @@ def __init__(
458458
) -> None:
459459
super().__init__(name, type_, class_, ttl, created)
460460
self.next_name = next_name
461-
self.rdtypes = rdtypes
461+
self.rdtypes = sorted(rdtypes)
462462
self._hash = hash((self.key, type_, self.class_, next_name, *self.rdtypes))
463463

464+
def write(self, out: 'DNSOutgoing') -> None:
465+
"""Used in constructing an outgoing packet."""
466+
bitmap = bytearray(b'\0' * 32)
467+
for rdtype in self.rdtypes:
468+
if rdtype > 255: # mDNS only supports window 0
469+
continue
470+
offset = rdtype % 256
471+
byte = offset // 8
472+
total_octets = byte + 1
473+
bitmap[byte] |= 0x80 >> (offset % 8)
474+
out_bytes = bytes(bitmap[0:total_octets])
475+
out.write_name(self.next_name)
476+
out.write_short(0)
477+
out.write_short(len(out_bytes))
478+
out.write_string(out_bytes)
479+
464480
def __eq__(self, other: Any) -> bool:
465481
"""Tests equality on cpu and os"""
466482
return (

0 commit comments

Comments
 (0)