From: Bob Halley Date: Wed, 7 Feb 2024 00:08:01 +0000 (-0800) Subject: Add EDNS NSID option. X-Git-Tag: v2.6.0rc1~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1d35451161ec43f37038167f35efad4ebed6b862;p=thirdparty%2Fdnspython.git Add EDNS NSID option. --- diff --git a/dns/edns.py b/dns/edns.py index c80e0482..b29afaa3 100644 --- a/dns/edns.py +++ b/dns/edns.py @@ -17,6 +17,7 @@ """EDNS Options""" +import binascii import math import socket import struct @@ -393,9 +394,37 @@ class EDEOption(Option): # lgtm[py/missing-equals] return cls(code, btext) +class NSIDOption(Option): + def __init__(self, nsid: bytes): + super().__init__(OptionType.NSID) + self.nsid = nsid + + def to_wire(self, file: Any = None) -> Optional[bytes]: + if file: + file.write(self.nsid) + return None + else: + return self.nsid + + def to_text(self) -> str: + if all(c >= 0x20 and c <= 0x7E for c in self.nsid): + # All ASCII printable, so it's probably a string. + value = self.nsid.decode() + else: + value = binascii.hexlify(self.nsid).decode() + return f"NSID {value}" + + @classmethod + def from_wire_parser( + cls, otype: Union[OptionType, str], parser: dns.wire.Parser + ) -> Option: + return cls(parser.get_remaining()) + + _type_to_class: Dict[OptionType, Any] = { OptionType.ECS: ECSOption, OptionType.EDE: EDEOption, + OptionType.NSID: NSIDOption, } diff --git a/doc/whatsnew.rst b/doc/whatsnew.rst index a4619e51..ada72d59 100644 --- a/doc/whatsnew.rst +++ b/doc/whatsnew.rst @@ -6,7 +6,7 @@ What's New in dnspython 2.6.0 (in development) ---------------------- -* TBD +* Added support for the NSID EDNS option. 2.5.0 ----- diff --git a/tests/test_edns.py b/tests/test_edns.py index 37bd9709..98e468ba 100644 --- a/tests/test_edns.py +++ b/tests/test_edns.py @@ -19,7 +19,6 @@ import operator import struct import unittest - from io import BytesIO import dns.edns @@ -201,6 +200,22 @@ class OptionTestCase(unittest.TestCase): self.assertFalse(o1 == 123) self.assertTrue(o1 != 123) + def testNSIDOption(self): + opt = dns.edns.NSIDOption(b"testing") + io = BytesIO() + opt.to_wire(io) + data = io.getvalue() + self.assertEqual(data, b"testing") + self.assertEqual(str(opt), "NSID testing") + opt = dns.edns.NSIDOption(b"\xfe\xff") + io = BytesIO() + opt.to_wire(io) + data = io.getvalue() + self.assertEqual(data, b"\xfe\xff") + self.assertEqual(str(opt), "NSID feff") + o = dns.edns.option_from_wire(dns.edns.OptionType.NSID, data, 0, len(data)) + self.assertEqual(o.nsid, b"\xfe\xff") + def test_option_registration(self): U32OptionType = 9999