]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
ReportChannel EDNS option support. (#1111)
authorBob Halley <halley@dnspython.org>
Wed, 24 Jul 2024 18:29:07 +0000 (11:29 -0700)
committerGitHub <noreply@github.com>
Wed, 24 Jul 2024 18:29:07 +0000 (11:29 -0700)
dns/edns.py
doc/message-edns.rst
tests/test_edns.py

index cbb7c443f77c783d7dd200a89117d8ecb727da9c..f7d9ff996b5ac4e68798c67d2c8c96195d0a5dad 100644 (file)
@@ -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
index 011fc8487d9a48a00a92a8c927acaae4c03bfb19..21d106db0210a88a7c06e45e6a6a5a0b9ae5ff16 100644 (file)
@@ -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
index 74b16c5c8deeb41c8df32228f20dea4dfaf58a0c..952ca05ecfb777abdb597d59543e76352ff66a02 100644 (file)
@@ -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