Skip to content

Commit bb0164b

Browse files
evverxguedou
authored andcommitted
DNS: add Extended DNS Error EDNS0 Option
https://www.rfc-editor.org/rfc/rfc8914.html The patch was also cross-checked with Wireshark: ``` Option: Extended DNS Error Option Code: Extended DNS Error (15) Option Length: 45 Option Data: 000670726f6f66206f66206e6f6e2d6578697374656e6365206f66206578616d706c652e… Info Code: DNSSEC Bogus (6) Extra Text: proof of non-existence of example.com. NSEC ```
1 parent f872e33 commit bb0164b

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

scapy/layers/dns.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ def i2m(self, pkt, s):
370370
# RFC 2671 - Extension Mechanisms for DNS (EDNS0)
371371

372372
edns0types = {0: "Reserved", 1: "LLQ", 2: "UL", 3: "NSID", 4: "Reserved",
373-
5: "PING", 8: "edns-client-subnet", 10: "COOKIE"}
373+
5: "PING", 8: "edns-client-subnet", 10: "COOKIE",
374+
15: "Extended DNS Error"}
374375

375376

376377
class EDNS0TLV(Packet):
@@ -394,6 +395,8 @@ def dispatch_hook(cls, _pkt=None, *args, **kargs):
394395
edns0type = struct.unpack("!H", _pkt[:2])[0]
395396
if edns0type == 8:
396397
return EDNS0ClientSubnet
398+
if edns0type == 15:
399+
return EDNS0ExtendedDNSError
397400
return EDNS0TLV
398401

399402

@@ -491,6 +494,54 @@ class EDNS0ClientSubnet(Packet):
491494
length_from=lambda p: p.source_plen))]
492495

493496

497+
# RFC 8914 - Extended DNS Errors
498+
499+
# https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#extended-dns-error-codes
500+
extended_dns_error_codes = {
501+
0: "Other",
502+
1: "Unsupported DNSKEY Algorithm",
503+
2: "Unsupported DS Digest Type",
504+
3: "Stale Answer",
505+
4: "Forged Answer",
506+
5: "DNSSEC Indeterminate",
507+
6: "DNSSEC Bogus",
508+
7: "Signature Expired",
509+
8: "Signature Not Yet Valid",
510+
9: "DNSKEY Missing",
511+
10: "RRSIGs Missing",
512+
11: "No Zone Key Bit Set",
513+
12: "NSEC Missing",
514+
13: "Cached Error",
515+
14: "Not Ready",
516+
15: "Blocked",
517+
16: "Censored",
518+
17: "Filtered",
519+
18: "Prohibited",
520+
19: "Stale NXDOMAIN Answer",
521+
20: "Not Authoritative",
522+
21: "Not Supported",
523+
22: "No Reachable Authority",
524+
23: "Network Error",
525+
24: "Invalid Data",
526+
25: "Signature Expired before Valid",
527+
26: "Too Early",
528+
27: "Unsupported NSEC3 Iterations Value",
529+
28: "Unable to conform to policy",
530+
29: "Synthesized",
531+
}
532+
533+
534+
# https://www.rfc-editor.org/rfc/rfc8914.html
535+
class EDNS0ExtendedDNSError(Packet):
536+
name = "DNS EDNS0 Extended DNS Error"
537+
fields_desc = [ShortEnumField("optcode", 15, edns0types),
538+
FieldLenField("optlen", None, length_of="extra_text", fmt="!H",
539+
adjust=lambda pkt, x: x + 2),
540+
ShortEnumField("info_code", 0, extended_dns_error_codes),
541+
StrLenField("extra_text", "",
542+
length_from=lambda pkt: pkt.optlen - 2)]
543+
544+
494545
# RFC 4034 - Resource Records for the DNS Security Extensions
495546

496547

test/scapy/layers/dns_edns0.uts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,26 @@ assert raw(d) == raw_d
9696

9797
d = DNSRROPT(raw_d)
9898
assert EDNS0ClientSubnet in d.rdata[0] and d.rdata[0].family == 2 and d.rdata[0].address == "2001:db8::"
99+
100+
101+
+ EDNS0 - Extended DNS Error
102+
103+
= Basic instantiation & dissection
104+
105+
b = b'\x00\x0f\x00\x02\x00\x00'
106+
107+
p = EDNS0ExtendedDNSError()
108+
assert raw(p) == b
109+
110+
p = EDNS0ExtendedDNSError(b)
111+
assert p.optcode == 15 and p.optlen == 2 and p.info_code == 0 and p.extra_text == b''
112+
113+
b = raw(EDNS0ExtendedDNSError(info_code="DNSSEC Bogus", extra_text="proof of non-existence of example.com. NSEC"))
114+
115+
p = EDNS0ExtendedDNSError(b)
116+
assert p.info_code == 6 and p.optlen == 45 and p.extra_text == b'proof of non-existence of example.com. NSEC'
117+
118+
rropt = DNSRROPT(b'\x00\x00)\x04\xd0\x00\x00\x00\x00\x001\x00\x0f\x00-\x00\x06proof of non-existence of example.com. NSEC')
119+
assert len(rropt.rdata) == 1
120+
p = rropt.rdata[0]
121+
assert p.info_code == 6 and p.optlen == 45 and p.extra_text == b'proof of non-existence of example.com. NSEC'

0 commit comments

Comments
 (0)