Skip to content

Commit

Permalink
DNS: add Extended DNS Error EDNS0 Option
Browse files Browse the repository at this point in the history
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

```
  • Loading branch information
evverx committed Oct 1, 2023
1 parent 112aa9b commit 67f281a
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
53 changes: 52 additions & 1 deletion scapy/layers/dns.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,8 @@ def i2m(self, pkt, s):
# RFC 2671 - Extension Mechanisms for DNS (EDNS0)

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


class EDNS0TLV(Packet):
Expand All @@ -394,6 +395,8 @@ def dispatch_hook(cls, _pkt=None, *args, **kargs):
edns0type = struct.unpack("!H", _pkt[:2])[0]
if edns0type == 8:
return EDNS0ClientSubnet
if edns0type == 15:
return EDNS0ExtendedDNSError
return EDNS0TLV


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


# RFC 8914 - Extended DNS Errors

# https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#extended-dns-error-codes
extended_dns_error_codes = {
0: "Other",
1: "Unsupported DNSKEY Algorithm",
2: "Unsupported DS Digest Type",
3: "Stale Answer",
4: "Forged Answer",
5: "DNSSEC Indeterminate",
6: "DNSSEC Bogus",
7: "Signature Expired",
8: "Signature Not Yet Valid",
9: "DNSKEY Missing",
10: "RRSIGs Missing",
11: "No Zone Key Bit Set",
12: "NSEC Missing",
13: "Cached Error",
14: "Not Ready",
15: "Blocked",
16: "Censored",
17: "Filtered",
18: "Prohibited",
19: "Stale NXDOMAIN Answer",
20: "Not Authoritative",
21: "Not Supported",
22: "No Reachable Authority",
23: "Network Error",
24: "Invalid Data",
25: "Signature Expired before Valid",
26: "Too Early",
27: "Unsupported NSEC3 Iterations Value",
28: "Unable to conform to policy",
29: "Synthesized",
}


# https://www.rfc-editor.org/rfc/rfc8914.html
class EDNS0ExtendedDNSError(Packet):
name = "DNS EDNS0 Extended DNS Error"
fields_desc = [ShortEnumField("optcode", 15, edns0types),
FieldLenField("optlen", None, length_of="extra_text", fmt="!H",
adjust=lambda pkt, x: x + 2),
ShortEnumField("info_code", 0, extended_dns_error_codes),
StrLenField("extra_text", "",
length_from=lambda pkt: pkt.optlen - 2)]


# RFC 4034 - Resource Records for the DNS Security Extensions


Expand Down
23 changes: 23 additions & 0 deletions test/scapy/layers/dns_edns0.uts
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,26 @@ assert raw(d) == raw_d

d = DNSRROPT(raw_d)
assert EDNS0ClientSubnet in d.rdata[0] and d.rdata[0].family == 2 and d.rdata[0].address == "2001:db8::"


+ EDNS0 - Extended DNS Error

= Basic instantiation & dissection

b = b'\x00\x0f\x00\x02\x00\x00'

p = EDNS0ExtendedDNSError()
assert raw(p) == b

p = EDNS0ExtendedDNSError(b)
assert p.optcode == 15 and p.optlen == 2 and p.info_code == 0 and p.extra_text == b''

b = raw(EDNS0ExtendedDNSError(info_code="DNSSEC Bogus", extra_text="proof of non-existence of example.com. NSEC"))

p = EDNS0ExtendedDNSError(b)
assert p.info_code == 6 and p.optlen == 45 and p.extra_text == b'proof of non-existence of example.com. NSEC'

rropt = DNSRROPT(b'\x00\x00)\x04\xd0\x00\x00\x00\x00\x001\x00\x0f\x00-\x00\x06proof of non-existence of example.com. NSEC')
assert len(rropt.rdata) == 1
p = rropt.rdata[0]
assert p.info_code == 6 and p.optlen == 45 and p.extra_text == b'proof of non-existence of example.com. NSEC'

0 comments on commit 67f281a

Please sign in to comment.