diff options
author | Brian Wellington <bwelling@xbill.org> | 2020-07-01 10:32:19 -0700 |
---|---|---|
committer | Brian Wellington <bwelling@xbill.org> | 2020-07-01 10:33:49 -0700 |
commit | 7482b94a28dfcd9a98a3518effcec2a6085235d1 (patch) | |
tree | 43517d65a18aeff8b1d920f6e75e8ee08f94300e | |
parent | 7c0accbb5412d4065446543077ab625daf9749af (diff) | |
download | dnspython-7482b94a28dfcd9a98a3518effcec2a6085235d1.tar.gz |
Add support for the AMTRELAY type.
-rw-r--r-- | dns/rdatatype.py | 1 | ||||
-rw-r--r-- | dns/rdtypes/ANY/AMTRELAY.py | 87 | ||||
-rw-r--r-- | dns/rdtypes/IN/IPSECKEY.py | 74 | ||||
-rw-r--r-- | dns/rdtypes/__init__.py | 1 | ||||
-rw-r--r-- | dns/rdtypes/util.py | 91 | ||||
-rw-r--r-- | tests/example | 5 | ||||
-rw-r--r-- | tests/example1.good | 5 | ||||
-rw-r--r-- | tests/example2.good | 5 | ||||
-rw-r--r-- | tests/example3.good | 5 |
9 files changed, 215 insertions, 59 deletions
diff --git a/dns/rdatatype.py b/dns/rdatatype.py index 7769657..c793d5a 100644 --- a/dns/rdatatype.py +++ b/dns/rdatatype.py @@ -92,6 +92,7 @@ class RdataType(dns.enum.IntEnum): URI = 256 CAA = 257 AVC = 258 + AMTRELAY = 259 TA = 32768 DLV = 32769 diff --git a/dns/rdtypes/ANY/AMTRELAY.py b/dns/rdtypes/ANY/AMTRELAY.py new file mode 100644 index 0000000..8fb18c1 --- /dev/null +++ b/dns/rdtypes/ANY/AMTRELAY.py @@ -0,0 +1,87 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import struct + +import dns.exception +import dns.rdtypes.util + + +class Relay(dns.rdtypes.util.Gateway): + name = 'AMTRELAY relay' + +class AMTRELAY(dns.rdata.Rdata): + + """AMTRELAY record""" + + # see: RFC 8777 + + __slots__ = ['precedence', 'discovery_optional', 'relay_type', 'relay'] + + def __init__(self, rdclass, rdtype, precedence, discovery_optional, + relay_type, relay): + super().__init__(rdclass, rdtype) + Relay(relay_type, relay).check() + object.__setattr__(self, 'precedence', precedence) + object.__setattr__(self, 'discovery_optional', discovery_optional) + object.__setattr__(self, 'relay_type', relay_type) + object.__setattr__(self, 'relay', relay) + + def to_text(self, origin=None, relativize=True, **kw): + relay = Relay(self.relay_type, self.relay).to_text(origin, relativize) + return '%d %d %d %s' % (self.precedence, self.discovery_optional, + self.relay_type, relay) + + @classmethod + def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True, + relativize_to=None): + precedence = tok.get_uint8() + discovery_optional = tok.get_uint8() + if discovery_optional > 1: + raise dns.exception.SyntaxError('expecting 0 or 1') + discovery_optional = bool(discovery_optional) + relay_type = tok.get_uint8() + if relay_type > 0x7f: + raise dns.exception.SyntaxError('expecting an integer <= 127') + relay = Relay(relay_type).from_text(tok, origin, relativize, + relativize_to) + return cls(rdclass, rdtype, precedence, discovery_optional, relay_type, + relay) + + def _to_wire(self, file, compress=None, origin=None, canonicalize=False): + relay_type = self.relay_type | (self.discovery_optional << 7) + header = struct.pack("!BB", self.precedence, relay_type) + file.write(header) + Relay(self.relay_type, self.relay).to_wire(file, compress, origin, + canonicalize) + + @classmethod + def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None): + if rdlen < 2: + raise dns.exception.FormError + (precedence, relay_type) = struct.unpack('!BB', + wire[current: current + 2]) + current += 2 + rdlen -= 2 + discovery_optional = bool(relay_type >> 7) + relay_type &= 0x7f + (relay, cused) = Relay(relay_type).from_wire(wire, current, rdlen, + origin) + current += cused + rdlen -= cused + return cls(rdclass, rdtype, precedence, discovery_optional, relay_type, + relay) diff --git a/dns/rdtypes/IN/IPSECKEY.py b/dns/rdtypes/IN/IPSECKEY.py index b5bc0b3..6d0f425 100644 --- a/dns/rdtypes/IN/IPSECKEY.py +++ b/dns/rdtypes/IN/IPSECKEY.py @@ -19,11 +19,12 @@ import struct import base64 import dns.exception -import dns.ipv4 -import dns.ipv6 -import dns.name +import dns.rdtypes.util +class Gateway(dns.rdtypes.util.Gateway): + name = 'IPSECKEY gateway' + class IPSECKEY(dns.rdata.Rdata): """IPSECKEY record""" @@ -35,21 +36,7 @@ class IPSECKEY(dns.rdata.Rdata): def __init__(self, rdclass, rdtype, precedence, gateway_type, algorithm, gateway, key): super().__init__(rdclass, rdtype) - if gateway_type == 0: - if gateway != '.' and gateway is not None: - raise SyntaxError('invalid gateway for gateway type 0') - gateway = None - elif gateway_type == 1: - # check that it's OK - dns.ipv4.inet_aton(gateway) - elif gateway_type == 2: - # check that it's OK - dns.ipv6.inet_aton(gateway) - elif gateway_type == 3: - pass - else: - raise SyntaxError( - 'invalid IPSECKEY gateway type: %d' % gateway_type) + Gateway(gateway_type, gateway).check() object.__setattr__(self, 'precedence', precedence) object.__setattr__(self, 'gateway_type', gateway_type) object.__setattr__(self, 'algorithm', algorithm) @@ -57,16 +44,8 @@ class IPSECKEY(dns.rdata.Rdata): object.__setattr__(self, 'key', key) def to_text(self, origin=None, relativize=True, **kw): - if self.gateway_type == 0: - gateway = '.' - elif self.gateway_type == 1: - gateway = self.gateway - elif self.gateway_type == 2: - gateway = self.gateway - elif self.gateway_type == 3: - gateway = str(self.gateway.choose_relativity(origin, relativize)) - else: - raise ValueError('invalid gateway type') + gateway = Gateway(self.gateway_type, self.gateway).to_text(origin, + relativize) return '%d %d %d %s %s' % (self.precedence, self.gateway_type, self.algorithm, gateway, dns.rdata._base64ify(self.key)) @@ -77,10 +56,8 @@ class IPSECKEY(dns.rdata.Rdata): precedence = tok.get_uint8() gateway_type = tok.get_uint8() algorithm = tok.get_uint8() - if gateway_type == 3: - gateway = tok.get_name(origin, relativize, relativize_to) - else: - gateway = tok.get_string() + gateway = Gateway(gateway_type).from_text(tok, origin, relativize, + relativize_to) b64 = tok.concatenate_remaining_identifiers().encode() key = base64.b64decode(b64) return cls(rdclass, rdtype, precedence, gateway_type, algorithm, @@ -90,16 +67,8 @@ class IPSECKEY(dns.rdata.Rdata): header = struct.pack("!BBB", self.precedence, self.gateway_type, self.algorithm) file.write(header) - if self.gateway_type == 0: - pass - elif self.gateway_type == 1: - file.write(dns.ipv4.inet_aton(self.gateway)) - 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, False) - else: - raise ValueError('invalid gateway type') + Gateway(self.gateway_type, self.gateway).to_wire(file, compress, + origin, canonicalize) file.write(self.key) @classmethod @@ -110,23 +79,10 @@ class IPSECKEY(dns.rdata.Rdata): gateway_type = header[1] current += 3 rdlen -= 3 - if gateway_type == 0: - gateway = None - elif gateway_type == 1: - gateway = dns.ipv4.inet_ntoa(wire[current: current + 4]) - current += 4 - rdlen -= 4 - elif gateway_type == 2: - gateway = dns.ipv6.inet_ntoa(wire[current: current + 16]) - current += 16 - rdlen -= 16 - elif gateway_type == 3: - (gateway, cused) = dns.name.from_wire(wire[: current + rdlen], - current) - current += cused - rdlen -= cused - else: - raise dns.exception.FormError('invalid IPSECKEY gateway type') + (gateway, cused) = Gateway(gateway_type).from_wire(wire, current, + rdlen, origin) + current += cused + rdlen -= cused key = wire[current: current + rdlen].unwrap() if origin is not None and gateway_type == 3: gateway = gateway.relativize(origin) diff --git a/dns/rdtypes/__init__.py b/dns/rdtypes/__init__.py index 1ac137f..ccc848c 100644 --- a/dns/rdtypes/__init__.py +++ b/dns/rdtypes/__init__.py @@ -24,4 +24,5 @@ __all__ = [ 'euibase', 'mxbase', 'nsbase', + 'util' ] diff --git a/dns/rdtypes/util.py b/dns/rdtypes/util.py new file mode 100644 index 0000000..5d1f6c9 --- /dev/null +++ b/dns/rdtypes/util.py @@ -0,0 +1,91 @@ +# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license + +# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose with or without fee is hereby granted, +# provided that the above copyright notice and this permission notice +# appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +import dns.exception +import dns.name +import dns.ipv4 +import dns.ipv6 + +class Gateway: + """A helper class for the IPSECKEY gateway and AMTRELAY relay fields""" + name = "" + + def __init__(self, type, gateway=None): + self.type = type + self.gateway = gateway + + def _invalid_type(self): + return f"invalid {self.name} type: {self.type}" + + def check(self): + if self.type == 0: + if self.gateway not in (".", None): + raise SyntaxError(f"invalid {self.name} for type 0") + self.gateway = None + elif self.type == 1: + # check that it's OK + dns.ipv4.inet_aton(self.gateway) + elif self.type == 2: + # check that it's OK + dns.ipv6.inet_aton(self.gateway) + elif self.type == 3: + if not isinstance(self.gateway, dns.name.Name): + raise SyntaxError(f"invalid {self.name}; not a name") + else: + raise SyntaxError(self._invalid_type()) + + def to_text(self, origin=None, relativize=True): + if self.type == 0: + return "." + elif self.type in (1, 2): + return self.gateway + elif self.type == 3: + return str(self.gateway.choose_relativity(origin, relativize)) + else: + raise ValueError(self._invalid_type()) + + def from_text(self, tok, origin=None, relativize=True, relativize_to=None): + if self.type in (0, 1, 2): + return tok.get_string() + elif self.type == 3: + return tok.get_name(origin, relativize, relativize_to) + else: + raise dns.exception.SyntaxError(self._invalid_type()) + + def to_wire(self, file, compress=None, origin=None, canonicalize=False): + if self.type == 0: + pass + elif self.type == 1: + file.write(dns.ipv4.inet_aton(self.gateway)) + elif self.type == 2: + file.write(dns.ipv6.inet_aton(self.gateway)) + elif self.type == 3: + self.gateway.to_wire(file, None, origin, False) + else: + raise ValueError(self._invalid_type()) + + def from_wire(self, wire, current, rdlen, origin=None): + if self.type == 0: + return (None, 0) + elif self.type == 1: + return (dns.ipv4.inet_ntoa(wire[current: current + 4]), 4) + elif self.type == 2: + return (dns.ipv6.inet_ntoa(wire[current: current + 16]), 16) + elif self.type == 3: + return dns.name.from_wire(wire[: current + rdlen], current) + else: + raise dns.exception.FormError(self._invalid_type()) diff --git a/tests/example b/tests/example index c35ba47..2cf5878 100644 --- a/tests/example +++ b/tests/example @@ -225,5 +225,10 @@ LV5eYdPYqfKE+27qjEBARf6PYh/8WQ8CPKS8DILFbwCZbRxUogyrZf/7AiHAGdJi 8dmpR1WPQYef2hF3kqGX6NngLBPzZ6CQRaHBhD4pHU1S/IRSlx9/3Ytww32PYD9A yO732NmCUcq3bmvqcOWy4Cc1NkEwU0Vg0qzwVBNGb84v/ex2MouwtAYScwc= ) +amtrelay01 AMTRELAY 0 0 0 . +amtrelay02 AMTRELAY 0 1 0 . +amtrelay03 AMTRELAY 10 0 1 203.0.113.15 +amtrelay04 AMTRELAY 10 0 2 2001:db8::15 +amtrelay05 AMTRELAY 128 1 3 amtrelays.example.com. csync0 CSYNC 12345 0 A MX RRSIG NSEC TYPE1234 avc01 AVC "app-name:WOLFGANG|app-class:OAM|business=yes" diff --git a/tests/example1.good b/tests/example1.good index a52e55c..beb57af 100644 --- a/tests/example1.good +++ b/tests/example1.good @@ -12,6 +12,11 @@ aaaa01 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff aaaa02 3600 IN AAAA ::1 afsdb01 3600 IN AFSDB 0 hostname afsdb02 3600 IN AFSDB 65535 . +amtrelay01 3600 IN AMTRELAY 0 0 0 . +amtrelay02 3600 IN AMTRELAY 0 1 0 . +amtrelay03 3600 IN AMTRELAY 10 0 1 203.0.113.15 +amtrelay04 3600 IN AMTRELAY 10 0 2 2001:db8::15 +amtrelay05 3600 IN AMTRELAY 128 1 3 amtrelays.example.com. apl01 3600 IN APL 1:192.168.32.0/21 !1:192.168.38.0/28 apl02 3600 IN APL 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8 avc01 3600 IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes" diff --git a/tests/example2.good b/tests/example2.good index df0fed6..75c787c 100644 --- a/tests/example2.good +++ b/tests/example2.good @@ -12,6 +12,11 @@ aaaa01.example. 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff aaaa02.example. 3600 IN AAAA ::1 afsdb01.example. 3600 IN AFSDB 0 hostname.example. afsdb02.example. 3600 IN AFSDB 65535 . +amtrelay01.example. 3600 IN AMTRELAY 0 0 0 . +amtrelay02.example. 3600 IN AMTRELAY 0 1 0 . +amtrelay03.example. 3600 IN AMTRELAY 10 0 1 203.0.113.15 +amtrelay04.example. 3600 IN AMTRELAY 10 0 2 2001:db8::15 +amtrelay05.example. 3600 IN AMTRELAY 128 1 3 amtrelays.example.com. apl01.example. 3600 IN APL 1:192.168.32.0/21 !1:192.168.38.0/28 apl02.example. 3600 IN APL 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8 avc01.example. 3600 IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes" diff --git a/tests/example3.good b/tests/example3.good index a52e55c..beb57af 100644 --- a/tests/example3.good +++ b/tests/example3.good @@ -12,6 +12,11 @@ aaaa01 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff aaaa02 3600 IN AAAA ::1 afsdb01 3600 IN AFSDB 0 hostname afsdb02 3600 IN AFSDB 65535 . +amtrelay01 3600 IN AMTRELAY 0 0 0 . +amtrelay02 3600 IN AMTRELAY 0 1 0 . +amtrelay03 3600 IN AMTRELAY 10 0 1 203.0.113.15 +amtrelay04 3600 IN AMTRELAY 10 0 2 2001:db8::15 +amtrelay05 3600 IN AMTRELAY 128 1 3 amtrelays.example.com. apl01 3600 IN APL 1:192.168.32.0/21 !1:192.168.38.0/28 apl02 3600 IN APL 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8 avc01 3600 IN AVC "app-name:WOLFGANG|app-class:OAM|business=yes" |