From: Bob Halley Date: Wed, 24 Jul 2024 18:29:07 +0000 (-0700) Subject: ReportChannel EDNS option support. (#1111) X-Git-Tag: v2.7.0rc1~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3f83a8d0ef37fa95a35881d4a7abb8ba86b263bd;p=thirdparty%2Fdnspython.git ReportChannel EDNS option support. (#1111) --- diff --git a/dns/edns.py b/dns/edns.py index cbb7c443..f7d9ff99 100644 --- a/dns/edns.py +++ b/dns/edns.py @@ -52,6 +52,8 @@ class OptionType(dns.enum.IntEnum): CHAIN = 13 #: EDE (extended-dns-error) EDE = 15 + #: REPORTCHANNEL + REPORTCHANNEL = 18 @classmethod def _maximum(cls): @@ -462,11 +464,31 @@ class CookieOption(Option): return cls(parser.get_bytes(8), parser.get_remaining()) +class ReportChannelOption(Option): + # RFC 9567 + def __init__(self, agent_domain: dns.name.Name): + super().__init__(OptionType.REPORTCHANNEL) + self.agent_domain = agent_domain + + def to_wire(self, file: Any = None) -> Optional[bytes]: + return self.agent_domain.to_wire(file) + + def to_text(self) -> str: + return "REPORTCHANNEL " + self.agent_domain.to_text() + + @classmethod + def from_wire_parser( + cls, otype: Union[OptionType, str], parser: dns.wire.Parser + ) -> Option: + return cls(parser.get_name()) + + _type_to_class: Dict[OptionType, Any] = { OptionType.ECS: ECSOption, OptionType.EDE: EDEOption, OptionType.NSID: NSIDOption, OptionType.COOKIE: CookieOption, + OptionType.REPORTCHANNEL: ReportChannelOption, } @@ -545,5 +567,6 @@ KEEPALIVE = OptionType.KEEPALIVE PADDING = OptionType.PADDING CHAIN = OptionType.CHAIN EDE = OptionType.EDE +REPORTCHANNEL = OptionType.REPORTCHANNEL ### END generated OptionType constants diff --git a/doc/message-edns.rst b/doc/message-edns.rst index 011fc848..21d106db 100644 --- a/doc/message-edns.rst +++ b/doc/message-edns.rst @@ -28,7 +28,19 @@ will create a ``dns.edns.ECSOption`` object to represent it. .. autoclass:: dns.edns.ECSOption :members: - + +.. autoclass:: dns.edns.EDEOption + :members: + +.. autoclass:: dns.edns.NSIDOption + :members: + +.. autoclass:: dns.edns.CookieOption + :members: + +.. autoclass:: dns.edns.ReportChannelOption + :members: + .. autofunction:: dns.edns.get_option_class .. autofunction:: dns.edns.option_from_wire_parser .. autofunction:: dns.edns.option_from_wire diff --git a/tests/test_edns.py b/tests/test_edns.py index 74b16c5c..952ca05e 100644 --- a/tests/test_edns.py +++ b/tests/test_edns.py @@ -252,6 +252,20 @@ class OptionTestCase(unittest.TestCase): b"12345678", b"abcdefghabcdefghabcdefghabcdefghi" ) + def testReportChannelOption(self): + agent_domain = dns.name.from_text("agent.example.") + expected_wire = b"\x05agent\x07example\x00" + opt = dns.edns.ReportChannelOption(agent_domain) + io = BytesIO() + opt.to_wire(io) + data = io.getvalue() + self.assertEqual(data, expected_wire) + self.assertEqual(str(opt), "REPORTCHANNEL agent.example.") + opt2 = dns.edns.option_from_wire( + dns.edns.OptionType.REPORTCHANNEL, expected_wire, 0, len(expected_wire) + ) + self.assertEqual(opt2.agent_domain, agent_domain) + def test_option_registration(self): U32OptionType = 9999