]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
Improvements to dns.rdata.to_wire(). 499/head
authorBrian Wellington <bwelling@xbill.org>
Mon, 1 Jun 2020 18:32:03 +0000 (11:32 -0700)
committerBrian Wellington <bwelling@xbill.org>
Mon, 1 Jun 2020 18:32:03 +0000 (11:32 -0700)
This does two things.

1) Makes the file parameter optional, removing the requirement that
callers create an io.BytesIO object if all they want is the bytes.  This
is done by renaming all of the rdata subclass to_wire() methods to
_to_wire(), and making dns.rdata.to_wire() create the io.BytesIO
internally if needed, and then delegate to the subclass.

2) Add canonicalize=False parameter, allowing code reuse for conversion
to wire format and conversion to hashable format.  This also removes all
of the rdata subclass to_digestable routines that are no longer needed,
as dns.rdata.to_digestable will work for all rdata types.

44 files changed:
dns/dnssec.py
dns/name.py
dns/name.pyi
dns/rdata.py
dns/rdata.pyi
dns/rdtypes/ANY/CAA.py
dns/rdtypes/ANY/CERT.py
dns/rdtypes/ANY/CSYNC.py
dns/rdtypes/ANY/DNAME.py
dns/rdtypes/ANY/GPOS.py
dns/rdtypes/ANY/HINFO.py
dns/rdtypes/ANY/HIP.py
dns/rdtypes/ANY/ISDN.py
dns/rdtypes/ANY/LOC.py
dns/rdtypes/ANY/NSEC.py
dns/rdtypes/ANY/NSEC3.py
dns/rdtypes/ANY/NSEC3PARAM.py
dns/rdtypes/ANY/OPENPGPKEY.py
dns/rdtypes/ANY/RP.py
dns/rdtypes/ANY/RRSIG.py
dns/rdtypes/ANY/SOA.py
dns/rdtypes/ANY/SSHFP.py
dns/rdtypes/ANY/TLSA.py
dns/rdtypes/ANY/URI.py
dns/rdtypes/ANY/X25.py
dns/rdtypes/CH/A.py
dns/rdtypes/IN/A.py
dns/rdtypes/IN/AAAA.py
dns/rdtypes/IN/APL.py
dns/rdtypes/IN/DHCID.py
dns/rdtypes/IN/IPSECKEY.py
dns/rdtypes/IN/NAPTR.py
dns/rdtypes/IN/NSAP.py
dns/rdtypes/IN/PX.py
dns/rdtypes/IN/SRV.py
dns/rdtypes/IN/WKS.py
dns/rdtypes/dnskeybase.py
dns/rdtypes/dnskeybase.pyi
dns/rdtypes/dsbase.py
dns/rdtypes/euibase.py
dns/rdtypes/mxbase.py
dns/rdtypes/nsbase.py
dns/rdtypes/txtbase.py
tests/test_rdtypeanyeui.py

index f775086ffe68757ef4b4751bd943494175ded307..598e486934db6b64d300e53de1821cf1e2916c64 100644 (file)
@@ -18,7 +18,6 @@
 """Common DNSSEC-related functions and constants."""
 
 import hashlib
-import io
 import struct
 import time
 import base64
@@ -90,12 +89,6 @@ def algorithm_to_text(value):
     return Algorithm.to_text(value)
 
 
-def _to_rdata(record, origin):
-    s = io.BytesIO()
-    record.to_wire(s, origin=origin)
-    return s.getvalue()
-
-
 def key_id(key):
     """Return the key id (a 16-bit number) for the specified key.
 
@@ -104,7 +97,7 @@ def key_id(key):
     Returns an ``int`` between 0 and 65535
     """
 
-    rdata = _to_rdata(key, None)
+    rdata = key.to_wire()
     if key.algorithm == Algorithm.RSAMD5:
         return (rdata[-3] << 8) + rdata[-2]
     else:
@@ -166,7 +159,7 @@ def make_ds(name, key, algorithm, origin=None):
     if isinstance(name, str):
         name = dns.name.from_text(name, origin)
     dshash.update(name.canonicalize().to_wire())
-    dshash.update(_to_rdata(key, origin))
+    dshash.update(key.to_wire(origin=origin))
     digest = dshash.digest()
 
     dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, algorithm) + \
@@ -397,7 +390,7 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None):
             raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm)
 
         data = b''
-        data += _to_rdata(rrsig, origin)[:18]
+        data += rrsig.to_wire(origin=origin)[:18]
         data += rrsig.signer.to_digestable(origin)
 
         if rrsig.labels < len(rrname) - 1:
index adf39c1b2fa9b03eee136516319aebe654b18f96..fb64f428d72594403e8f60bbc35856c0aec86cd6 100644 (file)
@@ -590,19 +590,10 @@ class Name(object):
         Returns a ``bytes``.
         """
 
-        out = bytearray()
-        for label in self.labels:
-            out.append(len(label))
-            out += label.lower()
-        if not self.is_absolute():
-            if origin is None or not origin.is_absolute():
-                raise NeedAbsoluteNameOrOrigin
-            for label in origin.labels:
-                out.append(len(label))
-                out += label.lower()
-        return bytes(out)
+        return self.to_wire(origin=origin, canonicalize=True)
 
-    def to_wire(self, file=None, compress=None, origin=None):
+    def to_wire(self, file=None, compress=None, origin=None,
+                canonicalize=False):
         """Convert name to wire format, possibly compressing it.
 
         *file* is the file where the name is emitted (typically an
@@ -619,6 +610,10 @@ class Name(object):
         relative and origin is not ``None``, then *origin* will be appended
         to it.
 
+        *canonicalize*, a ``bool``, indicates whether the name should
+        be canonicalized; that is, converted to a format suitable for
+        digesting in hashes.
+
         Raises ``dns.name.NeedAbsoluteNameOrOrigin`` if the name is
         relative and no origin was provided.
 
@@ -629,13 +624,19 @@ class Name(object):
             out = bytearray()
             for label in self.labels:
                 out.append(len(label))
-                out += label
+                if canonicalize:
+                    out += label.lower()
+                else:
+                    out += label
             if not self.is_absolute():
                 if origin is None or not origin.is_absolute():
                     raise NeedAbsoluteNameOrOrigin
                 for label in origin.labels:
                     out.append(len(label))
-                    out += label
+                    if canonicalize:
+                        out += label.lower()
+                    else:
+                        out += label
             return bytes(out)
 
         if not self.is_absolute():
@@ -666,7 +667,10 @@ class Name(object):
                 l = len(label)
                 file.write(struct.pack('!B', l))
                 if l > 0:
-                    file.write(label)
+                    if canonicalize:
+                        file.write(label.lower())
+                    else:
+                        file.write(label)
 
     def __len__(self):
         """The length of the name (in labels).
index 2fc37ad04ea7cc6870240cc4c45386713a9a2f2b..446600b099d29c32b577a5791ec4dabd23b9f4ad 100644 (file)
@@ -18,7 +18,8 @@ class Name:
     def to_text(self, omit_final_dot=False) -> str: ...
     def to_unicode(self, omit_final_dot=False, idna_codec=None) -> str: ...
     def to_digestable(self, origin=None) -> bytes: ...
-    def to_wire(self, file=None, compress=None, origin=None) -> Optional[bytes]: ...
+    def to_wire(self, file=None, compress=None, origin=None,
+                canonicalize=False) -> Optional[bytes]: ...
     def __add__(self, other : Name): ...
     def __sub__(self, other : Name): ...
     def split(self, depth) -> List[Tuple[str,str]]: ...
index b8d65f145ceb7f9f765b6358f1cad0e93577f6e0..be5d3dbde480cc5b2cc8ee4a7a8fb38ff187147f 100644 (file)
@@ -166,22 +166,30 @@ class Rdata(object):
 
         raise NotImplementedError
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
+        raise NotImplementedError
+
+    def to_wire(self, file=None, compress=None, origin=None,
+                canonicalize=False):
         """Convert an rdata to wire format.
 
-        Returns ``None``.
+        Returns a ``bytes`` or ``None``.
         """
 
-        raise NotImplementedError
+        if file:
+            return self._to_wire(file, compress, origin, canonicalize)
+        else:
+            f = io.BytesIO()
+            self._to_wire(f, compress, origin, canonicalize)
+            return f.getvalue()
 
     def to_generic(self, origin=None):
         """Creates a dns.rdata.GenericRdata equivalent of this rdata.
 
         Returns a ``dns.rdata.GenericRdata``.
         """
-        f = io.BytesIO()
-        self.to_wire(f, origin=origin)
-        return dns.rdata.GenericRdata(self.rdclass, self.rdtype, f.getvalue())
+        return dns.rdata.GenericRdata(self.rdclass, self.rdtype,
+                                      self.to_wire(origin=origin))
 
     def to_digestable(self, origin=None):
         """Convert rdata to a format suitable for digesting in hashes.  This
@@ -190,9 +198,7 @@ class Rdata(object):
         Returns a ``bytes``.
         """
 
-        f = io.BytesIO()
-        self.to_wire(f, None, origin)
-        return f.getvalue()
+        return self.to_wire(origin=origin, canonicalize=True)
 
     def validate(self):
         """Check that the current contents of the rdata's fields are
@@ -361,7 +367,7 @@ class GenericRdata(Rdata):
                 'generic rdata hex data has wrong length')
         return cls(rdclass, rdtype, data)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         file.write(self.data)
 
     @classmethod
index 84eeb8f8f61ade60eb3ff808b958d5bcc7e291a8..f394791fbaf19ab72a5021c026ed538b522ca085 100644 (file)
@@ -1,9 +1,9 @@
-from typing import Dict, Tuple, Any, Optional
+from typing import Dict, Tuple, Any, Optional, BinaryIO
 from .name import Name, IDNACodec
 class Rdata:
     def __init__(self):
         self.address : str
-    def to_wire(self, file, compress : Optional[Dict[Name,int]], origin : Optional[Name]) -> bytes:
+    def to_wire(self, file : Optional[BinaryIO], compress : Optional[Dict[Name,int]], origin : Optional[Name], canonicalize : Optional[bool]) -> Optional[bytes]:
         ...
     @classmethod
     def from_text(cls, rdclass : int, rdtype : int, tok, origin=None, relativize=True):
index 8e59800489f3888f9a80285b767cf4d21bb226d5..d498107e03bec89d0d0a6eb48beffbc63762fb4b 100644 (file)
@@ -53,7 +53,7 @@ class CAA(dns.rdata.Rdata):
         value = tok.get_string().encode()
         return cls(rdclass, rdtype, flags, tag, value)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         file.write(struct.pack('!B', self.flags))
         l = len(self.tag)
         assert l < 256
index 1432295ba914e50b4cd7166a8b3e0b1cd4bbc6a9..5e4ceb8c7386cc83b4f1bf15184115966634eee1 100644 (file)
@@ -97,7 +97,7 @@ class CERT(dns.rdata.Rdata):
         return cls(rdclass, rdtype, certificate_type, key_tag,
                    algorithm, certificate)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         prefix = struct.pack("!HHB", self.certificate_type, self.key_tag,
                              self.algorithm)
         file.write(prefix)
index e258fda7c5b0620b3442038cdd364724f6d06bad..66f2f31b34fd2cca7be1a076d3dbca9a8a42430d 100644 (file)
@@ -86,7 +86,7 @@ class CSYNC(dns.rdata.Rdata):
         windows.append((window, bitmap[0:octets]))
         return cls(rdclass, rdtype, serial, flags, windows)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         file.write(struct.pack('!IH', self.serial, self.flags))
         for (window, bitmap) in self.windows:
             file.write(struct.pack('!BB', window, len(bitmap)))
index 2499283cfaea30d5d9c1b316ac7584fae04f90a7..2000d9b03546ca02cf0a1a095080ca3ba01f8f4f 100644 (file)
@@ -22,5 +22,5 @@ class DNAME(dns.rdtypes.nsbase.UncompressedNS):
 
     """DNAME record"""
 
-    def to_digestable(self, origin=None):
-        return self.target.to_digestable(origin)
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
+        self.target.to_wire(file, None, origin, canonicalize)
index 4969509e0c7d8480f4ca2b7fa0544e4b83c0b450..4e9e8192a07935cb8178ef2cd85a01fa2bfe3bb6 100644 (file)
@@ -85,7 +85,7 @@ class GPOS(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, latitude, longitude, altitude)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         l = len(self.latitude)
         assert l < 256
         file.write(struct.pack('!B', l))
index e3efb51aedfbda67b407159c656b01e311aea3dc..dc982f11c9aa749f96879b6e9de481c75b90b96d 100644 (file)
@@ -53,7 +53,7 @@ class HINFO(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, cpu, os)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         l = len(self.cpu)
         assert l < 256
         file.write(struct.pack('!B', l))
index 8ac1d177978000df69e5d3b7721ec33e586f73fb..51e42ac9bbd12014ab9b46c3a46b54df4134471e 100644 (file)
@@ -67,14 +67,14 @@ class HIP(dns.rdata.Rdata):
             servers.append(server)
         return cls(rdclass, rdtype, hit, algorithm, key, servers)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         lh = len(self.hit)
         lk = len(self.key)
         file.write(struct.pack("!BBH", lh, self.algorithm, lk))
         file.write(self.hit)
         file.write(self.key)
         for server in self.servers:
-            server.to_wire(file, None, origin)
+            server.to_wire(file, None, origin, False)
 
     @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
index 4df58ad2474045dbfa8caf95b7b522c6422cbba9..37332321e11aea96b75c59a3043926adb3b46462 100644 (file)
@@ -62,7 +62,7 @@ class ISDN(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, address, subaddress)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         l = len(self.address)
         assert l < 256
         file.write(struct.pack('!B', l))
index a346cacb687dff9535441f4c0db3f0e8c10f0576..c8785acc50aa34263996f03262f223b59b5439a4 100644 (file)
@@ -254,7 +254,7 @@ class LOC(dns.rdata.Rdata):
         return cls(rdclass, rdtype, latitude, longitude, altitude,
                    size, hprec, vprec)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         milliseconds = (self.latitude[0] * 3600000 +
                         self.latitude[1] * 60000 +
                         self.latitude[2] * 1000 +
index 7da00e9ea141c40aa78103e2ca99e3edf4845399..24936cbea9815c4ff5910f09fd7b0f465b2426fa 100644 (file)
@@ -87,20 +87,12 @@ class NSEC(dns.rdata.Rdata):
         windows.append((window, bitmap[0:octets]))
         return cls(rdclass, rdtype, next, windows)
 
-    def to_wire(self, file, compress=None, origin=None):
-        self.next.to_wire(file, None, origin)
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
+        self.next.to_wire(file, None, origin, canonicalize)
         for (window, bitmap) in self.windows:
             file.write(struct.pack('!BB', window, len(bitmap)))
             file.write(bitmap)
 
-    def to_digestable(self, origin=None):
-        file = io.BytesIO()
-        file.write(self.next.to_digestable(origin))
-        for (window, bitmap) in self.windows:
-            file.write(struct.pack('!BB', window, len(bitmap)))
-            file.write(bitmap)
-        return file.getvalue()
-
     @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         (next, cused) = dns.name.from_wire(wire[: current + rdlen], current)
index c41b8fa644724d8c2e450f892c85ac8005d99c9a..208f9e8c93d821ec53611be1c866c706dd3dd272 100644 (file)
@@ -125,7 +125,7 @@ class NSEC3(dns.rdata.Rdata):
         return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next,
                    windows)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         l = len(self.salt)
         file.write(struct.pack("!BBHB", self.algorithm, self.flags,
                                self.iterations, l))
index f0d5bb104e2c5513313ecbc4411891627456df80..d10321b3417865f86f13c3e8ae12a5eefc1eb372 100644 (file)
@@ -60,7 +60,7 @@ class NSEC3PARAM(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, algorithm, flags, iterations, salt)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         l = len(self.salt)
         file.write(struct.pack("!BBHB", self.algorithm, self.flags,
                                self.iterations, l))
index 0bf7ab4305be0723f23aa02414aeb1b79c16c9cc..ddcd055c073775003aa12715d1a5fe845b1bf37d 100644 (file)
@@ -49,7 +49,7 @@ class OPENPGPKEY(dns.rdata.Rdata):
         key = base64.b64decode(b64)
         return cls(rdclass, rdtype, key)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         file.write(self.key)
 
     @classmethod
index 9580929f706713766933e8960b9bdf8a5c178c59..5c4cc59b2ffe492064eafbd86df2c3c98dfff157 100644 (file)
@@ -46,13 +46,9 @@ class RP(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, mbox, txt)
 
-    def to_wire(self, file, compress=None, origin=None):
-        self.mbox.to_wire(file, None, origin)
-        self.txt.to_wire(file, None, origin)
-
-    def to_digestable(self, origin=None):
-        return self.mbox.to_digestable(origin) + \
-            self.txt.to_digestable(origin)
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
+        self.mbox.to_wire(file, None, origin, canonicalize)
+        self.txt.to_wire(file, None, origin, canonicalize)
 
     @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
index c7b9e7a1a900ca6d22ea00105727648f7390bf78..0ee1c0673e3caab491f5957d7ff916cb302a0e2a 100644 (file)
@@ -113,23 +113,15 @@ class RRSIG(dns.rdata.Rdata):
                    original_ttl, expiration, inception, key_tag, signer,
                    signature)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         header = struct.pack('!HBBIIIH', self.type_covered,
                              self.algorithm, self.labels,
                              self.original_ttl, self.expiration,
                              self.inception, self.key_tag)
         file.write(header)
-        self.signer.to_wire(file, None, origin)
+        self.signer.to_wire(file, None, origin, canonicalize)
         file.write(self.signature)
 
-    def to_digestable(self, origin=None):
-        return struct.pack('!HBBIIIH', self.type_covered,
-                           self.algorithm, self.labels,
-                           self.original_ttl, self.expiration,
-                           self.inception, self.key_tag) + \
-                           self.signer.to_digestable(origin) + \
-                           self.signature
-
     @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         header = struct.unpack('!HBBIIIH', wire[current: current + 18])
index bb502653d64c165a8e939ec7156e28b016655231..cd59ec0d2aa8b06e13499e7bf2b9f6d8dfd2adc3 100644 (file)
@@ -63,19 +63,13 @@ class SOA(dns.rdata.Rdata):
         return cls(rdclass, rdtype, mname, rname, serial, refresh, retry,
                    expire, minimum)
 
-    def to_wire(self, file, compress=None, origin=None):
-        self.mname.to_wire(file, compress, origin)
-        self.rname.to_wire(file, compress, origin)
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
+        self.mname.to_wire(file, compress, origin, canonicalize)
+        self.rname.to_wire(file, compress, origin, canonicalize)
         five_ints = struct.pack('!IIIII', self.serial, self.refresh,
                                 self.retry, self.expire, self.minimum)
         file.write(five_ints)
 
-    def to_digestable(self, origin=None):
-        return self.mname.to_digestable(origin) + \
-            self.rname.to_digestable(origin) + \
-            struct.pack('!IIIII', self.serial, self.refresh,
-                        self.retry, self.expire, self.minimum)
-
     @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         (mname, cused) = dns.name.from_wire(wire[: current + rdlen], current)
index 8f8d0ca46300e2b9c3c149872e113b89270ffed5..1c5269fd9ef67511461c30d3115279401502224a 100644 (file)
@@ -60,7 +60,7 @@ class SSHFP(dns.rdata.Rdata):
         fingerprint = binascii.unhexlify(fingerprint)
         return cls(rdclass, rdtype, algorithm, fp_type, fingerprint)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         header = struct.pack("!BB", self.algorithm, self.fp_type)
         file.write(header)
         file.write(self.fingerprint)
index 7b39030f14fb9068f52cb2054ea980fef672be39..c6db8623d16b863eb23bf9c16226006ac90c43ed 100644 (file)
@@ -63,7 +63,7 @@ class TLSA(dns.rdata.Rdata):
         cert = binascii.unhexlify(cert)
         return cls(rdclass, rdtype, usage, selector, mtype, cert)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         header = struct.pack("!BBB", self.usage, self.selector, self.mtype)
         file.write(header)
         file.write(self.cert)
index c37ecdf189e200674c8c91fbfe019708b9fe83dc..77f89645795d15f98acb41c78abde4a4a6516734 100644 (file)
@@ -57,7 +57,7 @@ class URI(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, priority, weight, target.value)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         two_ints = struct.pack("!HH", self.priority, self.weight)
         file.write(two_ints)
         file.write(self.target)
index 04c332061811cc62496bb4c3b8e369ccba1404b8..ac61849e1fffb7d11d7ca5df8965ea7d14e083b4 100644 (file)
@@ -47,7 +47,7 @@ class X25(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, address)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         l = len(self.address)
         assert l < 256
         file.write(struct.pack('!B', l))
index 42b72e5b044ad1a94ca3f731817cf5720f418454..fefbab63ee23f1395e7e4f77b7326aa3c1569ab4 100644 (file)
@@ -44,15 +44,11 @@ class A(dns.rdtypes.mxbase.MXBase):
         tok.get_eol()
         return cls(rdclass, rdtype, address, domain)
 
-    def to_wire(self, file, compress=None, origin=None):
-        self.domain.to_wire(file, compress, origin)
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
+        self.domain.to_wire(file, compress, origin, canonicalize)
         pref = struct.pack("!H", self.address)
         file.write(pref)
 
-    def to_digestable(self, origin=None):
-        return self.domain.to_digestable(origin) + \
-            struct.pack("!H", self.address)
-
     @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
         (domain, cused) = dns.name.from_wire(wire[:current + rdlen - 2],
index 9476d47552cb2def94d54211a54656f5346a1f0f..461ce9275e7a2dd4fe3e34ce6aa84b2f1bc1c562 100644 (file)
@@ -43,7 +43,7 @@ class A(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, address)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         file.write(dns.ipv4.inet_aton(self.address))
 
     @classmethod
index 658cc4b0006c9460aae4147e6d098d6980104e9a..9751f82cb5796023cd2e752260d2d108a50b4600 100644 (file)
@@ -43,7 +43,7 @@ class AAAA(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, address)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         file.write(dns.ipv6.inet_aton(self.address))
 
     @classmethod
index 2481d62da68479f6ed0ed0be7878c709227b124e..5facf05d58a7fe5a691a72f8dc017266cbdc16ad 100644 (file)
@@ -106,7 +106,7 @@ class APL(dns.rdata.Rdata):
 
         return cls(rdclass, rdtype, items)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         for item in self.items:
             item.to_wire(file)
 
index c5e526ce555fd15c564d18c1218c082e2eefbf33..cd5d07454a684bbd8264b29af893e1783695cf0a 100644 (file)
@@ -50,7 +50,7 @@ class DHCID(dns.rdata.Rdata):
         data = base64.b64decode(b64)
         return cls(rdclass, rdtype, data)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         file.write(self.data)
 
     @classmethod
index 674f5e99e083c451669b11ed442b1358414050e6..24dc652eaf5f086a6cabefd65f2e3069aa8efe79 100644 (file)
@@ -94,7 +94,7 @@ class IPSECKEY(dns.rdata.Rdata):
         return cls(rdclass, rdtype, precedence, gateway_type, algorithm,
                    gateway, key)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         header = struct.pack("!BBB", self.precedence, self.gateway_type,
                              self.algorithm)
         file.write(header)
@@ -105,7 +105,7 @@ class IPSECKEY(dns.rdata.Rdata):
         elif self.gateway_type == 2:
             file.write(dns.ipv6.inet_aton(self.gateway))
         elif self.gateway_type == 3:
-            self.gateway.to_wire(file, None, origin)
+            self.gateway.to_wire(file, None, origin, False)
         else:
             raise ValueError('invalid gateway type')
         file.write(self.key)
index c68efc3845e1442afdded85a1420c0c8df9732dd..c0afc94302496c8ddbe79275d985ac693d8a57fb 100644 (file)
@@ -77,22 +77,13 @@ class NAPTR(dns.rdata.Rdata):
         return cls(rdclass, rdtype, order, preference, flags, service,
                    regexp, replacement)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         two_ints = struct.pack("!HH", self.order, self.preference)
         file.write(two_ints)
         _write_string(file, self.flags)
         _write_string(file, self.service)
         _write_string(file, self.regexp)
-        self.replacement.to_wire(file, compress, origin)
-
-    def to_digestable(self, origin=None):
-        file = io.BytesIO()
-        two_ints = struct.pack("!HH", self.order, self.preference)
-        file.write(two_ints)
-        _write_string(file, self.flags)
-        _write_string(file, self.service)
-        _write_string(file, self.regexp)
-        return file.getvalue() + self.replacement.to_digestable(origin)
+        self.replacement.to_wire(file, compress, origin, canonicalize)
 
     @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
index d098b4d98e06ea16fa7b3597f254289b3c8f8f36..a42e5928782bf051d45a2c067c43ce57cda5d0b8 100644 (file)
@@ -50,7 +50,7 @@ class NSAP(dns.rdata.Rdata):
         address = binascii.unhexlify(address.encode())
         return cls(rdclass, rdtype, address)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         file.write(self.address)
 
     @classmethod
index e11f26554838191a4c9f7a4f1dc37c39ae906583..e8e0adacfa6670bd50744039b161aadabeb92db2 100644 (file)
@@ -50,16 +50,11 @@ class PX(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, preference, map822, mapx400)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         pref = struct.pack("!H", self.preference)
         file.write(pref)
-        self.map822.to_wire(file, None, origin)
-        self.mapx400.to_wire(file, None, origin)
-
-    def to_digestable(self, origin=None):
-        return struct.pack("!H", self.preference) + \
-            self.map822.to_digestable(origin) + \
-            self.mapx400.to_digestable(origin)
+        self.map822.to_wire(file, None, origin, canonicalize)
+        self.mapx400.to_wire(file, None, origin, canonicalize)
 
     @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
index 8c08f0b01e3fafbd8fcbd4d6c010112c33be76a4..2b46305f5317f50b2355bc02eb4ac5af14386ebc 100644 (file)
@@ -53,16 +53,10 @@ class SRV(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, priority, weight, port, target)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         three_ints = struct.pack("!HHH", self.priority, self.weight, self.port)
         file.write(three_ints)
-        self.target.to_wire(file, compress, origin)
-
-    def to_digestable(self, origin=None):
-        f = io.BytesIO()
-        f.write(struct.pack("!HHH", self.priority, self.weight, self.port))
-        f.write(self.target.to_digestable(origin))
-        return f.getvalue()
+        self.target.to_wire(file, compress, origin, canonicalize)
 
     @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
index 155f86be870f5a4bac96fde6311fb2ddf2d6f062..a56413581a5ff86be22f51d90cf26cd8ae140aaa 100644 (file)
@@ -82,7 +82,7 @@ class WKS(dns.rdata.Rdata):
         bitmap = dns.rdata._truncate_bitmap(bitmap)
         return cls(rdclass, rdtype, address, protocol, bitmap)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         file.write(dns.ipv4.inet_aton(self.address))
         protocol = struct.pack('!B', self.protocol)
         file.write(protocol)
index 1099e394551f85cc0a2503567000a9dfa7101fab..cfa34c2a836d0d74d3b5a7ea433457fb4c3c2773 100644 (file)
@@ -69,7 +69,7 @@ class DNSKEYBase(dns.rdata.Rdata):
         key = base64.b64decode(b64)
         return cls(rdclass, rdtype, flags, protocol, algorithm, key)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         header = struct.pack("!HBB", self.flags, self.protocol, self.algorithm)
         file.write(header)
         file.write(self.key)
index ee70691d3afeb49a950d00489a779dcf850cbf63..2588cf379a4ea407f0c390a825bec98eae833713 100644 (file)
@@ -27,7 +27,7 @@ class DNSKEYBase(rdata.Rdata):
                   relativize_to=None):
         ...
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         ...
 
     @classmethod
index 8da007bc8ea31682282cdbffb29cb0ae1e716271..4f082c7f3218b11d585322d7fd82b25984f3b503 100644 (file)
@@ -61,7 +61,7 @@ class DSBase(dns.rdata.Rdata):
         return cls(rdclass, rdtype, key_tag, algorithm, digest_type,
                    digest)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         header = struct.pack("!HBB", self.key_tag, self.algorithm,
                              self.digest_type)
         file.write(header)
index db4e56b12294f6b9e6e2e667cdeee806614ad280..7756538c5c3541bed69750de401e539f3c612ff9 100644 (file)
@@ -59,7 +59,7 @@ class EUIBase(dns.rdata.Rdata):
             raise dns.exception.SyntaxError('Hex decoding error: %s' % str(ex))
         return cls(rdclass, rdtype, data)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         file.write(self.eui)
 
     @classmethod
index a238b511643465b4fe7ef41109f0665e7544cabf..eb5816b2204565d631abf9e7f67d5d6f0603b4f6 100644 (file)
@@ -48,14 +48,10 @@ class MXBase(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, preference, exchange)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         pref = struct.pack("!H", self.preference)
         file.write(pref)
-        self.exchange.to_wire(file, compress, origin)
-
-    def to_digestable(self, origin=None):
-        return struct.pack("!H", self.preference) + \
-            self.exchange.to_digestable(origin)
+        self.exchange.to_wire(file, compress, origin, canonicalize)
 
     @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
@@ -77,13 +73,8 @@ class UncompressedMX(MXBase):
     is not compressed when converted to DNS wire format, and whose
     digestable form is not downcased."""
 
-    def to_wire(self, file, compress=None, origin=None):
-        super(UncompressedMX, self).to_wire(file, None, origin)
-
-    def to_digestable(self, origin=None):
-        f = io.BytesIO()
-        self.to_wire(f, None, origin)
-        return f.getvalue()
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
+        super()._to_wire(file, None, origin, False)
 
 
 class UncompressedDowncasingMX(MXBase):
@@ -91,5 +82,5 @@ class UncompressedDowncasingMX(MXBase):
     """Base class for rdata that is like an MX record, but whose name
     is not compressed when convert to DNS wire format."""
 
-    def to_wire(self, file, compress=None, origin=None):
-        super(UncompressedDowncasingMX, self).to_wire(file, None, origin)
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
+        super()._to_wire(file, None, origin, canonicalize)
index aab57fa3e748792e32902e477b29004e950df4f6..dbd016096d0166a791fc7771c7be1203d0070b7c 100644 (file)
@@ -45,11 +45,8 @@ class NSBase(dns.rdata.Rdata):
         tok.get_eol()
         return cls(rdclass, rdtype, target)
 
-    def to_wire(self, file, compress=None, origin=None):
-        self.target.to_wire(file, compress, origin)
-
-    def to_digestable(self, origin=None):
-        return self.target.to_digestable(origin)
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
+        self.target.to_wire(file, compress, origin, canonicalize)
 
     @classmethod
     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
@@ -68,10 +65,5 @@ class UncompressedNS(NSBase):
     is not compressed when convert to DNS wire format, and whose
     digestable form is not downcased."""
 
-    def to_wire(self, file, compress=None, origin=None):
-        super(UncompressedNS, self).to_wire(file, None, origin)
-
-    def to_digestable(self, origin=None):
-        f = io.BytesIO()
-        self.to_wire(f, None, origin)
-        return f.getvalue()
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
+        self.target.to_wire(file, None, origin, False)
index 1c15dbf58a8bc5064af1ce6d757328ea431bc8c5..ec061a185022d77aeef1fd28d4c48cf1205f7d56 100644 (file)
@@ -76,7 +76,7 @@ class TXTBase(dns.rdata.Rdata):
             raise dns.exception.UnexpectedEnd
         return cls(rdclass, rdtype, strings)
 
-    def to_wire(self, file, compress=None, origin=None):
+    def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
         for s in self.strings:
             l = len(s)
             assert l < 256
index 625c0c3c4f5b81a52b337c7f2f0da2995ec17431..e8645820175d85853432ab6748838cb1ae124710 100644 (file)
@@ -15,7 +15,6 @@
 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 import unittest
-from io import BytesIO
 
 import dns.rrset
 import dns.rdtypes.ANY.EUI48
@@ -89,9 +88,7 @@ class RdtypeAnyEUI48TestCase(unittest.TestCase):
         inst = dns.rdtypes.ANY.EUI48.EUI48(dns.rdataclass.IN,
                                            dns.rdatatype.EUI48,
                                            eui)
-        buff = BytesIO()
-        inst.to_wire(buff)
-        self.assertEqual(buff.getvalue(), eui)
+        self.assertEqual(inst.to_wire(), eui)
 
     def testFromWireOk(self):
         '''Valid wire format.'''
@@ -188,9 +185,7 @@ class RdtypeAnyEUI64TestCase(unittest.TestCase):
         inst = dns.rdtypes.ANY.EUI64.EUI64(dns.rdataclass.IN,
                                            dns.rdatatype.EUI64,
                                            eui)
-        buff = BytesIO()
-        inst.to_wire(buff)
-        self.assertEqual(buff.getvalue(), eui)
+        self.assertEqual(inst.to_wire(), eui)
 
     def testFromWireOk(self):
         '''Valid wire format.'''