]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
Add dns.edns.register_type().
authorBrian Wellington <bwelling@xbill.org>
Sat, 18 Jul 2020 00:01:32 +0000 (17:01 -0700)
committerBrian Wellington <bwelling@xbill.org>
Sat, 18 Jul 2020 00:01:32 +0000 (17:01 -0700)
This allows an application to register a custom EDNS option type.

dns/edns.py
tests/test_edns.py

index 28718d523501c7488ef8b35c14764fe3137833d4..05f76e6307c3825939e31c735e56b077fd598eb4 100644 (file)
@@ -342,3 +342,13 @@ def option_from_wire(otype, wire, current, olen):
     parser = dns.wire.Parser(wire, current)
     with parser.restrict_to(olen):
         return option_from_wire_parser(otype, parser)
+
+def register_type(implementation, otype):
+    """Register the implementation of an option type.
+
+    *implementation*, a ``class``, is a subclass of ``dns.edns.Option``.
+
+    *otype*, an ``int``, is the option type.
+    """
+
+    _type_to_class[otype] = implementation
index a640a743bda63acde1f1a11c044e9ed38e777372..e5dca062f9f21db1b67fec77b050e5bf113ccd61 100644 (file)
@@ -17,6 +17,7 @@
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import operator
+import struct
 import unittest
 
 from io import BytesIO
@@ -138,3 +139,39 @@ class OptionTestCase(unittest.TestCase):
         self.assertTrue(o1 != o2)
         self.assertFalse(o1 == 123)
         self.assertTrue(o1 != 123)
+
+    def test_option_registration(self):
+        U32OptionType = 9999
+
+        class U32Option(dns.edns.Option):
+            def __init__(self, value=None):
+                super().__init__(U32OptionType)
+                self.value = value
+
+            def to_wire(self, file=None):
+                data = struct.pack('!I', self.value)
+                if file:
+                    file.write(data)
+                else:
+                    return data
+
+            @classmethod
+            def from_wire_parser(cls, otype, parser):
+                (value,) = parser.get_struct('!I')
+                return cls(value)
+
+        try:
+            dns.edns.register_type(U32Option, U32OptionType)
+            generic = dns.edns.GenericOption(U32OptionType, b'\x00\x00\x00\x01')
+            wire1 = generic.to_wire()
+            u32 = dns.edns.option_from_wire_parser(U32OptionType,
+                                                   dns.wire.Parser(wire1))
+            self.assertEqual(u32.value, 1)
+            wire2 = u32.to_wire()
+            self.assertEqual(wire1, wire2)
+            self.assertEqual(u32, generic)
+        finally:
+            dns.edns._type_to_class.pop(U32OptionType, None)
+
+        opt = dns.edns.option_from_wire_parser(9999, dns.wire.Parser(wire1))
+        self.assertEqual(opt, generic)