summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Wellington <bwelling@xbill.org>2020-07-01 10:32:19 -0700
committerBrian Wellington <bwelling@xbill.org>2020-07-01 10:33:49 -0700
commit7482b94a28dfcd9a98a3518effcec2a6085235d1 (patch)
tree43517d65a18aeff8b1d920f6e75e8ee08f94300e
parent7c0accbb5412d4065446543077ab625daf9749af (diff)
downloaddnspython-7482b94a28dfcd9a98a3518effcec2a6085235d1.tar.gz
Add support for the AMTRELAY type.
-rw-r--r--dns/rdatatype.py1
-rw-r--r--dns/rdtypes/ANY/AMTRELAY.py87
-rw-r--r--dns/rdtypes/IN/IPSECKEY.py74
-rw-r--r--dns/rdtypes/__init__.py1
-rw-r--r--dns/rdtypes/util.py91
-rw-r--r--tests/example5
-rw-r--r--tests/example1.good5
-rw-r--r--tests/example2.good5
-rw-r--r--tests/example3.good5
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"