├── .gitignore ├── README.md ├── dns ├── __init__.py ├── _asyncbackend.py ├── _asyncio_backend.py ├── _curio_backend.py ├── _immutable_ctx.py ├── _trio_backend.py ├── asyncbackend.py ├── asyncquery.py ├── asyncresolver.py ├── dnssec.py ├── dnssectypes.py ├── e164.py ├── edns.py ├── entropy.py ├── enum.py ├── exception.py ├── flags.py ├── grange.py ├── immutable.py ├── inet.py ├── ipv4.py ├── ipv6.py ├── message.py ├── name.py ├── namedict.py ├── node.py ├── opcode.py ├── py.typed ├── query.py ├── quic │ ├── __init__.py │ ├── _asyncio.py │ ├── _common.py │ ├── _sync.py │ └── _trio.py ├── rcode.py ├── rdata.py ├── rdataclass.py ├── rdataset.py ├── rdatatype.py ├── rdtypes │ ├── ANY │ │ ├── AFSDB.py │ │ ├── AMTRELAY.py │ │ ├── AVC.py │ │ ├── CAA.py │ │ ├── CDNSKEY.py │ │ ├── CDS.py │ │ ├── CERT.py │ │ ├── CNAME.py │ │ ├── CSYNC.py │ │ ├── DLV.py │ │ ├── DNAME.py │ │ ├── DNSKEY.py │ │ ├── DS.py │ │ ├── EUI48.py │ │ ├── EUI64.py │ │ ├── GPOS.py │ │ ├── HINFO.py │ │ ├── HIP.py │ │ ├── ISDN.py │ │ ├── L32.py │ │ ├── L64.py │ │ ├── LOC.py │ │ ├── LP.py │ │ ├── MX.py │ │ ├── NID.py │ │ ├── NINFO.py │ │ ├── NS.py │ │ ├── NSEC.py │ │ ├── NSEC3.py │ │ ├── NSEC3PARAM.py │ │ ├── OPENPGPKEY.py │ │ ├── OPT.py │ │ ├── PTR.py │ │ ├── RP.py │ │ ├── RRSIG.py │ │ ├── RT.py │ │ ├── SMIMEA.py │ │ ├── SOA.py │ │ ├── SPF.py │ │ ├── SSHFP.py │ │ ├── TKEY.py │ │ ├── TLSA.py │ │ ├── TSIG.py │ │ ├── TXT.py │ │ ├── URI.py │ │ ├── X25.py │ │ ├── ZONEMD.py │ │ └── __init__.py │ ├── CH │ │ ├── A.py │ │ └── __init__.py │ ├── IN │ │ ├── A.py │ │ ├── AAAA.py │ │ ├── APL.py │ │ ├── DHCID.py │ │ ├── HTTPS.py │ │ ├── IPSECKEY.py │ │ ├── KX.py │ │ ├── NAPTR.py │ │ ├── NSAP.py │ │ ├── NSAP_PTR.py │ │ ├── PX.py │ │ ├── SRV.py │ │ ├── SVCB.py │ │ ├── WKS.py │ │ └── __init__.py │ ├── __init__.py │ ├── dnskeybase.py │ ├── dsbase.py │ ├── euibase.py │ ├── mxbase.py │ ├── nsbase.py │ ├── svcbbase.py │ ├── tlsabase.py │ ├── txtbase.py │ └── util.py ├── renderer.py ├── resolver.py ├── reversename.py ├── rrset.py ├── serial.py ├── set.py ├── tokenizer.py ├── transaction.py ├── tsig.py ├── tsigkeyring.py ├── ttl.py ├── update.py ├── version.py ├── versioned.py ├── win32util.py ├── wire.py ├── xfr.py ├── zone.py ├── zonefile.py └── zonetypes.py ├── lib ├── __init__.py ├── http_proxy_server.py ├── ifaddrs.py ├── proxy_server.py ├── socks5_server.py └── status.py └── socks5.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /dns/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """dnspython DNS toolkit""" 19 | 20 | __all__ = [ 21 | "asyncbackend", 22 | "asyncquery", 23 | "asyncresolver", 24 | "dnssec", 25 | "dnssectypes", 26 | "e164", 27 | "edns", 28 | "entropy", 29 | "exception", 30 | "flags", 31 | "immutable", 32 | "inet", 33 | "ipv4", 34 | "ipv6", 35 | "message", 36 | "name", 37 | "namedict", 38 | "node", 39 | "opcode", 40 | "query", 41 | "quic", 42 | "rcode", 43 | "rdata", 44 | "rdataclass", 45 | "rdataset", 46 | "rdatatype", 47 | "renderer", 48 | "resolver", 49 | "reversename", 50 | "rrset", 51 | "serial", 52 | "set", 53 | "tokenizer", 54 | "transaction", 55 | "tsig", 56 | "tsigkeyring", 57 | "ttl", 58 | "rdtypes", 59 | "update", 60 | "version", 61 | "versioned", 62 | "wire", 63 | "xfr", 64 | "zone", 65 | "zonetypes", 66 | "zonefile", 67 | ] 68 | 69 | from dns.version import version as __version__ # noqa 70 | -------------------------------------------------------------------------------- /dns/_asyncbackend.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # This is a nullcontext for both sync and async. 3.7 has a nullcontext, 4 | # but it is only for sync use. 5 | 6 | 7 | class NullContext: 8 | def __init__(self, enter_result=None): 9 | self.enter_result = enter_result 10 | 11 | def __enter__(self): 12 | return self.enter_result 13 | 14 | def __exit__(self, exc_type, exc_value, traceback): 15 | pass 16 | 17 | async def __aenter__(self): 18 | return self.enter_result 19 | 20 | async def __aexit__(self, exc_type, exc_value, traceback): 21 | pass 22 | 23 | 24 | # These are declared here so backends can import them without creating 25 | # circular dependencies with dns.asyncbackend. 26 | 27 | 28 | class Socket: # pragma: no cover 29 | async def close(self): 30 | pass 31 | 32 | async def getpeername(self): 33 | raise NotImplementedError 34 | 35 | async def getsockname(self): 36 | raise NotImplementedError 37 | 38 | async def __aenter__(self): 39 | return self 40 | 41 | async def __aexit__(self, exc_type, exc_value, traceback): 42 | await self.close() 43 | 44 | 45 | class DatagramSocket(Socket): # pragma: no cover 46 | def __init__(self, family: int): 47 | self.family = family 48 | 49 | async def sendto(self, what, destination, timeout): 50 | raise NotImplementedError 51 | 52 | async def recvfrom(self, size, timeout): 53 | raise NotImplementedError 54 | 55 | 56 | class StreamSocket(Socket): # pragma: no cover 57 | async def sendall(self, what, timeout): 58 | raise NotImplementedError 59 | 60 | async def recv(self, size, timeout): 61 | raise NotImplementedError 62 | 63 | 64 | class Backend: # pragma: no cover 65 | def name(self): 66 | return "unknown" 67 | 68 | async def make_socket( 69 | self, 70 | af, 71 | socktype, 72 | proto=0, 73 | source=None, 74 | destination=None, 75 | timeout=None, 76 | ssl_context=None, 77 | server_hostname=None, 78 | ): 79 | raise NotImplementedError 80 | 81 | def datagram_connection_required(self): 82 | return False 83 | 84 | async def sleep(self, interval): 85 | raise NotImplementedError 86 | -------------------------------------------------------------------------------- /dns/_curio_backend.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | """curio async I/O library query support""" 4 | 5 | import socket 6 | import curio 7 | import curio.socket # type: ignore 8 | 9 | import dns._asyncbackend 10 | import dns.exception 11 | import dns.inet 12 | 13 | 14 | def _maybe_timeout(timeout): 15 | if timeout: 16 | return curio.ignore_after(timeout) 17 | else: 18 | return dns._asyncbackend.NullContext() 19 | 20 | 21 | # for brevity 22 | _lltuple = dns.inet.low_level_address_tuple 23 | 24 | # pylint: disable=redefined-outer-name 25 | 26 | 27 | class DatagramSocket(dns._asyncbackend.DatagramSocket): 28 | def __init__(self, socket): 29 | super().__init__(socket.family) 30 | self.socket = socket 31 | 32 | async def sendto(self, what, destination, timeout): 33 | async with _maybe_timeout(timeout): 34 | return await self.socket.sendto(what, destination) 35 | raise dns.exception.Timeout( 36 | timeout=timeout 37 | ) # pragma: no cover lgtm[py/unreachable-statement] 38 | 39 | async def recvfrom(self, size, timeout): 40 | async with _maybe_timeout(timeout): 41 | return await self.socket.recvfrom(size) 42 | raise dns.exception.Timeout(timeout=timeout) # lgtm[py/unreachable-statement] 43 | 44 | async def close(self): 45 | await self.socket.close() 46 | 47 | async def getpeername(self): 48 | return self.socket.getpeername() 49 | 50 | async def getsockname(self): 51 | return self.socket.getsockname() 52 | 53 | 54 | class StreamSocket(dns._asyncbackend.StreamSocket): 55 | def __init__(self, socket): 56 | self.socket = socket 57 | self.family = socket.family 58 | 59 | async def sendall(self, what, timeout): 60 | async with _maybe_timeout(timeout): 61 | return await self.socket.sendall(what) 62 | raise dns.exception.Timeout(timeout=timeout) # lgtm[py/unreachable-statement] 63 | 64 | async def recv(self, size, timeout): 65 | async with _maybe_timeout(timeout): 66 | return await self.socket.recv(size) 67 | raise dns.exception.Timeout(timeout=timeout) # lgtm[py/unreachable-statement] 68 | 69 | async def close(self): 70 | await self.socket.close() 71 | 72 | async def getpeername(self): 73 | return self.socket.getpeername() 74 | 75 | async def getsockname(self): 76 | return self.socket.getsockname() 77 | 78 | 79 | class Backend(dns._asyncbackend.Backend): 80 | def name(self): 81 | return "curio" 82 | 83 | async def make_socket( 84 | self, 85 | af, 86 | socktype, 87 | proto=0, 88 | source=None, 89 | destination=None, 90 | timeout=None, 91 | ssl_context=None, 92 | server_hostname=None, 93 | ): 94 | if socktype == socket.SOCK_DGRAM: 95 | s = curio.socket.socket(af, socktype, proto) 96 | try: 97 | if source: 98 | s.bind(_lltuple(source, af)) 99 | except Exception: # pragma: no cover 100 | await s.close() 101 | raise 102 | return DatagramSocket(s) 103 | elif socktype == socket.SOCK_STREAM: 104 | if source: 105 | source_addr = _lltuple(source, af) 106 | else: 107 | source_addr = None 108 | async with _maybe_timeout(timeout): 109 | s = await curio.open_connection( 110 | destination[0], 111 | destination[1], 112 | ssl=ssl_context, 113 | source_addr=source_addr, 114 | server_hostname=server_hostname, 115 | ) 116 | return StreamSocket(s) 117 | raise NotImplementedError( 118 | "unsupported socket " + f"type {socktype}" 119 | ) # pragma: no cover 120 | 121 | async def sleep(self, interval): 122 | await curio.sleep(interval) 123 | -------------------------------------------------------------------------------- /dns/_immutable_ctx.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # This implementation of the immutable decorator requires python >= 4 | # 3.7, and is significantly more storage efficient when making classes 5 | # with slots immutable. It's also faster. 6 | 7 | import contextvars 8 | import inspect 9 | 10 | 11 | _in__init__ = contextvars.ContextVar("_immutable_in__init__", default=False) 12 | 13 | 14 | class _Immutable: 15 | """Immutable mixin class""" 16 | 17 | # We set slots to the empty list to say "we don't have any attributes". 18 | # We do this so that if we're mixed in with a class with __slots__, we 19 | # don't cause a __dict__ to be added which would waste space. 20 | 21 | __slots__ = () 22 | 23 | def __setattr__(self, name, value): 24 | if _in__init__.get() is not self: 25 | raise TypeError("object doesn't support attribute assignment") 26 | else: 27 | super().__setattr__(name, value) 28 | 29 | def __delattr__(self, name): 30 | if _in__init__.get() is not self: 31 | raise TypeError("object doesn't support attribute assignment") 32 | else: 33 | super().__delattr__(name) 34 | 35 | 36 | def _immutable_init(f): 37 | def nf(*args, **kwargs): 38 | previous = _in__init__.set(args[0]) 39 | try: 40 | # call the actual __init__ 41 | f(*args, **kwargs) 42 | finally: 43 | _in__init__.reset(previous) 44 | 45 | nf.__signature__ = inspect.signature(f) 46 | return nf 47 | 48 | 49 | def immutable(cls): 50 | if _Immutable in cls.__mro__: 51 | # Some ancestor already has the mixin, so just make sure we keep 52 | # following the __init__ protocol. 53 | cls.__init__ = _immutable_init(cls.__init__) 54 | if hasattr(cls, "__setstate__"): 55 | cls.__setstate__ = _immutable_init(cls.__setstate__) 56 | ncls = cls 57 | else: 58 | # Mixin the Immutable class and follow the __init__ protocol. 59 | class ncls(_Immutable, cls): 60 | # We have to do the __slots__ declaration here too! 61 | __slots__ = () 62 | 63 | @_immutable_init 64 | def __init__(self, *args, **kwargs): 65 | super().__init__(*args, **kwargs) 66 | 67 | if hasattr(cls, "__setstate__"): 68 | 69 | @_immutable_init 70 | def __setstate__(self, *args, **kwargs): 71 | super().__setstate__(*args, **kwargs) 72 | 73 | # make ncls have the same name and module as cls 74 | ncls.__name__ = cls.__name__ 75 | ncls.__qualname__ = cls.__qualname__ 76 | ncls.__module__ = cls.__module__ 77 | return ncls 78 | -------------------------------------------------------------------------------- /dns/_trio_backend.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | """trio async I/O library query support""" 4 | 5 | import socket 6 | import trio 7 | import trio.socket # type: ignore 8 | 9 | import dns._asyncbackend 10 | import dns.exception 11 | import dns.inet 12 | 13 | 14 | def _maybe_timeout(timeout): 15 | if timeout: 16 | return trio.move_on_after(timeout) 17 | else: 18 | return dns._asyncbackend.NullContext() 19 | 20 | 21 | # for brevity 22 | _lltuple = dns.inet.low_level_address_tuple 23 | 24 | # pylint: disable=redefined-outer-name 25 | 26 | 27 | class DatagramSocket(dns._asyncbackend.DatagramSocket): 28 | def __init__(self, socket): 29 | super().__init__(socket.family) 30 | self.socket = socket 31 | 32 | async def sendto(self, what, destination, timeout): 33 | with _maybe_timeout(timeout): 34 | return await self.socket.sendto(what, destination) 35 | raise dns.exception.Timeout( 36 | timeout=timeout 37 | ) # pragma: no cover lgtm[py/unreachable-statement] 38 | 39 | async def recvfrom(self, size, timeout): 40 | with _maybe_timeout(timeout): 41 | return await self.socket.recvfrom(size) 42 | raise dns.exception.Timeout(timeout=timeout) # lgtm[py/unreachable-statement] 43 | 44 | async def close(self): 45 | self.socket.close() 46 | 47 | async def getpeername(self): 48 | return self.socket.getpeername() 49 | 50 | async def getsockname(self): 51 | return self.socket.getsockname() 52 | 53 | 54 | class StreamSocket(dns._asyncbackend.StreamSocket): 55 | def __init__(self, family, stream, tls=False): 56 | self.family = family 57 | self.stream = stream 58 | self.tls = tls 59 | 60 | async def sendall(self, what, timeout): 61 | with _maybe_timeout(timeout): 62 | return await self.stream.send_all(what) 63 | raise dns.exception.Timeout(timeout=timeout) # lgtm[py/unreachable-statement] 64 | 65 | async def recv(self, size, timeout): 66 | with _maybe_timeout(timeout): 67 | return await self.stream.receive_some(size) 68 | raise dns.exception.Timeout(timeout=timeout) # lgtm[py/unreachable-statement] 69 | 70 | async def close(self): 71 | await self.stream.aclose() 72 | 73 | async def getpeername(self): 74 | if self.tls: 75 | return self.stream.transport_stream.socket.getpeername() 76 | else: 77 | return self.stream.socket.getpeername() 78 | 79 | async def getsockname(self): 80 | if self.tls: 81 | return self.stream.transport_stream.socket.getsockname() 82 | else: 83 | return self.stream.socket.getsockname() 84 | 85 | 86 | class Backend(dns._asyncbackend.Backend): 87 | def name(self): 88 | return "trio" 89 | 90 | async def make_socket( 91 | self, 92 | af, 93 | socktype, 94 | proto=0, 95 | source=None, 96 | destination=None, 97 | timeout=None, 98 | ssl_context=None, 99 | server_hostname=None, 100 | ): 101 | s = trio.socket.socket(af, socktype, proto) 102 | stream = None 103 | try: 104 | if source: 105 | await s.bind(_lltuple(source, af)) 106 | if socktype == socket.SOCK_STREAM: 107 | with _maybe_timeout(timeout): 108 | await s.connect(_lltuple(destination, af)) 109 | except Exception: # pragma: no cover 110 | s.close() 111 | raise 112 | if socktype == socket.SOCK_DGRAM: 113 | return DatagramSocket(s) 114 | elif socktype == socket.SOCK_STREAM: 115 | stream = trio.SocketStream(s) 116 | tls = False 117 | if ssl_context: 118 | tls = True 119 | try: 120 | stream = trio.SSLStream( 121 | stream, ssl_context, server_hostname=server_hostname 122 | ) 123 | except Exception: # pragma: no cover 124 | await stream.aclose() 125 | raise 126 | return StreamSocket(af, stream, tls) 127 | raise NotImplementedError( 128 | "unsupported socket " + f"type {socktype}" 129 | ) # pragma: no cover 130 | 131 | async def sleep(self, interval): 132 | await trio.sleep(interval) 133 | -------------------------------------------------------------------------------- /dns/asyncbackend.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | from typing import Dict 4 | 5 | import dns.exception 6 | 7 | # pylint: disable=unused-import 8 | 9 | from dns._asyncbackend import ( 10 | Socket, 11 | DatagramSocket, 12 | StreamSocket, 13 | Backend, 14 | ) # noqa: F401 lgtm[py/unused-import] 15 | 16 | # pylint: enable=unused-import 17 | 18 | _default_backend = None 19 | 20 | _backends: Dict[str, Backend] = {} 21 | 22 | # Allow sniffio import to be disabled for testing purposes 23 | _no_sniffio = False 24 | 25 | 26 | class AsyncLibraryNotFoundError(dns.exception.DNSException): 27 | pass 28 | 29 | 30 | def get_backend(name: str) -> Backend: 31 | """Get the specified asynchronous backend. 32 | 33 | *name*, a ``str``, the name of the backend. Currently the "trio", 34 | "curio", and "asyncio" backends are available. 35 | 36 | Raises NotImplementError if an unknown backend name is specified. 37 | """ 38 | # pylint: disable=import-outside-toplevel,redefined-outer-name 39 | backend = _backends.get(name) 40 | if backend: 41 | return backend 42 | if name == "trio": 43 | import dns._trio_backend 44 | 45 | backend = dns._trio_backend.Backend() 46 | elif name == "curio": 47 | import dns._curio_backend 48 | 49 | backend = dns._curio_backend.Backend() 50 | elif name == "asyncio": 51 | import dns._asyncio_backend 52 | 53 | backend = dns._asyncio_backend.Backend() 54 | else: 55 | raise NotImplementedError(f"unimplemented async backend {name}") 56 | _backends[name] = backend 57 | return backend 58 | 59 | 60 | def sniff() -> str: 61 | """Attempt to determine the in-use asynchronous I/O library by using 62 | the ``sniffio`` module if it is available. 63 | 64 | Returns the name of the library, or raises AsyncLibraryNotFoundError 65 | if the library cannot be determined. 66 | """ 67 | # pylint: disable=import-outside-toplevel 68 | try: 69 | if _no_sniffio: 70 | raise ImportError 71 | import sniffio 72 | 73 | try: 74 | return sniffio.current_async_library() 75 | except sniffio.AsyncLibraryNotFoundError: 76 | raise AsyncLibraryNotFoundError( 77 | "sniffio cannot determine " + "async library" 78 | ) 79 | except ImportError: 80 | import asyncio 81 | 82 | try: 83 | asyncio.get_running_loop() 84 | return "asyncio" 85 | except RuntimeError: 86 | raise AsyncLibraryNotFoundError("no async library detected") 87 | 88 | 89 | def get_default_backend() -> Backend: 90 | """Get the default backend, initializing it if necessary.""" 91 | if _default_backend: 92 | return _default_backend 93 | 94 | return set_default_backend(sniff()) 95 | 96 | 97 | def set_default_backend(name: str) -> Backend: 98 | """Set the default backend. 99 | 100 | It's not normally necessary to call this method, as 101 | ``get_default_backend()`` will initialize the backend 102 | appropriately in many cases. If ``sniffio`` is not installed, or 103 | in testing situations, this function allows the backend to be set 104 | explicitly. 105 | """ 106 | global _default_backend 107 | _default_backend = get_backend(name) 108 | return _default_backend 109 | -------------------------------------------------------------------------------- /dns/dnssectypes.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """Common DNSSEC-related types.""" 19 | 20 | # This is a separate file to avoid import circularity between dns.dnssec and 21 | # the implementations of the DS and DNSKEY types. 22 | 23 | import dns.enum 24 | 25 | 26 | class Algorithm(dns.enum.IntEnum): 27 | RSAMD5 = 1 28 | DH = 2 29 | DSA = 3 30 | ECC = 4 31 | RSASHA1 = 5 32 | DSANSEC3SHA1 = 6 33 | RSASHA1NSEC3SHA1 = 7 34 | RSASHA256 = 8 35 | RSASHA512 = 10 36 | ECCGOST = 12 37 | ECDSAP256SHA256 = 13 38 | ECDSAP384SHA384 = 14 39 | ED25519 = 15 40 | ED448 = 16 41 | INDIRECT = 252 42 | PRIVATEDNS = 253 43 | PRIVATEOID = 254 44 | 45 | @classmethod 46 | def _maximum(cls): 47 | return 255 48 | 49 | 50 | class DSDigest(dns.enum.IntEnum): 51 | """DNSSEC Delegation Signer Digest Algorithm""" 52 | 53 | NULL = 0 54 | SHA1 = 1 55 | SHA256 = 2 56 | GOST = 3 57 | SHA384 = 4 58 | 59 | @classmethod 60 | def _maximum(cls): 61 | return 255 62 | 63 | 64 | class NSEC3Hash(dns.enum.IntEnum): 65 | """NSEC3 hash algorithm""" 66 | 67 | SHA1 = 1 68 | 69 | @classmethod 70 | def _maximum(cls): 71 | return 255 72 | -------------------------------------------------------------------------------- /dns/e164.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2006-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """DNS E.164 helpers.""" 19 | 20 | from typing import Iterable, Optional, Union 21 | 22 | import dns.exception 23 | import dns.name 24 | import dns.resolver 25 | 26 | #: The public E.164 domain. 27 | public_enum_domain = dns.name.from_text("e164.arpa.") 28 | 29 | 30 | def from_e164( 31 | text: str, origin: Optional[dns.name.Name] = public_enum_domain 32 | ) -> dns.name.Name: 33 | """Convert an E.164 number in textual form into a Name object whose 34 | value is the ENUM domain name for that number. 35 | 36 | Non-digits in the text are ignored, i.e. "16505551212", 37 | "+1.650.555.1212" and "1 (650) 555-1212" are all the same. 38 | 39 | *text*, a ``str``, is an E.164 number in textual form. 40 | 41 | *origin*, a ``dns.name.Name``, the domain in which the number 42 | should be constructed. The default is ``e164.arpa.``. 43 | 44 | Returns a ``dns.name.Name``. 45 | """ 46 | 47 | parts = [d for d in text if d.isdigit()] 48 | parts.reverse() 49 | return dns.name.from_text(".".join(parts), origin=origin) 50 | 51 | 52 | def to_e164( 53 | name: dns.name.Name, 54 | origin: Optional[dns.name.Name] = public_enum_domain, 55 | want_plus_prefix: bool = True, 56 | ) -> str: 57 | """Convert an ENUM domain name into an E.164 number. 58 | 59 | Note that dnspython does not have any information about preferred 60 | number formats within national numbering plans, so all numbers are 61 | emitted as a simple string of digits, prefixed by a '+' (unless 62 | *want_plus_prefix* is ``False``). 63 | 64 | *name* is a ``dns.name.Name``, the ENUM domain name. 65 | 66 | *origin* is a ``dns.name.Name``, a domain containing the ENUM 67 | domain name. The name is relativized to this domain before being 68 | converted to text. If ``None``, no relativization is done. 69 | 70 | *want_plus_prefix* is a ``bool``. If True, add a '+' to the beginning of 71 | the returned number. 72 | 73 | Returns a ``str``. 74 | 75 | """ 76 | if origin is not None: 77 | name = name.relativize(origin) 78 | dlabels = [d for d in name.labels if d.isdigit() and len(d) == 1] 79 | if len(dlabels) != len(name.labels): 80 | raise dns.exception.SyntaxError("non-digit labels in ENUM domain name") 81 | dlabels.reverse() 82 | text = b"".join(dlabels) 83 | if want_plus_prefix: 84 | text = b"+" + text 85 | return text.decode() 86 | 87 | 88 | def query( 89 | number: str, 90 | domains: Iterable[Union[dns.name.Name, str]], 91 | resolver: Optional[dns.resolver.Resolver] = None, 92 | ) -> dns.resolver.Answer: 93 | """Look for NAPTR RRs for the specified number in the specified domains. 94 | 95 | e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.']) 96 | 97 | *number*, a ``str`` is the number to look for. 98 | 99 | *domains* is an iterable containing ``dns.name.Name`` values. 100 | 101 | *resolver*, a ``dns.resolver.Resolver``, is the resolver to use. If 102 | ``None``, the default resolver is used. 103 | """ 104 | 105 | if resolver is None: 106 | resolver = dns.resolver.get_default_resolver() 107 | e_nx = dns.resolver.NXDOMAIN() 108 | for domain in domains: 109 | if isinstance(domain, str): 110 | domain = dns.name.from_text(domain) 111 | qname = dns.e164.from_e164(number, domain) 112 | try: 113 | return resolver.resolve(qname, "NAPTR") 114 | except dns.resolver.NXDOMAIN as e: 115 | e_nx += e 116 | raise e_nx 117 | -------------------------------------------------------------------------------- /dns/enum.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import enum 19 | 20 | 21 | class IntEnum(enum.IntEnum): 22 | @classmethod 23 | def _check_value(cls, value): 24 | max = cls._maximum() 25 | if value < 0 or value > max: 26 | name = cls._short_name() 27 | raise ValueError(f"{name} must be between >= 0 and <= {max}") 28 | 29 | @classmethod 30 | def from_text(cls, text): 31 | text = text.upper() 32 | try: 33 | return cls[text] 34 | except KeyError: 35 | pass 36 | value = cls._extra_from_text(text) 37 | if value: 38 | return value 39 | prefix = cls._prefix() 40 | if text.startswith(prefix) and text[len(prefix) :].isdigit(): 41 | value = int(text[len(prefix) :]) 42 | cls._check_value(value) 43 | try: 44 | return cls(value) 45 | except ValueError: 46 | return value 47 | raise cls._unknown_exception_class() 48 | 49 | @classmethod 50 | def to_text(cls, value): 51 | cls._check_value(value) 52 | try: 53 | text = cls(value).name 54 | except ValueError: 55 | text = None 56 | text = cls._extra_to_text(value, text) 57 | if text is None: 58 | text = f"{cls._prefix()}{value}" 59 | return text 60 | 61 | @classmethod 62 | def make(cls, value): 63 | """Convert text or a value into an enumerated type, if possible. 64 | 65 | *value*, the ``int`` or ``str`` to convert. 66 | 67 | Raises a class-specific exception if a ``str`` is provided that 68 | cannot be converted. 69 | 70 | Raises ``ValueError`` if the value is out of range. 71 | 72 | Returns an enumeration from the calling class corresponding to the 73 | value, if one is defined, or an ``int`` otherwise. 74 | """ 75 | 76 | if isinstance(value, str): 77 | return cls.from_text(value) 78 | cls._check_value(value) 79 | try: 80 | return cls(value) 81 | except ValueError: 82 | return value 83 | 84 | @classmethod 85 | def _maximum(cls): 86 | raise NotImplementedError # pragma: no cover 87 | 88 | @classmethod 89 | def _short_name(cls): 90 | return cls.__name__.lower() 91 | 92 | @classmethod 93 | def _prefix(cls): 94 | return "" 95 | 96 | @classmethod 97 | def _extra_from_text(cls, text): # pylint: disable=W0613 98 | return None 99 | 100 | @classmethod 101 | def _extra_to_text(cls, value, current_text): # pylint: disable=W0613 102 | return current_text 103 | 104 | @classmethod 105 | def _unknown_exception_class(cls): 106 | return ValueError 107 | -------------------------------------------------------------------------------- /dns/flags.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2001-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """DNS Message Flags.""" 19 | 20 | from typing import Any 21 | 22 | import enum 23 | 24 | # Standard DNS flags 25 | 26 | 27 | class Flag(enum.IntFlag): 28 | #: Query Response 29 | QR = 0x8000 30 | #: Authoritative Answer 31 | AA = 0x0400 32 | #: Truncated Response 33 | TC = 0x0200 34 | #: Recursion Desired 35 | RD = 0x0100 36 | #: Recursion Available 37 | RA = 0x0080 38 | #: Authentic Data 39 | AD = 0x0020 40 | #: Checking Disabled 41 | CD = 0x0010 42 | 43 | 44 | # EDNS flags 45 | 46 | 47 | class EDNSFlag(enum.IntFlag): 48 | #: DNSSEC answer OK 49 | DO = 0x8000 50 | 51 | 52 | def _from_text(text: str, enum_class: Any) -> int: 53 | flags = 0 54 | tokens = text.split() 55 | for t in tokens: 56 | flags |= enum_class[t.upper()] 57 | return flags 58 | 59 | 60 | def _to_text(flags: int, enum_class: Any) -> str: 61 | text_flags = [] 62 | for k, v in enum_class.__members__.items(): 63 | if flags & v != 0: 64 | text_flags.append(k) 65 | return " ".join(text_flags) 66 | 67 | 68 | def from_text(text: str) -> int: 69 | """Convert a space-separated list of flag text values into a flags 70 | value. 71 | 72 | Returns an ``int`` 73 | """ 74 | 75 | return _from_text(text, Flag) 76 | 77 | 78 | def to_text(flags: int) -> str: 79 | """Convert a flags value into a space-separated list of flag text 80 | values. 81 | 82 | Returns a ``str``. 83 | """ 84 | 85 | return _to_text(flags, Flag) 86 | 87 | 88 | def edns_from_text(text: str) -> int: 89 | """Convert a space-separated list of EDNS flag text values into a EDNS 90 | flags value. 91 | 92 | Returns an ``int`` 93 | """ 94 | 95 | return _from_text(text, EDNSFlag) 96 | 97 | 98 | def edns_to_text(flags: int) -> str: 99 | """Convert an EDNS flags value into a space-separated list of EDNS flag 100 | text values. 101 | 102 | Returns a ``str``. 103 | """ 104 | 105 | return _to_text(flags, EDNSFlag) 106 | 107 | 108 | ### BEGIN generated Flag constants 109 | 110 | QR = Flag.QR 111 | AA = Flag.AA 112 | TC = Flag.TC 113 | RD = Flag.RD 114 | RA = Flag.RA 115 | AD = Flag.AD 116 | CD = Flag.CD 117 | 118 | ### END generated Flag constants 119 | 120 | ### BEGIN generated EDNSFlag constants 121 | 122 | DO = EDNSFlag.DO 123 | 124 | ### END generated EDNSFlag constants 125 | -------------------------------------------------------------------------------- /dns/grange.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2012-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """DNS GENERATE range conversion.""" 19 | 20 | from typing import Tuple 21 | 22 | import dns 23 | 24 | 25 | def from_text(text: str) -> Tuple[int, int, int]: 26 | """Convert the text form of a range in a ``$GENERATE`` statement to an 27 | integer. 28 | 29 | *text*, a ``str``, the textual range in ``$GENERATE`` form. 30 | 31 | Returns a tuple of three ``int`` values ``(start, stop, step)``. 32 | """ 33 | 34 | start = -1 35 | stop = -1 36 | step = 1 37 | cur = "" 38 | state = 0 39 | # state 0 1 2 40 | # x - y / z 41 | 42 | if text and text[0] == "-": 43 | raise dns.exception.SyntaxError("Start cannot be a negative number") 44 | 45 | for c in text: 46 | if c == "-" and state == 0: 47 | start = int(cur) 48 | cur = "" 49 | state = 1 50 | elif c == "/": 51 | stop = int(cur) 52 | cur = "" 53 | state = 2 54 | elif c.isdigit(): 55 | cur += c 56 | else: 57 | raise dns.exception.SyntaxError("Could not parse %s" % (c)) 58 | 59 | if state == 0: 60 | raise dns.exception.SyntaxError("no stop value specified") 61 | elif state == 1: 62 | stop = int(cur) 63 | else: 64 | assert state == 2 65 | step = int(cur) 66 | 67 | assert step >= 1 68 | assert start >= 0 69 | if start > stop: 70 | raise dns.exception.SyntaxError("start must be <= stop") 71 | 72 | return (start, stop, step) 73 | -------------------------------------------------------------------------------- /dns/immutable.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | from typing import Any 4 | 5 | import collections.abc 6 | 7 | from dns._immutable_ctx import immutable 8 | 9 | 10 | @immutable 11 | class Dict(collections.abc.Mapping): # lgtm[py/missing-equals] 12 | def __init__(self, dictionary: Any, no_copy: bool = False): 13 | """Make an immutable dictionary from the specified dictionary. 14 | 15 | If *no_copy* is `True`, then *dictionary* will be wrapped instead 16 | of copied. Only set this if you are sure there will be no external 17 | references to the dictionary. 18 | """ 19 | if no_copy and isinstance(dictionary, dict): 20 | self._odict = dictionary 21 | else: 22 | self._odict = dict(dictionary) 23 | self._hash = None 24 | 25 | def __getitem__(self, key): 26 | return self._odict.__getitem__(key) 27 | 28 | def __hash__(self): # pylint: disable=invalid-hash-returned 29 | if self._hash is None: 30 | h = 0 31 | for key in sorted(self._odict.keys()): 32 | h ^= hash(key) 33 | object.__setattr__(self, "_hash", h) 34 | # this does return an int, but pylint doesn't figure that out 35 | return self._hash 36 | 37 | def __len__(self): 38 | return len(self._odict) 39 | 40 | def __iter__(self): 41 | return iter(self._odict) 42 | 43 | 44 | def constify(o: Any) -> Any: 45 | """ 46 | Convert mutable types to immutable types. 47 | """ 48 | if isinstance(o, bytearray): 49 | return bytes(o) 50 | if isinstance(o, tuple): 51 | try: 52 | hash(o) 53 | return o 54 | except Exception: 55 | return tuple(constify(elt) for elt in o) 56 | if isinstance(o, list): 57 | return tuple(constify(elt) for elt in o) 58 | if isinstance(o, dict): 59 | cdict = dict() 60 | for k, v in o.items(): 61 | cdict[k] = constify(v) 62 | return Dict(cdict, True) 63 | return o 64 | -------------------------------------------------------------------------------- /dns/ipv4.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """IPv4 helper functions.""" 19 | 20 | from typing import Union 21 | 22 | import struct 23 | 24 | import dns.exception 25 | 26 | 27 | def inet_ntoa(address: bytes) -> str: 28 | """Convert an IPv4 address in binary form to text form. 29 | 30 | *address*, a ``bytes``, the IPv4 address in binary form. 31 | 32 | Returns a ``str``. 33 | """ 34 | 35 | if len(address) != 4: 36 | raise dns.exception.SyntaxError 37 | return "%u.%u.%u.%u" % (address[0], address[1], address[2], address[3]) 38 | 39 | 40 | def inet_aton(text: Union[str, bytes]) -> bytes: 41 | """Convert an IPv4 address in text form to binary form. 42 | 43 | *text*, a ``str`` or ``bytes``, the IPv4 address in textual form. 44 | 45 | Returns a ``bytes``. 46 | """ 47 | 48 | if not isinstance(text, bytes): 49 | btext = text.encode() 50 | else: 51 | btext = text 52 | parts = btext.split(b".") 53 | if len(parts) != 4: 54 | raise dns.exception.SyntaxError 55 | for part in parts: 56 | if not part.isdigit(): 57 | raise dns.exception.SyntaxError 58 | if len(part) > 1 and part[0] == ord("0"): 59 | # No leading zeros 60 | raise dns.exception.SyntaxError 61 | try: 62 | b = [int(part) for part in parts] 63 | return struct.pack("BBBB", *b) 64 | except Exception: 65 | raise dns.exception.SyntaxError 66 | -------------------------------------------------------------------------------- /dns/namedict.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2017 Nominum, Inc. 4 | # Copyright (C) 2016 Coresec Systems AB 5 | # 6 | # Permission to use, copy, modify, and distribute this software and its 7 | # documentation for any purpose with or without fee is hereby granted, 8 | # provided that the above copyright notice and this permission notice 9 | # appear in all copies. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 12 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 14 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS" AND CORESEC SYSTEMS AB DISCLAIMS ALL 20 | # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 21 | # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CORESEC 22 | # SYSTEMS AB BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 23 | # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 24 | # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 25 | # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 26 | # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 27 | 28 | """DNS name dictionary""" 29 | 30 | # pylint seems to be confused about this one! 31 | from collections.abc import MutableMapping # pylint: disable=no-name-in-module 32 | 33 | import dns.name 34 | 35 | 36 | class NameDict(MutableMapping): 37 | """A dictionary whose keys are dns.name.Name objects. 38 | 39 | In addition to being like a regular Python dictionary, this 40 | dictionary can also get the deepest match for a given key. 41 | """ 42 | 43 | __slots__ = ["max_depth", "max_depth_items", "__store"] 44 | 45 | def __init__(self, *args, **kwargs): 46 | super().__init__() 47 | self.__store = dict() 48 | #: the maximum depth of the keys that have ever been added 49 | self.max_depth = 0 50 | #: the number of items of maximum depth 51 | self.max_depth_items = 0 52 | self.update(dict(*args, **kwargs)) 53 | 54 | def __update_max_depth(self, key): 55 | if len(key) == self.max_depth: 56 | self.max_depth_items = self.max_depth_items + 1 57 | elif len(key) > self.max_depth: 58 | self.max_depth = len(key) 59 | self.max_depth_items = 1 60 | 61 | def __getitem__(self, key): 62 | return self.__store[key] 63 | 64 | def __setitem__(self, key, value): 65 | if not isinstance(key, dns.name.Name): 66 | raise ValueError("NameDict key must be a name") 67 | self.__store[key] = value 68 | self.__update_max_depth(key) 69 | 70 | def __delitem__(self, key): 71 | self.__store.pop(key) 72 | if len(key) == self.max_depth: 73 | self.max_depth_items = self.max_depth_items - 1 74 | if self.max_depth_items == 0: 75 | self.max_depth = 0 76 | for k in self.__store: 77 | self.__update_max_depth(k) 78 | 79 | def __iter__(self): 80 | return iter(self.__store) 81 | 82 | def __len__(self): 83 | return len(self.__store) 84 | 85 | def has_key(self, key): 86 | return key in self.__store 87 | 88 | def get_deepest_match(self, name): 89 | """Find the deepest match to *name* in the dictionary. 90 | 91 | The deepest match is the longest name in the dictionary which is 92 | a superdomain of *name*. Note that *superdomain* includes matching 93 | *name* itself. 94 | 95 | *name*, a ``dns.name.Name``, the name to find. 96 | 97 | Returns a ``(key, value)`` where *key* is the deepest 98 | ``dns.name.Name``, and *value* is the value associated with *key*. 99 | """ 100 | 101 | depth = len(name) 102 | if depth > self.max_depth: 103 | depth = self.max_depth 104 | for i in range(-depth, 0): 105 | n = dns.name.Name(name[i:]) 106 | if n in self: 107 | return (n, self[n]) 108 | v = self[dns.name.empty] 109 | return (dns.name.empty, v) 110 | -------------------------------------------------------------------------------- /dns/opcode.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2001-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """DNS Opcodes.""" 19 | 20 | import dns.enum 21 | import dns.exception 22 | 23 | 24 | class Opcode(dns.enum.IntEnum): 25 | #: Query 26 | QUERY = 0 27 | #: Inverse Query (historical) 28 | IQUERY = 1 29 | #: Server Status (unspecified and unimplemented anywhere) 30 | STATUS = 2 31 | #: Notify 32 | NOTIFY = 4 33 | #: Dynamic Update 34 | UPDATE = 5 35 | 36 | @classmethod 37 | def _maximum(cls): 38 | return 15 39 | 40 | @classmethod 41 | def _unknown_exception_class(cls): 42 | return UnknownOpcode 43 | 44 | 45 | class UnknownOpcode(dns.exception.DNSException): 46 | """An DNS opcode is unknown.""" 47 | 48 | 49 | def from_text(text: str) -> Opcode: 50 | """Convert text into an opcode. 51 | 52 | *text*, a ``str``, the textual opcode 53 | 54 | Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown. 55 | 56 | Returns an ``int``. 57 | """ 58 | 59 | return Opcode.from_text(text) 60 | 61 | 62 | def from_flags(flags: int) -> Opcode: 63 | """Extract an opcode from DNS message flags. 64 | 65 | *flags*, an ``int``, the DNS flags. 66 | 67 | Returns an ``int``. 68 | """ 69 | 70 | return Opcode((flags & 0x7800) >> 11) 71 | 72 | 73 | def to_flags(value: Opcode) -> int: 74 | """Convert an opcode to a value suitable for ORing into DNS message 75 | flags. 76 | 77 | *value*, an ``int``, the DNS opcode value. 78 | 79 | Returns an ``int``. 80 | """ 81 | 82 | return (value << 11) & 0x7800 83 | 84 | 85 | def to_text(value: Opcode) -> str: 86 | """Convert an opcode to text. 87 | 88 | *value*, an ``int`` the opcode value, 89 | 90 | Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown. 91 | 92 | Returns a ``str``. 93 | """ 94 | 95 | return Opcode.to_text(value) 96 | 97 | 98 | def is_update(flags: int) -> bool: 99 | """Is the opcode in flags UPDATE? 100 | 101 | *flags*, an ``int``, the DNS message flags. 102 | 103 | Returns a ``bool``. 104 | """ 105 | 106 | return from_flags(flags) == Opcode.UPDATE 107 | 108 | 109 | ### BEGIN generated Opcode constants 110 | 111 | QUERY = Opcode.QUERY 112 | IQUERY = Opcode.IQUERY 113 | STATUS = Opcode.STATUS 114 | NOTIFY = Opcode.NOTIFY 115 | UPDATE = Opcode.UPDATE 116 | 117 | ### END generated Opcode constants 118 | -------------------------------------------------------------------------------- /dns/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nneonneo/iOS-SOCKS-Server/e8722f91418e9c0897adbb2041d7cc214ed82738/dns/py.typed -------------------------------------------------------------------------------- /dns/quic/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | try: 4 | import aioquic.quic.configuration # type: ignore 5 | 6 | import dns.asyncbackend 7 | from dns._asyncbackend import NullContext 8 | from dns.quic._sync import SyncQuicManager, SyncQuicConnection, SyncQuicStream 9 | from dns.quic._asyncio import ( 10 | AsyncioQuicManager, 11 | AsyncioQuicConnection, 12 | AsyncioQuicStream, 13 | ) 14 | from dns.quic._common import AsyncQuicConnection, AsyncQuicManager 15 | 16 | have_quic = True 17 | 18 | def null_factory( 19 | *args, # pylint: disable=unused-argument 20 | **kwargs # pylint: disable=unused-argument 21 | ): 22 | return NullContext(None) 23 | 24 | def _asyncio_manager_factory( 25 | context, *args, **kwargs # pylint: disable=unused-argument 26 | ): 27 | return AsyncioQuicManager(*args, **kwargs) 28 | 29 | # We have a context factory and a manager factory as for trio we need to have 30 | # a nursery. 31 | 32 | _async_factories = {"asyncio": (null_factory, _asyncio_manager_factory)} 33 | 34 | try: 35 | import trio 36 | from dns.quic._trio import ( # pylint: disable=ungrouped-imports 37 | TrioQuicManager, 38 | TrioQuicConnection, 39 | TrioQuicStream, 40 | ) 41 | 42 | def _trio_context_factory(): 43 | return trio.open_nursery() 44 | 45 | def _trio_manager_factory(context, *args, **kwargs): 46 | return TrioQuicManager(context, *args, **kwargs) 47 | 48 | _async_factories["trio"] = (_trio_context_factory, _trio_manager_factory) 49 | except ImportError: 50 | pass 51 | 52 | def factories_for_backend(backend=None): 53 | if backend is None: 54 | backend = dns.asyncbackend.get_default_backend() 55 | return _async_factories[backend.name()] 56 | 57 | except ImportError: 58 | have_quic = False 59 | 60 | from typing import Any 61 | 62 | class AsyncQuicStream: # type: ignore 63 | pass 64 | 65 | class AsyncQuicConnection: # type: ignore 66 | async def make_stream(self) -> Any: 67 | raise NotImplementedError 68 | 69 | class SyncQuicStream: # type: ignore 70 | pass 71 | 72 | class SyncQuicConnection: # type: ignore 73 | def make_stream(self) -> Any: 74 | raise NotImplementedError 75 | -------------------------------------------------------------------------------- /dns/rdataclass.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2001-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """DNS Rdata Classes.""" 19 | 20 | import dns.enum 21 | import dns.exception 22 | 23 | 24 | class RdataClass(dns.enum.IntEnum): 25 | """DNS Rdata Class""" 26 | 27 | RESERVED0 = 0 28 | IN = 1 29 | INTERNET = IN 30 | CH = 3 31 | CHAOS = CH 32 | HS = 4 33 | HESIOD = HS 34 | NONE = 254 35 | ANY = 255 36 | 37 | @classmethod 38 | def _maximum(cls): 39 | return 65535 40 | 41 | @classmethod 42 | def _short_name(cls): 43 | return "class" 44 | 45 | @classmethod 46 | def _prefix(cls): 47 | return "CLASS" 48 | 49 | @classmethod 50 | def _unknown_exception_class(cls): 51 | return UnknownRdataclass 52 | 53 | 54 | _metaclasses = {RdataClass.NONE, RdataClass.ANY} 55 | 56 | 57 | class UnknownRdataclass(dns.exception.DNSException): 58 | """A DNS class is unknown.""" 59 | 60 | 61 | def from_text(text: str) -> RdataClass: 62 | """Convert text into a DNS rdata class value. 63 | 64 | The input text can be a defined DNS RR class mnemonic or 65 | instance of the DNS generic class syntax. 66 | 67 | For example, "IN" and "CLASS1" will both result in a value of 1. 68 | 69 | Raises ``dns.rdatatype.UnknownRdataclass`` if the class is unknown. 70 | 71 | Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535. 72 | 73 | Returns a ``dns.rdataclass.RdataClass``. 74 | """ 75 | 76 | return RdataClass.from_text(text) 77 | 78 | 79 | def to_text(value: RdataClass) -> str: 80 | """Convert a DNS rdata class value to text. 81 | 82 | If the value has a known mnemonic, it will be used, otherwise the 83 | DNS generic class syntax will be used. 84 | 85 | Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535. 86 | 87 | Returns a ``str``. 88 | """ 89 | 90 | return RdataClass.to_text(value) 91 | 92 | 93 | def is_metaclass(rdclass: RdataClass) -> bool: 94 | """True if the specified class is a metaclass. 95 | 96 | The currently defined metaclasses are ANY and NONE. 97 | 98 | *rdclass* is a ``dns.rdataclass.RdataClass``. 99 | """ 100 | 101 | if rdclass in _metaclasses: 102 | return True 103 | return False 104 | 105 | 106 | ### BEGIN generated RdataClass constants 107 | 108 | RESERVED0 = RdataClass.RESERVED0 109 | IN = RdataClass.IN 110 | INTERNET = RdataClass.INTERNET 111 | CH = RdataClass.CH 112 | CHAOS = RdataClass.CHAOS 113 | HS = RdataClass.HS 114 | HESIOD = RdataClass.HESIOD 115 | NONE = RdataClass.NONE 116 | ANY = RdataClass.ANY 117 | 118 | ### END generated RdataClass constants 119 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/AFSDB.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.mxbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class AFSDB(dns.rdtypes.mxbase.UncompressedDowncasingMX): 24 | 25 | """AFSDB record""" 26 | 27 | # Use the property mechanism to make "subtype" an alias for the 28 | # "preference" attribute, and "hostname" an alias for the "exchange" 29 | # attribute. 30 | # 31 | # This lets us inherit the UncompressedMX implementation but lets 32 | # the caller use appropriate attribute names for the rdata type. 33 | # 34 | # We probably lose some performance vs. a cut-and-paste 35 | # implementation, but this way we don't copy code, and that's 36 | # good. 37 | 38 | @property 39 | def subtype(self): 40 | "the AFSDB subtype" 41 | return self.preference 42 | 43 | @property 44 | def hostname(self): 45 | "the AFSDB hostname" 46 | return self.exchange 47 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/AMTRELAY.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdtypes.util 23 | 24 | 25 | class Relay(dns.rdtypes.util.Gateway): 26 | name = "AMTRELAY relay" 27 | 28 | @property 29 | def relay(self): 30 | return self.gateway 31 | 32 | 33 | @dns.immutable.immutable 34 | class AMTRELAY(dns.rdata.Rdata): 35 | 36 | """AMTRELAY record""" 37 | 38 | # see: RFC 8777 39 | 40 | __slots__ = ["precedence", "discovery_optional", "relay_type", "relay"] 41 | 42 | def __init__( 43 | self, rdclass, rdtype, precedence, discovery_optional, relay_type, relay 44 | ): 45 | super().__init__(rdclass, rdtype) 46 | relay = Relay(relay_type, relay) 47 | self.precedence = self._as_uint8(precedence) 48 | self.discovery_optional = self._as_bool(discovery_optional) 49 | self.relay_type = relay.type 50 | self.relay = relay.relay 51 | 52 | def to_text(self, origin=None, relativize=True, **kw): 53 | relay = Relay(self.relay_type, self.relay).to_text(origin, relativize) 54 | return "%d %d %d %s" % ( 55 | self.precedence, 56 | self.discovery_optional, 57 | self.relay_type, 58 | relay, 59 | ) 60 | 61 | @classmethod 62 | def from_text( 63 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 64 | ): 65 | precedence = tok.get_uint8() 66 | discovery_optional = tok.get_uint8() 67 | if discovery_optional > 1: 68 | raise dns.exception.SyntaxError("expecting 0 or 1") 69 | discovery_optional = bool(discovery_optional) 70 | relay_type = tok.get_uint8() 71 | if relay_type > 0x7F: 72 | raise dns.exception.SyntaxError("expecting an integer <= 127") 73 | relay = Relay.from_text(relay_type, tok, origin, relativize, relativize_to) 74 | return cls( 75 | rdclass, rdtype, precedence, discovery_optional, relay_type, relay.relay 76 | ) 77 | 78 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 79 | relay_type = self.relay_type | (self.discovery_optional << 7) 80 | header = struct.pack("!BB", self.precedence, relay_type) 81 | file.write(header) 82 | Relay(self.relay_type, self.relay).to_wire(file, compress, origin, canonicalize) 83 | 84 | @classmethod 85 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 86 | (precedence, relay_type) = parser.get_struct("!BB") 87 | discovery_optional = bool(relay_type >> 7) 88 | relay_type &= 0x7F 89 | relay = Relay.from_wire_parser(relay_type, parser, origin) 90 | return cls( 91 | rdclass, rdtype, precedence, discovery_optional, relay_type, relay.relay 92 | ) 93 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/AVC.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2016 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.txtbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class AVC(dns.rdtypes.txtbase.TXTBase): 24 | 25 | """AVC record""" 26 | 27 | # See: IANA dns parameters for AVC 28 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/CAA.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | import dns.tokenizer 24 | 25 | 26 | @dns.immutable.immutable 27 | class CAA(dns.rdata.Rdata): 28 | 29 | """CAA (Certification Authority Authorization) record""" 30 | 31 | # see: RFC 6844 32 | 33 | __slots__ = ["flags", "tag", "value"] 34 | 35 | def __init__(self, rdclass, rdtype, flags, tag, value): 36 | super().__init__(rdclass, rdtype) 37 | self.flags = self._as_uint8(flags) 38 | self.tag = self._as_bytes(tag, True, 255) 39 | if not tag.isalnum(): 40 | raise ValueError("tag is not alphanumeric") 41 | self.value = self._as_bytes(value) 42 | 43 | def to_text(self, origin=None, relativize=True, **kw): 44 | return '%u %s "%s"' % ( 45 | self.flags, 46 | dns.rdata._escapify(self.tag), 47 | dns.rdata._escapify(self.value), 48 | ) 49 | 50 | @classmethod 51 | def from_text( 52 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 53 | ): 54 | flags = tok.get_uint8() 55 | tag = tok.get_string().encode() 56 | value = tok.get_string().encode() 57 | return cls(rdclass, rdtype, flags, tag, value) 58 | 59 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 60 | file.write(struct.pack("!B", self.flags)) 61 | l = len(self.tag) 62 | assert l < 256 63 | file.write(struct.pack("!B", l)) 64 | file.write(self.tag) 65 | file.write(self.value) 66 | 67 | @classmethod 68 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 69 | flags = parser.get_uint8() 70 | tag = parser.get_counted_bytes() 71 | value = parser.get_remaining() 72 | return cls(rdclass, rdtype, flags, tag, value) 73 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/CDNSKEY.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.dnskeybase # lgtm[py/import-and-import-from] 19 | import dns.immutable 20 | 21 | # pylint: disable=unused-import 22 | from dns.rdtypes.dnskeybase import ( 23 | SEP, 24 | REVOKE, 25 | ZONE, 26 | ) # noqa: F401 lgtm[py/unused-import] 27 | 28 | # pylint: enable=unused-import 29 | 30 | 31 | @dns.immutable.immutable 32 | class CDNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase): 33 | 34 | """CDNSKEY record""" 35 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/CDS.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.dsbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class CDS(dns.rdtypes.dsbase.DSBase): 24 | 25 | """CDS record""" 26 | 27 | _digest_length_by_type = { 28 | **dns.rdtypes.dsbase.DSBase._digest_length_by_type, 29 | 0: 1, # delete, RFC 8078 Sec. 4 (including Errata ID 5049) 30 | } 31 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/CERT.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | import base64 20 | 21 | import dns.exception 22 | import dns.immutable 23 | import dns.dnssectypes 24 | import dns.rdata 25 | import dns.tokenizer 26 | 27 | _ctype_by_value = { 28 | 1: "PKIX", 29 | 2: "SPKI", 30 | 3: "PGP", 31 | 4: "IPKIX", 32 | 5: "ISPKI", 33 | 6: "IPGP", 34 | 7: "ACPKIX", 35 | 8: "IACPKIX", 36 | 253: "URI", 37 | 254: "OID", 38 | } 39 | 40 | _ctype_by_name = { 41 | "PKIX": 1, 42 | "SPKI": 2, 43 | "PGP": 3, 44 | "IPKIX": 4, 45 | "ISPKI": 5, 46 | "IPGP": 6, 47 | "ACPKIX": 7, 48 | "IACPKIX": 8, 49 | "URI": 253, 50 | "OID": 254, 51 | } 52 | 53 | 54 | def _ctype_from_text(what): 55 | v = _ctype_by_name.get(what) 56 | if v is not None: 57 | return v 58 | return int(what) 59 | 60 | 61 | def _ctype_to_text(what): 62 | v = _ctype_by_value.get(what) 63 | if v is not None: 64 | return v 65 | return str(what) 66 | 67 | 68 | @dns.immutable.immutable 69 | class CERT(dns.rdata.Rdata): 70 | 71 | """CERT record""" 72 | 73 | # see RFC 4398 74 | 75 | __slots__ = ["certificate_type", "key_tag", "algorithm", "certificate"] 76 | 77 | def __init__( 78 | self, rdclass, rdtype, certificate_type, key_tag, algorithm, certificate 79 | ): 80 | super().__init__(rdclass, rdtype) 81 | self.certificate_type = self._as_uint16(certificate_type) 82 | self.key_tag = self._as_uint16(key_tag) 83 | self.algorithm = self._as_uint8(algorithm) 84 | self.certificate = self._as_bytes(certificate) 85 | 86 | def to_text(self, origin=None, relativize=True, **kw): 87 | certificate_type = _ctype_to_text(self.certificate_type) 88 | return "%s %d %s %s" % ( 89 | certificate_type, 90 | self.key_tag, 91 | dns.dnssectypes.Algorithm.to_text(self.algorithm), 92 | dns.rdata._base64ify(self.certificate, **kw), 93 | ) 94 | 95 | @classmethod 96 | def from_text( 97 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 98 | ): 99 | certificate_type = _ctype_from_text(tok.get_string()) 100 | key_tag = tok.get_uint16() 101 | algorithm = dns.dnssectypes.Algorithm.from_text(tok.get_string()) 102 | b64 = tok.concatenate_remaining_identifiers().encode() 103 | certificate = base64.b64decode(b64) 104 | return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, certificate) 105 | 106 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 107 | prefix = struct.pack( 108 | "!HHB", self.certificate_type, self.key_tag, self.algorithm 109 | ) 110 | file.write(prefix) 111 | file.write(self.certificate) 112 | 113 | @classmethod 114 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 115 | (certificate_type, key_tag, algorithm) = parser.get_struct("!HHB") 116 | certificate = parser.get_remaining() 117 | return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, certificate) 118 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/CNAME.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.nsbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class CNAME(dns.rdtypes.nsbase.NSBase): 24 | 25 | """CNAME record 26 | 27 | Note: although CNAME is officially a singleton type, dnspython allows 28 | non-singleton CNAME rdatasets because such sets have been commonly 29 | used by BIND and other nameservers for load balancing.""" 30 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/CSYNC.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2004-2007, 2009-2011, 2016 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | import dns.rdatatype 24 | import dns.name 25 | import dns.rdtypes.util 26 | 27 | 28 | @dns.immutable.immutable 29 | class Bitmap(dns.rdtypes.util.Bitmap): 30 | type_name = "CSYNC" 31 | 32 | 33 | @dns.immutable.immutable 34 | class CSYNC(dns.rdata.Rdata): 35 | 36 | """CSYNC record""" 37 | 38 | __slots__ = ["serial", "flags", "windows"] 39 | 40 | def __init__(self, rdclass, rdtype, serial, flags, windows): 41 | super().__init__(rdclass, rdtype) 42 | self.serial = self._as_uint32(serial) 43 | self.flags = self._as_uint16(flags) 44 | if not isinstance(windows, Bitmap): 45 | windows = Bitmap(windows) 46 | self.windows = tuple(windows.windows) 47 | 48 | def to_text(self, origin=None, relativize=True, **kw): 49 | text = Bitmap(self.windows).to_text() 50 | return "%d %d%s" % (self.serial, self.flags, text) 51 | 52 | @classmethod 53 | def from_text( 54 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 55 | ): 56 | serial = tok.get_uint32() 57 | flags = tok.get_uint16() 58 | bitmap = Bitmap.from_text(tok) 59 | return cls(rdclass, rdtype, serial, flags, bitmap) 60 | 61 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 62 | file.write(struct.pack("!IH", self.serial, self.flags)) 63 | Bitmap(self.windows).to_wire(file) 64 | 65 | @classmethod 66 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 67 | (serial, flags) = parser.get_struct("!IH") 68 | bitmap = Bitmap.from_wire_parser(parser) 69 | return cls(rdclass, rdtype, serial, flags, bitmap) 70 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/DLV.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.dsbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class DLV(dns.rdtypes.dsbase.DSBase): 24 | 25 | """DLV record""" 26 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/DNAME.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.nsbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class DNAME(dns.rdtypes.nsbase.UncompressedNS): 24 | 25 | """DNAME record""" 26 | 27 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 28 | self.target.to_wire(file, None, origin, canonicalize) 29 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/DNSKEY.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.dnskeybase # lgtm[py/import-and-import-from] 19 | import dns.immutable 20 | 21 | # pylint: disable=unused-import 22 | from dns.rdtypes.dnskeybase import ( 23 | SEP, 24 | REVOKE, 25 | ZONE, 26 | ) # noqa: F401 lgtm[py/unused-import] 27 | 28 | # pylint: enable=unused-import 29 | 30 | 31 | @dns.immutable.immutable 32 | class DNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase): 33 | 34 | """DNSKEY record""" 35 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/DS.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.dsbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class DS(dns.rdtypes.dsbase.DSBase): 24 | 25 | """DS record""" 26 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/EUI48.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2015 Red Hat, Inc. 4 | # Author: Petr Spacek 5 | # 6 | # Permission to use, copy, modify, and distribute this software and its 7 | # documentation for any purpose with or without fee is hereby granted, 8 | # provided that the above copyright notice and this permission notice 9 | # appear in all copies. 10 | # 11 | # THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES 12 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 14 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | 19 | import dns.rdtypes.euibase 20 | import dns.immutable 21 | 22 | 23 | @dns.immutable.immutable 24 | class EUI48(dns.rdtypes.euibase.EUIBase): 25 | 26 | """EUI48 record""" 27 | 28 | # see: rfc7043.txt 29 | 30 | byte_len = 6 # 0123456789ab (in hex) 31 | text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab 32 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/EUI64.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2015 Red Hat, Inc. 4 | # Author: Petr Spacek 5 | # 6 | # Permission to use, copy, modify, and distribute this software and its 7 | # documentation for any purpose with or without fee is hereby granted, 8 | # provided that the above copyright notice and this permission notice 9 | # appear in all copies. 10 | # 11 | # THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES 12 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 14 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | 19 | import dns.rdtypes.euibase 20 | import dns.immutable 21 | 22 | 23 | @dns.immutable.immutable 24 | class EUI64(dns.rdtypes.euibase.EUIBase): 25 | 26 | """EUI64 record""" 27 | 28 | # see: rfc7043.txt 29 | 30 | byte_len = 8 # 0123456789abcdef (in hex) 31 | text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab-cd-ef 32 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/HINFO.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | import dns.tokenizer 24 | 25 | 26 | @dns.immutable.immutable 27 | class HINFO(dns.rdata.Rdata): 28 | 29 | """HINFO record""" 30 | 31 | # see: RFC 1035 32 | 33 | __slots__ = ["cpu", "os"] 34 | 35 | def __init__(self, rdclass, rdtype, cpu, os): 36 | super().__init__(rdclass, rdtype) 37 | self.cpu = self._as_bytes(cpu, True, 255) 38 | self.os = self._as_bytes(os, True, 255) 39 | 40 | def to_text(self, origin=None, relativize=True, **kw): 41 | return '"{}" "{}"'.format( 42 | dns.rdata._escapify(self.cpu), dns.rdata._escapify(self.os) 43 | ) 44 | 45 | @classmethod 46 | def from_text( 47 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 48 | ): 49 | cpu = tok.get_string(max_length=255) 50 | os = tok.get_string(max_length=255) 51 | return cls(rdclass, rdtype, cpu, os) 52 | 53 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 54 | l = len(self.cpu) 55 | assert l < 256 56 | file.write(struct.pack("!B", l)) 57 | file.write(self.cpu) 58 | l = len(self.os) 59 | assert l < 256 60 | file.write(struct.pack("!B", l)) 61 | file.write(self.os) 62 | 63 | @classmethod 64 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 65 | cpu = parser.get_counted_bytes() 66 | os = parser.get_counted_bytes() 67 | return cls(rdclass, rdtype, cpu, os) 68 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/HIP.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2010, 2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | import base64 20 | import binascii 21 | 22 | import dns.exception 23 | import dns.immutable 24 | import dns.rdata 25 | import dns.rdatatype 26 | 27 | 28 | @dns.immutable.immutable 29 | class HIP(dns.rdata.Rdata): 30 | 31 | """HIP record""" 32 | 33 | # see: RFC 5205 34 | 35 | __slots__ = ["hit", "algorithm", "key", "servers"] 36 | 37 | def __init__(self, rdclass, rdtype, hit, algorithm, key, servers): 38 | super().__init__(rdclass, rdtype) 39 | self.hit = self._as_bytes(hit, True, 255) 40 | self.algorithm = self._as_uint8(algorithm) 41 | self.key = self._as_bytes(key, True) 42 | self.servers = self._as_tuple(servers, self._as_name) 43 | 44 | def to_text(self, origin=None, relativize=True, **kw): 45 | hit = binascii.hexlify(self.hit).decode() 46 | key = base64.b64encode(self.key).replace(b"\n", b"").decode() 47 | text = "" 48 | servers = [] 49 | for server in self.servers: 50 | servers.append(server.choose_relativity(origin, relativize)) 51 | if len(servers) > 0: 52 | text += " " + " ".join((x.to_unicode() for x in servers)) 53 | return "%u %s %s%s" % (self.algorithm, hit, key, text) 54 | 55 | @classmethod 56 | def from_text( 57 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 58 | ): 59 | algorithm = tok.get_uint8() 60 | hit = binascii.unhexlify(tok.get_string().encode()) 61 | key = base64.b64decode(tok.get_string().encode()) 62 | servers = [] 63 | for token in tok.get_remaining(): 64 | server = tok.as_name(token, origin, relativize, relativize_to) 65 | servers.append(server) 66 | return cls(rdclass, rdtype, hit, algorithm, key, servers) 67 | 68 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 69 | lh = len(self.hit) 70 | lk = len(self.key) 71 | file.write(struct.pack("!BBH", lh, self.algorithm, lk)) 72 | file.write(self.hit) 73 | file.write(self.key) 74 | for server in self.servers: 75 | server.to_wire(file, None, origin, False) 76 | 77 | @classmethod 78 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 79 | (lh, algorithm, lk) = parser.get_struct("!BBH") 80 | hit = parser.get_bytes(lh) 81 | key = parser.get_bytes(lk) 82 | servers = [] 83 | while parser.remaining() > 0: 84 | server = parser.get_name(origin) 85 | servers.append(server) 86 | return cls(rdclass, rdtype, hit, algorithm, key, servers) 87 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/ISDN.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | import dns.tokenizer 24 | 25 | 26 | @dns.immutable.immutable 27 | class ISDN(dns.rdata.Rdata): 28 | 29 | """ISDN record""" 30 | 31 | # see: RFC 1183 32 | 33 | __slots__ = ["address", "subaddress"] 34 | 35 | def __init__(self, rdclass, rdtype, address, subaddress): 36 | super().__init__(rdclass, rdtype) 37 | self.address = self._as_bytes(address, True, 255) 38 | self.subaddress = self._as_bytes(subaddress, True, 255) 39 | 40 | def to_text(self, origin=None, relativize=True, **kw): 41 | if self.subaddress: 42 | return '"{}" "{}"'.format( 43 | dns.rdata._escapify(self.address), dns.rdata._escapify(self.subaddress) 44 | ) 45 | else: 46 | return '"%s"' % dns.rdata._escapify(self.address) 47 | 48 | @classmethod 49 | def from_text( 50 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 51 | ): 52 | address = tok.get_string() 53 | tokens = tok.get_remaining(max_tokens=1) 54 | if len(tokens) >= 1: 55 | subaddress = tokens[0].unescape().value 56 | else: 57 | subaddress = "" 58 | return cls(rdclass, rdtype, address, subaddress) 59 | 60 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 61 | l = len(self.address) 62 | assert l < 256 63 | file.write(struct.pack("!B", l)) 64 | file.write(self.address) 65 | l = len(self.subaddress) 66 | if l > 0: 67 | assert l < 256 68 | file.write(struct.pack("!B", l)) 69 | file.write(self.subaddress) 70 | 71 | @classmethod 72 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 73 | address = parser.get_counted_bytes() 74 | if parser.remaining() > 0: 75 | subaddress = parser.get_counted_bytes() 76 | else: 77 | subaddress = b"" 78 | return cls(rdclass, rdtype, address, subaddress) 79 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/L32.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | import struct 4 | 5 | import dns.immutable 6 | import dns.rdata 7 | 8 | 9 | @dns.immutable.immutable 10 | class L32(dns.rdata.Rdata): 11 | 12 | """L32 record""" 13 | 14 | # see: rfc6742.txt 15 | 16 | __slots__ = ["preference", "locator32"] 17 | 18 | def __init__(self, rdclass, rdtype, preference, locator32): 19 | super().__init__(rdclass, rdtype) 20 | self.preference = self._as_uint16(preference) 21 | self.locator32 = self._as_ipv4_address(locator32) 22 | 23 | def to_text(self, origin=None, relativize=True, **kw): 24 | return f"{self.preference} {self.locator32}" 25 | 26 | @classmethod 27 | def from_text( 28 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 29 | ): 30 | preference = tok.get_uint16() 31 | nodeid = tok.get_identifier() 32 | return cls(rdclass, rdtype, preference, nodeid) 33 | 34 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 35 | file.write(struct.pack("!H", self.preference)) 36 | file.write(dns.ipv4.inet_aton(self.locator32)) 37 | 38 | @classmethod 39 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 40 | preference = parser.get_uint16() 41 | locator32 = parser.get_remaining() 42 | return cls(rdclass, rdtype, preference, locator32) 43 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/L64.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | import struct 4 | 5 | import dns.immutable 6 | import dns.rdtypes.util 7 | 8 | 9 | @dns.immutable.immutable 10 | class L64(dns.rdata.Rdata): 11 | 12 | """L64 record""" 13 | 14 | # see: rfc6742.txt 15 | 16 | __slots__ = ["preference", "locator64"] 17 | 18 | def __init__(self, rdclass, rdtype, preference, locator64): 19 | super().__init__(rdclass, rdtype) 20 | self.preference = self._as_uint16(preference) 21 | if isinstance(locator64, bytes): 22 | if len(locator64) != 8: 23 | raise ValueError("invalid locator64") 24 | self.locator64 = dns.rdata._hexify(locator64, 4, b":") 25 | else: 26 | dns.rdtypes.util.parse_formatted_hex(locator64, 4, 4, ":") 27 | self.locator64 = locator64 28 | 29 | def to_text(self, origin=None, relativize=True, **kw): 30 | return f"{self.preference} {self.locator64}" 31 | 32 | @classmethod 33 | def from_text( 34 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 35 | ): 36 | preference = tok.get_uint16() 37 | locator64 = tok.get_identifier() 38 | return cls(rdclass, rdtype, preference, locator64) 39 | 40 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 41 | file.write(struct.pack("!H", self.preference)) 42 | file.write(dns.rdtypes.util.parse_formatted_hex(self.locator64, 4, 4, ":")) 43 | 44 | @classmethod 45 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 46 | preference = parser.get_uint16() 47 | locator64 = parser.get_remaining() 48 | return cls(rdclass, rdtype, preference, locator64) 49 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/LP.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | import struct 4 | 5 | import dns.immutable 6 | import dns.rdata 7 | 8 | 9 | @dns.immutable.immutable 10 | class LP(dns.rdata.Rdata): 11 | 12 | """LP record""" 13 | 14 | # see: rfc6742.txt 15 | 16 | __slots__ = ["preference", "fqdn"] 17 | 18 | def __init__(self, rdclass, rdtype, preference, fqdn): 19 | super().__init__(rdclass, rdtype) 20 | self.preference = self._as_uint16(preference) 21 | self.fqdn = self._as_name(fqdn) 22 | 23 | def to_text(self, origin=None, relativize=True, **kw): 24 | fqdn = self.fqdn.choose_relativity(origin, relativize) 25 | return "%d %s" % (self.preference, fqdn) 26 | 27 | @classmethod 28 | def from_text( 29 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 30 | ): 31 | preference = tok.get_uint16() 32 | fqdn = tok.get_name(origin, relativize, relativize_to) 33 | return cls(rdclass, rdtype, preference, fqdn) 34 | 35 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 36 | file.write(struct.pack("!H", self.preference)) 37 | self.fqdn.to_wire(file, compress, origin, canonicalize) 38 | 39 | @classmethod 40 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 41 | preference = parser.get_uint16() 42 | fqdn = parser.get_name(origin) 43 | return cls(rdclass, rdtype, preference, fqdn) 44 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/MX.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.mxbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class MX(dns.rdtypes.mxbase.MXBase): 24 | 25 | """MX record""" 26 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/NID.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | import struct 4 | 5 | import dns.immutable 6 | import dns.rdtypes.util 7 | 8 | 9 | @dns.immutable.immutable 10 | class NID(dns.rdata.Rdata): 11 | 12 | """NID record""" 13 | 14 | # see: rfc6742.txt 15 | 16 | __slots__ = ["preference", "nodeid"] 17 | 18 | def __init__(self, rdclass, rdtype, preference, nodeid): 19 | super().__init__(rdclass, rdtype) 20 | self.preference = self._as_uint16(preference) 21 | if isinstance(nodeid, bytes): 22 | if len(nodeid) != 8: 23 | raise ValueError("invalid nodeid") 24 | self.nodeid = dns.rdata._hexify(nodeid, 4, b":") 25 | else: 26 | dns.rdtypes.util.parse_formatted_hex(nodeid, 4, 4, ":") 27 | self.nodeid = nodeid 28 | 29 | def to_text(self, origin=None, relativize=True, **kw): 30 | return f"{self.preference} {self.nodeid}" 31 | 32 | @classmethod 33 | def from_text( 34 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 35 | ): 36 | preference = tok.get_uint16() 37 | nodeid = tok.get_identifier() 38 | return cls(rdclass, rdtype, preference, nodeid) 39 | 40 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 41 | file.write(struct.pack("!H", self.preference)) 42 | file.write(dns.rdtypes.util.parse_formatted_hex(self.nodeid, 4, 4, ":")) 43 | 44 | @classmethod 45 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 46 | preference = parser.get_uint16() 47 | nodeid = parser.get_remaining() 48 | return cls(rdclass, rdtype, preference, nodeid) 49 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/NINFO.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.txtbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class NINFO(dns.rdtypes.txtbase.TXTBase): 24 | 25 | """NINFO record""" 26 | 27 | # see: draft-reid-dnsext-zs-01 28 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/NS.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.nsbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class NS(dns.rdtypes.nsbase.NSBase): 24 | 25 | """NS record""" 26 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/NSEC.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.exception 19 | import dns.immutable 20 | import dns.rdata 21 | import dns.rdatatype 22 | import dns.name 23 | import dns.rdtypes.util 24 | 25 | 26 | @dns.immutable.immutable 27 | class Bitmap(dns.rdtypes.util.Bitmap): 28 | type_name = "NSEC" 29 | 30 | 31 | @dns.immutable.immutable 32 | class NSEC(dns.rdata.Rdata): 33 | 34 | """NSEC record""" 35 | 36 | __slots__ = ["next", "windows"] 37 | 38 | def __init__(self, rdclass, rdtype, next, windows): 39 | super().__init__(rdclass, rdtype) 40 | self.next = self._as_name(next) 41 | if not isinstance(windows, Bitmap): 42 | windows = Bitmap(windows) 43 | self.windows = tuple(windows.windows) 44 | 45 | def to_text(self, origin=None, relativize=True, **kw): 46 | next = self.next.choose_relativity(origin, relativize) 47 | text = Bitmap(self.windows).to_text() 48 | return "{}{}".format(next, text) 49 | 50 | @classmethod 51 | def from_text( 52 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 53 | ): 54 | next = tok.get_name(origin, relativize, relativize_to) 55 | windows = Bitmap.from_text(tok) 56 | return cls(rdclass, rdtype, next, windows) 57 | 58 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 59 | # Note that NSEC downcasing, originally mandated by RFC 4034 60 | # section 6.2 was removed by RFC 6840 section 5.1. 61 | self.next.to_wire(file, None, origin, False) 62 | Bitmap(self.windows).to_wire(file) 63 | 64 | @classmethod 65 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 66 | next = parser.get_name(origin) 67 | bitmap = Bitmap.from_wire_parser(parser) 68 | return cls(rdclass, rdtype, next, bitmap) 69 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/NSEC3.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2004-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import base64 19 | import binascii 20 | import struct 21 | 22 | import dns.exception 23 | import dns.immutable 24 | import dns.rdata 25 | import dns.rdatatype 26 | import dns.rdtypes.util 27 | 28 | 29 | b32_hex_to_normal = bytes.maketrans( 30 | b"0123456789ABCDEFGHIJKLMNOPQRSTUV", b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" 31 | ) 32 | b32_normal_to_hex = bytes.maketrans( 33 | b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", b"0123456789ABCDEFGHIJKLMNOPQRSTUV" 34 | ) 35 | 36 | # hash algorithm constants 37 | SHA1 = 1 38 | 39 | # flag constants 40 | OPTOUT = 1 41 | 42 | 43 | @dns.immutable.immutable 44 | class Bitmap(dns.rdtypes.util.Bitmap): 45 | type_name = "NSEC3" 46 | 47 | 48 | @dns.immutable.immutable 49 | class NSEC3(dns.rdata.Rdata): 50 | 51 | """NSEC3 record""" 52 | 53 | __slots__ = ["algorithm", "flags", "iterations", "salt", "next", "windows"] 54 | 55 | def __init__( 56 | self, rdclass, rdtype, algorithm, flags, iterations, salt, next, windows 57 | ): 58 | super().__init__(rdclass, rdtype) 59 | self.algorithm = self._as_uint8(algorithm) 60 | self.flags = self._as_uint8(flags) 61 | self.iterations = self._as_uint16(iterations) 62 | self.salt = self._as_bytes(salt, True, 255) 63 | self.next = self._as_bytes(next, True, 255) 64 | if not isinstance(windows, Bitmap): 65 | windows = Bitmap(windows) 66 | self.windows = tuple(windows.windows) 67 | 68 | def to_text(self, origin=None, relativize=True, **kw): 69 | next = base64.b32encode(self.next).translate(b32_normal_to_hex).lower().decode() 70 | if self.salt == b"": 71 | salt = "-" 72 | else: 73 | salt = binascii.hexlify(self.salt).decode() 74 | text = Bitmap(self.windows).to_text() 75 | return "%u %u %u %s %s%s" % ( 76 | self.algorithm, 77 | self.flags, 78 | self.iterations, 79 | salt, 80 | next, 81 | text, 82 | ) 83 | 84 | @classmethod 85 | def from_text( 86 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 87 | ): 88 | algorithm = tok.get_uint8() 89 | flags = tok.get_uint8() 90 | iterations = tok.get_uint16() 91 | salt = tok.get_string() 92 | if salt == "-": 93 | salt = b"" 94 | else: 95 | salt = binascii.unhexlify(salt.encode("ascii")) 96 | next = tok.get_string().encode("ascii").upper().translate(b32_hex_to_normal) 97 | next = base64.b32decode(next) 98 | bitmap = Bitmap.from_text(tok) 99 | return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, bitmap) 100 | 101 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 102 | l = len(self.salt) 103 | file.write(struct.pack("!BBHB", self.algorithm, self.flags, self.iterations, l)) 104 | file.write(self.salt) 105 | l = len(self.next) 106 | file.write(struct.pack("!B", l)) 107 | file.write(self.next) 108 | Bitmap(self.windows).to_wire(file) 109 | 110 | @classmethod 111 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 112 | (algorithm, flags, iterations) = parser.get_struct("!BBH") 113 | salt = parser.get_counted_bytes() 114 | next = parser.get_counted_bytes() 115 | bitmap = Bitmap.from_wire_parser(parser) 116 | return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, bitmap) 117 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/NSEC3PARAM.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | import binascii 20 | 21 | import dns.exception 22 | import dns.immutable 23 | import dns.rdata 24 | 25 | 26 | @dns.immutable.immutable 27 | class NSEC3PARAM(dns.rdata.Rdata): 28 | 29 | """NSEC3PARAM record""" 30 | 31 | __slots__ = ["algorithm", "flags", "iterations", "salt"] 32 | 33 | def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt): 34 | super().__init__(rdclass, rdtype) 35 | self.algorithm = self._as_uint8(algorithm) 36 | self.flags = self._as_uint8(flags) 37 | self.iterations = self._as_uint16(iterations) 38 | self.salt = self._as_bytes(salt, True, 255) 39 | 40 | def to_text(self, origin=None, relativize=True, **kw): 41 | if self.salt == b"": 42 | salt = "-" 43 | else: 44 | salt = binascii.hexlify(self.salt).decode() 45 | return "%u %u %u %s" % (self.algorithm, self.flags, self.iterations, salt) 46 | 47 | @classmethod 48 | def from_text( 49 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 50 | ): 51 | algorithm = tok.get_uint8() 52 | flags = tok.get_uint8() 53 | iterations = tok.get_uint16() 54 | salt = tok.get_string() 55 | if salt == "-": 56 | salt = "" 57 | else: 58 | salt = binascii.unhexlify(salt.encode()) 59 | return cls(rdclass, rdtype, algorithm, flags, iterations, salt) 60 | 61 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 62 | l = len(self.salt) 63 | file.write(struct.pack("!BBHB", self.algorithm, self.flags, self.iterations, l)) 64 | file.write(self.salt) 65 | 66 | @classmethod 67 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 68 | (algorithm, flags, iterations) = parser.get_struct("!BBH") 69 | salt = parser.get_counted_bytes() 70 | return cls(rdclass, rdtype, algorithm, flags, iterations, salt) 71 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/OPENPGPKEY.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2016 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import base64 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | import dns.tokenizer 24 | 25 | 26 | @dns.immutable.immutable 27 | class OPENPGPKEY(dns.rdata.Rdata): 28 | 29 | """OPENPGPKEY record""" 30 | 31 | # see: RFC 7929 32 | 33 | def __init__(self, rdclass, rdtype, key): 34 | super().__init__(rdclass, rdtype) 35 | self.key = self._as_bytes(key) 36 | 37 | def to_text(self, origin=None, relativize=True, **kw): 38 | return dns.rdata._base64ify(self.key, chunksize=None, **kw) 39 | 40 | @classmethod 41 | def from_text( 42 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 43 | ): 44 | b64 = tok.concatenate_remaining_identifiers().encode() 45 | key = base64.b64decode(b64) 46 | return cls(rdclass, rdtype, key) 47 | 48 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 49 | file.write(self.key) 50 | 51 | @classmethod 52 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 53 | key = parser.get_remaining() 54 | return cls(rdclass, rdtype, key) 55 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/OPT.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2001-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.edns 21 | import dns.immutable 22 | import dns.exception 23 | import dns.rdata 24 | 25 | 26 | # We don't implement from_text, and that's ok. 27 | # pylint: disable=abstract-method 28 | 29 | 30 | @dns.immutable.immutable 31 | class OPT(dns.rdata.Rdata): 32 | 33 | """OPT record""" 34 | 35 | __slots__ = ["options"] 36 | 37 | def __init__(self, rdclass, rdtype, options): 38 | """Initialize an OPT rdata. 39 | 40 | *rdclass*, an ``int`` is the rdataclass of the Rdata, 41 | which is also the payload size. 42 | 43 | *rdtype*, an ``int`` is the rdatatype of the Rdata. 44 | 45 | *options*, a tuple of ``bytes`` 46 | """ 47 | 48 | super().__init__(rdclass, rdtype) 49 | 50 | def as_option(option): 51 | if not isinstance(option, dns.edns.Option): 52 | raise ValueError("option is not a dns.edns.option") 53 | return option 54 | 55 | self.options = self._as_tuple(options, as_option) 56 | 57 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 58 | for opt in self.options: 59 | owire = opt.to_wire() 60 | file.write(struct.pack("!HH", opt.otype, len(owire))) 61 | file.write(owire) 62 | 63 | def to_text(self, origin=None, relativize=True, **kw): 64 | return " ".join(opt.to_text() for opt in self.options) 65 | 66 | @classmethod 67 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 68 | options = [] 69 | while parser.remaining() > 0: 70 | (otype, olen) = parser.get_struct("!HH") 71 | with parser.restrict_to(olen): 72 | opt = dns.edns.option_from_wire_parser(otype, parser) 73 | options.append(opt) 74 | return cls(rdclass, rdtype, options) 75 | 76 | @property 77 | def payload(self): 78 | "payload size" 79 | return self.rdclass 80 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/PTR.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.nsbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class PTR(dns.rdtypes.nsbase.NSBase): 24 | 25 | """PTR record""" 26 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/RP.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.exception 19 | import dns.immutable 20 | import dns.rdata 21 | import dns.name 22 | 23 | 24 | @dns.immutable.immutable 25 | class RP(dns.rdata.Rdata): 26 | 27 | """RP record""" 28 | 29 | # see: RFC 1183 30 | 31 | __slots__ = ["mbox", "txt"] 32 | 33 | def __init__(self, rdclass, rdtype, mbox, txt): 34 | super().__init__(rdclass, rdtype) 35 | self.mbox = self._as_name(mbox) 36 | self.txt = self._as_name(txt) 37 | 38 | def to_text(self, origin=None, relativize=True, **kw): 39 | mbox = self.mbox.choose_relativity(origin, relativize) 40 | txt = self.txt.choose_relativity(origin, relativize) 41 | return "{} {}".format(str(mbox), str(txt)) 42 | 43 | @classmethod 44 | def from_text( 45 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 46 | ): 47 | mbox = tok.get_name(origin, relativize, relativize_to) 48 | txt = tok.get_name(origin, relativize, relativize_to) 49 | return cls(rdclass, rdtype, mbox, txt) 50 | 51 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 52 | self.mbox.to_wire(file, None, origin, canonicalize) 53 | self.txt.to_wire(file, None, origin, canonicalize) 54 | 55 | @classmethod 56 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 57 | mbox = parser.get_name(origin) 58 | txt = parser.get_name(origin) 59 | return cls(rdclass, rdtype, mbox, txt) 60 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/RT.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.mxbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class RT(dns.rdtypes.mxbase.UncompressedDowncasingMX): 24 | 25 | """RT record""" 26 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/SMIMEA.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | import dns.immutable 4 | import dns.rdtypes.tlsabase 5 | 6 | 7 | @dns.immutable.immutable 8 | class SMIMEA(dns.rdtypes.tlsabase.TLSABase): 9 | """SMIMEA record""" 10 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/SOA.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | import dns.name 24 | 25 | 26 | @dns.immutable.immutable 27 | class SOA(dns.rdata.Rdata): 28 | 29 | """SOA record""" 30 | 31 | # see: RFC 1035 32 | 33 | __slots__ = ["mname", "rname", "serial", "refresh", "retry", "expire", "minimum"] 34 | 35 | def __init__( 36 | self, rdclass, rdtype, mname, rname, serial, refresh, retry, expire, minimum 37 | ): 38 | super().__init__(rdclass, rdtype) 39 | self.mname = self._as_name(mname) 40 | self.rname = self._as_name(rname) 41 | self.serial = self._as_uint32(serial) 42 | self.refresh = self._as_ttl(refresh) 43 | self.retry = self._as_ttl(retry) 44 | self.expire = self._as_ttl(expire) 45 | self.minimum = self._as_ttl(minimum) 46 | 47 | def to_text(self, origin=None, relativize=True, **kw): 48 | mname = self.mname.choose_relativity(origin, relativize) 49 | rname = self.rname.choose_relativity(origin, relativize) 50 | return "%s %s %d %d %d %d %d" % ( 51 | mname, 52 | rname, 53 | self.serial, 54 | self.refresh, 55 | self.retry, 56 | self.expire, 57 | self.minimum, 58 | ) 59 | 60 | @classmethod 61 | def from_text( 62 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 63 | ): 64 | mname = tok.get_name(origin, relativize, relativize_to) 65 | rname = tok.get_name(origin, relativize, relativize_to) 66 | serial = tok.get_uint32() 67 | refresh = tok.get_ttl() 68 | retry = tok.get_ttl() 69 | expire = tok.get_ttl() 70 | minimum = tok.get_ttl() 71 | return cls( 72 | rdclass, rdtype, mname, rname, serial, refresh, retry, expire, minimum 73 | ) 74 | 75 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 76 | self.mname.to_wire(file, compress, origin, canonicalize) 77 | self.rname.to_wire(file, compress, origin, canonicalize) 78 | five_ints = struct.pack( 79 | "!IIIII", self.serial, self.refresh, self.retry, self.expire, self.minimum 80 | ) 81 | file.write(five_ints) 82 | 83 | @classmethod 84 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 85 | mname = parser.get_name(origin) 86 | rname = parser.get_name(origin) 87 | return cls(rdclass, rdtype, mname, rname, *parser.get_struct("!IIIII")) 88 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/SPF.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.txtbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class SPF(dns.rdtypes.txtbase.TXTBase): 24 | 25 | """SPF record""" 26 | 27 | # see: RFC 4408 28 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/SSHFP.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2005-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | import binascii 20 | 21 | import dns.rdata 22 | import dns.immutable 23 | import dns.rdatatype 24 | 25 | 26 | @dns.immutable.immutable 27 | class SSHFP(dns.rdata.Rdata): 28 | 29 | """SSHFP record""" 30 | 31 | # See RFC 4255 32 | 33 | __slots__ = ["algorithm", "fp_type", "fingerprint"] 34 | 35 | def __init__(self, rdclass, rdtype, algorithm, fp_type, fingerprint): 36 | super().__init__(rdclass, rdtype) 37 | self.algorithm = self._as_uint8(algorithm) 38 | self.fp_type = self._as_uint8(fp_type) 39 | self.fingerprint = self._as_bytes(fingerprint, True) 40 | 41 | def to_text(self, origin=None, relativize=True, **kw): 42 | kw = kw.copy() 43 | chunksize = kw.pop("chunksize", 128) 44 | return "%d %d %s" % ( 45 | self.algorithm, 46 | self.fp_type, 47 | dns.rdata._hexify(self.fingerprint, chunksize=chunksize, **kw), 48 | ) 49 | 50 | @classmethod 51 | def from_text( 52 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 53 | ): 54 | algorithm = tok.get_uint8() 55 | fp_type = tok.get_uint8() 56 | fingerprint = tok.concatenate_remaining_identifiers().encode() 57 | fingerprint = binascii.unhexlify(fingerprint) 58 | return cls(rdclass, rdtype, algorithm, fp_type, fingerprint) 59 | 60 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 61 | header = struct.pack("!BB", self.algorithm, self.fp_type) 62 | file.write(header) 63 | file.write(self.fingerprint) 64 | 65 | @classmethod 66 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 67 | header = parser.get_struct("BB") 68 | fingerprint = parser.get_remaining() 69 | return cls(rdclass, rdtype, header[0], header[1], fingerprint) 70 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/TLSA.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | import dns.immutable 4 | import dns.rdtypes.tlsabase 5 | 6 | 7 | @dns.immutable.immutable 8 | class TLSA(dns.rdtypes.tlsabase.TLSABase): 9 | 10 | """TLSA record""" 11 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/TXT.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.txtbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class TXT(dns.rdtypes.txtbase.TXTBase): 24 | 25 | """TXT record""" 26 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/URI.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # Copyright (C) 2015 Red Hat, Inc. 5 | # 6 | # Permission to use, copy, modify, and distribute this software and its 7 | # documentation for any purpose with or without fee is hereby granted, 8 | # provided that the above copyright notice and this permission notice 9 | # appear in all copies. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 12 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 14 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | 19 | import struct 20 | 21 | import dns.exception 22 | import dns.immutable 23 | import dns.rdata 24 | import dns.rdtypes.util 25 | import dns.name 26 | 27 | 28 | @dns.immutable.immutable 29 | class URI(dns.rdata.Rdata): 30 | 31 | """URI record""" 32 | 33 | # see RFC 7553 34 | 35 | __slots__ = ["priority", "weight", "target"] 36 | 37 | def __init__(self, rdclass, rdtype, priority, weight, target): 38 | super().__init__(rdclass, rdtype) 39 | self.priority = self._as_uint16(priority) 40 | self.weight = self._as_uint16(weight) 41 | self.target = self._as_bytes(target, True) 42 | if len(self.target) == 0: 43 | raise dns.exception.SyntaxError("URI target cannot be empty") 44 | 45 | def to_text(self, origin=None, relativize=True, **kw): 46 | return '%d %d "%s"' % (self.priority, self.weight, self.target.decode()) 47 | 48 | @classmethod 49 | def from_text( 50 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 51 | ): 52 | priority = tok.get_uint16() 53 | weight = tok.get_uint16() 54 | target = tok.get().unescape() 55 | if not (target.is_quoted_string() or target.is_identifier()): 56 | raise dns.exception.SyntaxError("URI target must be a string") 57 | return cls(rdclass, rdtype, priority, weight, target.value) 58 | 59 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 60 | two_ints = struct.pack("!HH", self.priority, self.weight) 61 | file.write(two_ints) 62 | file.write(self.target) 63 | 64 | @classmethod 65 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 66 | (priority, weight) = parser.get_struct("!HH") 67 | target = parser.get_remaining() 68 | if len(target) == 0: 69 | raise dns.exception.FormError("URI target may not be empty") 70 | return cls(rdclass, rdtype, priority, weight, target) 71 | 72 | def _processing_priority(self): 73 | return self.priority 74 | 75 | def _processing_weight(self): 76 | return self.weight 77 | 78 | @classmethod 79 | def _processing_order(cls, iterable): 80 | return dns.rdtypes.util.weighted_processing_order(iterable) 81 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/X25.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | import dns.tokenizer 24 | 25 | 26 | @dns.immutable.immutable 27 | class X25(dns.rdata.Rdata): 28 | 29 | """X25 record""" 30 | 31 | # see RFC 1183 32 | 33 | __slots__ = ["address"] 34 | 35 | def __init__(self, rdclass, rdtype, address): 36 | super().__init__(rdclass, rdtype) 37 | self.address = self._as_bytes(address, True, 255) 38 | 39 | def to_text(self, origin=None, relativize=True, **kw): 40 | return '"%s"' % dns.rdata._escapify(self.address) 41 | 42 | @classmethod 43 | def from_text( 44 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 45 | ): 46 | address = tok.get_string() 47 | return cls(rdclass, rdtype, address) 48 | 49 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 50 | l = len(self.address) 51 | assert l < 256 52 | file.write(struct.pack("!B", l)) 53 | file.write(self.address) 54 | 55 | @classmethod 56 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 57 | address = parser.get_counted_bytes() 58 | return cls(rdclass, rdtype, address) 59 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/ZONEMD.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | import struct 4 | import binascii 5 | 6 | import dns.immutable 7 | import dns.rdata 8 | import dns.rdatatype 9 | import dns.zonetypes 10 | 11 | 12 | @dns.immutable.immutable 13 | class ZONEMD(dns.rdata.Rdata): 14 | 15 | """ZONEMD record""" 16 | 17 | # See RFC 8976 18 | 19 | __slots__ = ["serial", "scheme", "hash_algorithm", "digest"] 20 | 21 | def __init__(self, rdclass, rdtype, serial, scheme, hash_algorithm, digest): 22 | super().__init__(rdclass, rdtype) 23 | self.serial = self._as_uint32(serial) 24 | self.scheme = dns.zonetypes.DigestScheme.make(scheme) 25 | self.hash_algorithm = dns.zonetypes.DigestHashAlgorithm.make(hash_algorithm) 26 | self.digest = self._as_bytes(digest) 27 | 28 | if self.scheme == 0: # reserved, RFC 8976 Sec. 5.2 29 | raise ValueError("scheme 0 is reserved") 30 | if self.hash_algorithm == 0: # reserved, RFC 8976 Sec. 5.3 31 | raise ValueError("hash_algorithm 0 is reserved") 32 | 33 | hasher = dns.zonetypes._digest_hashers.get(self.hash_algorithm) 34 | if hasher and hasher().digest_size != len(self.digest): 35 | raise ValueError("digest length inconsistent with hash algorithm") 36 | 37 | def to_text(self, origin=None, relativize=True, **kw): 38 | kw = kw.copy() 39 | chunksize = kw.pop("chunksize", 128) 40 | return "%d %d %d %s" % ( 41 | self.serial, 42 | self.scheme, 43 | self.hash_algorithm, 44 | dns.rdata._hexify(self.digest, chunksize=chunksize, **kw), 45 | ) 46 | 47 | @classmethod 48 | def from_text( 49 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 50 | ): 51 | serial = tok.get_uint32() 52 | scheme = tok.get_uint8() 53 | hash_algorithm = tok.get_uint8() 54 | digest = tok.concatenate_remaining_identifiers().encode() 55 | digest = binascii.unhexlify(digest) 56 | return cls(rdclass, rdtype, serial, scheme, hash_algorithm, digest) 57 | 58 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 59 | header = struct.pack("!IBB", self.serial, self.scheme, self.hash_algorithm) 60 | file.write(header) 61 | file.write(self.digest) 62 | 63 | @classmethod 64 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 65 | header = parser.get_struct("!IBB") 66 | digest = parser.get_remaining() 67 | return cls(rdclass, rdtype, header[0], header[1], header[2], digest) 68 | -------------------------------------------------------------------------------- /dns/rdtypes/ANY/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """Class ANY (generic) rdata type classes.""" 19 | 20 | __all__ = [ 21 | "AFSDB", 22 | "AMTRELAY", 23 | "AVC", 24 | "CAA", 25 | "CDNSKEY", 26 | "CDS", 27 | "CERT", 28 | "CNAME", 29 | "CSYNC", 30 | "DLV", 31 | "DNAME", 32 | "DNSKEY", 33 | "DS", 34 | "EUI48", 35 | "EUI64", 36 | "GPOS", 37 | "HINFO", 38 | "HIP", 39 | "ISDN", 40 | "L32", 41 | "L64", 42 | "LOC", 43 | "LP", 44 | "MX", 45 | "NID", 46 | "NINFO", 47 | "NS", 48 | "NSEC", 49 | "NSEC3", 50 | "NSEC3PARAM", 51 | "OPENPGPKEY", 52 | "OPT", 53 | "PTR", 54 | "RP", 55 | "RRSIG", 56 | "RT", 57 | "SMIMEA", 58 | "SOA", 59 | "SPF", 60 | "SSHFP", 61 | "TKEY", 62 | "TLSA", 63 | "TSIG", 64 | "TXT", 65 | "URI", 66 | "X25", 67 | "ZONEMD", 68 | ] 69 | -------------------------------------------------------------------------------- /dns/rdtypes/CH/A.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.rdtypes.mxbase 21 | import dns.immutable 22 | 23 | 24 | @dns.immutable.immutable 25 | class A(dns.rdata.Rdata): 26 | 27 | """A record for Chaosnet""" 28 | 29 | # domain: the domain of the address 30 | # address: the 16-bit address 31 | 32 | __slots__ = ["domain", "address"] 33 | 34 | def __init__(self, rdclass, rdtype, domain, address): 35 | super().__init__(rdclass, rdtype) 36 | self.domain = self._as_name(domain) 37 | self.address = self._as_uint16(address) 38 | 39 | def to_text(self, origin=None, relativize=True, **kw): 40 | domain = self.domain.choose_relativity(origin, relativize) 41 | return "%s %o" % (domain, self.address) 42 | 43 | @classmethod 44 | def from_text( 45 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 46 | ): 47 | domain = tok.get_name(origin, relativize, relativize_to) 48 | address = tok.get_uint16(base=8) 49 | return cls(rdclass, rdtype, domain, address) 50 | 51 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 52 | self.domain.to_wire(file, compress, origin, canonicalize) 53 | pref = struct.pack("!H", self.address) 54 | file.write(pref) 55 | 56 | @classmethod 57 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 58 | domain = parser.get_name(origin) 59 | address = parser.get_uint16() 60 | return cls(rdclass, rdtype, domain, address) 61 | -------------------------------------------------------------------------------- /dns/rdtypes/CH/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """Class CH rdata type classes.""" 19 | 20 | __all__ = [ 21 | "A", 22 | ] 23 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/A.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.exception 19 | import dns.immutable 20 | import dns.ipv4 21 | import dns.rdata 22 | import dns.tokenizer 23 | 24 | 25 | @dns.immutable.immutable 26 | class A(dns.rdata.Rdata): 27 | 28 | """A record.""" 29 | 30 | __slots__ = ["address"] 31 | 32 | def __init__(self, rdclass, rdtype, address): 33 | super().__init__(rdclass, rdtype) 34 | self.address = self._as_ipv4_address(address) 35 | 36 | def to_text(self, origin=None, relativize=True, **kw): 37 | return self.address 38 | 39 | @classmethod 40 | def from_text( 41 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 42 | ): 43 | address = tok.get_identifier() 44 | return cls(rdclass, rdtype, address) 45 | 46 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 47 | file.write(dns.ipv4.inet_aton(self.address)) 48 | 49 | @classmethod 50 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 51 | address = parser.get_remaining() 52 | return cls(rdclass, rdtype, address) 53 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/AAAA.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.exception 19 | import dns.immutable 20 | import dns.ipv6 21 | import dns.rdata 22 | import dns.tokenizer 23 | 24 | 25 | @dns.immutable.immutable 26 | class AAAA(dns.rdata.Rdata): 27 | 28 | """AAAA record.""" 29 | 30 | __slots__ = ["address"] 31 | 32 | def __init__(self, rdclass, rdtype, address): 33 | super().__init__(rdclass, rdtype) 34 | self.address = self._as_ipv6_address(address) 35 | 36 | def to_text(self, origin=None, relativize=True, **kw): 37 | return self.address 38 | 39 | @classmethod 40 | def from_text( 41 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 42 | ): 43 | address = tok.get_identifier() 44 | return cls(rdclass, rdtype, address) 45 | 46 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 47 | file.write(dns.ipv6.inet_aton(self.address)) 48 | 49 | @classmethod 50 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 51 | address = parser.get_remaining() 52 | return cls(rdclass, rdtype, address) 53 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/DHCID.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import base64 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | 24 | 25 | @dns.immutable.immutable 26 | class DHCID(dns.rdata.Rdata): 27 | 28 | """DHCID record""" 29 | 30 | # see: RFC 4701 31 | 32 | __slots__ = ["data"] 33 | 34 | def __init__(self, rdclass, rdtype, data): 35 | super().__init__(rdclass, rdtype) 36 | self.data = self._as_bytes(data) 37 | 38 | def to_text(self, origin=None, relativize=True, **kw): 39 | return dns.rdata._base64ify(self.data, **kw) 40 | 41 | @classmethod 42 | def from_text( 43 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 44 | ): 45 | b64 = tok.concatenate_remaining_identifiers().encode() 46 | data = base64.b64decode(b64) 47 | return cls(rdclass, rdtype, data) 48 | 49 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 50 | file.write(self.data) 51 | 52 | @classmethod 53 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 54 | data = parser.get_remaining() 55 | return cls(rdclass, rdtype, data) 56 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/HTTPS.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | import dns.rdtypes.svcbbase 4 | import dns.immutable 5 | 6 | 7 | @dns.immutable.immutable 8 | class HTTPS(dns.rdtypes.svcbbase.SVCBBase): 9 | """HTTPS record""" 10 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/IPSECKEY.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | import base64 20 | 21 | import dns.exception 22 | import dns.immutable 23 | import dns.rdtypes.util 24 | 25 | 26 | class Gateway(dns.rdtypes.util.Gateway): 27 | name = "IPSECKEY gateway" 28 | 29 | 30 | @dns.immutable.immutable 31 | class IPSECKEY(dns.rdata.Rdata): 32 | 33 | """IPSECKEY record""" 34 | 35 | # see: RFC 4025 36 | 37 | __slots__ = ["precedence", "gateway_type", "algorithm", "gateway", "key"] 38 | 39 | def __init__( 40 | self, rdclass, rdtype, precedence, gateway_type, algorithm, gateway, key 41 | ): 42 | super().__init__(rdclass, rdtype) 43 | gateway = Gateway(gateway_type, gateway) 44 | self.precedence = self._as_uint8(precedence) 45 | self.gateway_type = gateway.type 46 | self.algorithm = self._as_uint8(algorithm) 47 | self.gateway = gateway.gateway 48 | self.key = self._as_bytes(key) 49 | 50 | def to_text(self, origin=None, relativize=True, **kw): 51 | gateway = Gateway(self.gateway_type, self.gateway).to_text(origin, relativize) 52 | return "%d %d %d %s %s" % ( 53 | self.precedence, 54 | self.gateway_type, 55 | self.algorithm, 56 | gateway, 57 | dns.rdata._base64ify(self.key, **kw), 58 | ) 59 | 60 | @classmethod 61 | def from_text( 62 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 63 | ): 64 | precedence = tok.get_uint8() 65 | gateway_type = tok.get_uint8() 66 | algorithm = tok.get_uint8() 67 | gateway = Gateway.from_text( 68 | gateway_type, tok, origin, relativize, relativize_to 69 | ) 70 | b64 = tok.concatenate_remaining_identifiers().encode() 71 | key = base64.b64decode(b64) 72 | return cls( 73 | rdclass, rdtype, precedence, gateway_type, algorithm, gateway.gateway, key 74 | ) 75 | 76 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 77 | header = struct.pack("!BBB", self.precedence, self.gateway_type, self.algorithm) 78 | file.write(header) 79 | Gateway(self.gateway_type, self.gateway).to_wire( 80 | file, compress, origin, canonicalize 81 | ) 82 | file.write(self.key) 83 | 84 | @classmethod 85 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 86 | header = parser.get_struct("!BBB") 87 | gateway_type = header[1] 88 | gateway = Gateway.from_wire_parser(gateway_type, parser, origin) 89 | key = parser.get_remaining() 90 | return cls( 91 | rdclass, rdtype, header[0], gateway_type, header[2], gateway.gateway, key 92 | ) 93 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/KX.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.mxbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class KX(dns.rdtypes.mxbase.UncompressedDowncasingMX): 24 | 25 | """KX record""" 26 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/NAPTR.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.name 23 | import dns.rdata 24 | import dns.rdtypes.util 25 | 26 | 27 | def _write_string(file, s): 28 | l = len(s) 29 | assert l < 256 30 | file.write(struct.pack("!B", l)) 31 | file.write(s) 32 | 33 | 34 | @dns.immutable.immutable 35 | class NAPTR(dns.rdata.Rdata): 36 | 37 | """NAPTR record""" 38 | 39 | # see: RFC 3403 40 | 41 | __slots__ = ["order", "preference", "flags", "service", "regexp", "replacement"] 42 | 43 | def __init__( 44 | self, rdclass, rdtype, order, preference, flags, service, regexp, replacement 45 | ): 46 | super().__init__(rdclass, rdtype) 47 | self.flags = self._as_bytes(flags, True, 255) 48 | self.service = self._as_bytes(service, True, 255) 49 | self.regexp = self._as_bytes(regexp, True, 255) 50 | self.order = self._as_uint16(order) 51 | self.preference = self._as_uint16(preference) 52 | self.replacement = self._as_name(replacement) 53 | 54 | def to_text(self, origin=None, relativize=True, **kw): 55 | replacement = self.replacement.choose_relativity(origin, relativize) 56 | return '%d %d "%s" "%s" "%s" %s' % ( 57 | self.order, 58 | self.preference, 59 | dns.rdata._escapify(self.flags), 60 | dns.rdata._escapify(self.service), 61 | dns.rdata._escapify(self.regexp), 62 | replacement, 63 | ) 64 | 65 | @classmethod 66 | def from_text( 67 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 68 | ): 69 | order = tok.get_uint16() 70 | preference = tok.get_uint16() 71 | flags = tok.get_string() 72 | service = tok.get_string() 73 | regexp = tok.get_string() 74 | replacement = tok.get_name(origin, relativize, relativize_to) 75 | return cls( 76 | rdclass, rdtype, order, preference, flags, service, regexp, replacement 77 | ) 78 | 79 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 80 | two_ints = struct.pack("!HH", self.order, self.preference) 81 | file.write(two_ints) 82 | _write_string(file, self.flags) 83 | _write_string(file, self.service) 84 | _write_string(file, self.regexp) 85 | self.replacement.to_wire(file, compress, origin, canonicalize) 86 | 87 | @classmethod 88 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 89 | (order, preference) = parser.get_struct("!HH") 90 | strings = [] 91 | for _ in range(3): 92 | s = parser.get_counted_bytes() 93 | strings.append(s) 94 | replacement = parser.get_name(origin) 95 | return cls( 96 | rdclass, 97 | rdtype, 98 | order, 99 | preference, 100 | strings[0], 101 | strings[1], 102 | strings[2], 103 | replacement, 104 | ) 105 | 106 | def _processing_priority(self): 107 | return (self.order, self.preference) 108 | 109 | @classmethod 110 | def _processing_order(cls, iterable): 111 | return dns.rdtypes.util.priority_processing_order(iterable) 112 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/NSAP.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import binascii 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | import dns.tokenizer 24 | 25 | 26 | @dns.immutable.immutable 27 | class NSAP(dns.rdata.Rdata): 28 | 29 | """NSAP record.""" 30 | 31 | # see: RFC 1706 32 | 33 | __slots__ = ["address"] 34 | 35 | def __init__(self, rdclass, rdtype, address): 36 | super().__init__(rdclass, rdtype) 37 | self.address = self._as_bytes(address) 38 | 39 | def to_text(self, origin=None, relativize=True, **kw): 40 | return "0x%s" % binascii.hexlify(self.address).decode() 41 | 42 | @classmethod 43 | def from_text( 44 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 45 | ): 46 | address = tok.get_string() 47 | if address[0:2] != "0x": 48 | raise dns.exception.SyntaxError("string does not start with 0x") 49 | address = address[2:].replace(".", "") 50 | if len(address) % 2 != 0: 51 | raise dns.exception.SyntaxError("hexstring has odd length") 52 | address = binascii.unhexlify(address.encode()) 53 | return cls(rdclass, rdtype, address) 54 | 55 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 56 | file.write(self.address) 57 | 58 | @classmethod 59 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 60 | address = parser.get_remaining() 61 | return cls(rdclass, rdtype, address) 62 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/NSAP_PTR.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import dns.rdtypes.nsbase 19 | import dns.immutable 20 | 21 | 22 | @dns.immutable.immutable 23 | class NSAP_PTR(dns.rdtypes.nsbase.UncompressedNS): 24 | 25 | """NSAP-PTR record""" 26 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/PX.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | import dns.rdtypes.util 24 | import dns.name 25 | 26 | 27 | @dns.immutable.immutable 28 | class PX(dns.rdata.Rdata): 29 | 30 | """PX record.""" 31 | 32 | # see: RFC 2163 33 | 34 | __slots__ = ["preference", "map822", "mapx400"] 35 | 36 | def __init__(self, rdclass, rdtype, preference, map822, mapx400): 37 | super().__init__(rdclass, rdtype) 38 | self.preference = self._as_uint16(preference) 39 | self.map822 = self._as_name(map822) 40 | self.mapx400 = self._as_name(mapx400) 41 | 42 | def to_text(self, origin=None, relativize=True, **kw): 43 | map822 = self.map822.choose_relativity(origin, relativize) 44 | mapx400 = self.mapx400.choose_relativity(origin, relativize) 45 | return "%d %s %s" % (self.preference, map822, mapx400) 46 | 47 | @classmethod 48 | def from_text( 49 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 50 | ): 51 | preference = tok.get_uint16() 52 | map822 = tok.get_name(origin, relativize, relativize_to) 53 | mapx400 = tok.get_name(origin, relativize, relativize_to) 54 | return cls(rdclass, rdtype, preference, map822, mapx400) 55 | 56 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 57 | pref = struct.pack("!H", self.preference) 58 | file.write(pref) 59 | self.map822.to_wire(file, None, origin, canonicalize) 60 | self.mapx400.to_wire(file, None, origin, canonicalize) 61 | 62 | @classmethod 63 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 64 | preference = parser.get_uint16() 65 | map822 = parser.get_name(origin) 66 | mapx400 = parser.get_name(origin) 67 | return cls(rdclass, rdtype, preference, map822, mapx400) 68 | 69 | def _processing_priority(self): 70 | return self.preference 71 | 72 | @classmethod 73 | def _processing_order(cls, iterable): 74 | return dns.rdtypes.util.priority_processing_order(iterable) 75 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/SRV.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | import dns.rdtypes.util 24 | import dns.name 25 | 26 | 27 | @dns.immutable.immutable 28 | class SRV(dns.rdata.Rdata): 29 | 30 | """SRV record""" 31 | 32 | # see: RFC 2782 33 | 34 | __slots__ = ["priority", "weight", "port", "target"] 35 | 36 | def __init__(self, rdclass, rdtype, priority, weight, port, target): 37 | super().__init__(rdclass, rdtype) 38 | self.priority = self._as_uint16(priority) 39 | self.weight = self._as_uint16(weight) 40 | self.port = self._as_uint16(port) 41 | self.target = self._as_name(target) 42 | 43 | def to_text(self, origin=None, relativize=True, **kw): 44 | target = self.target.choose_relativity(origin, relativize) 45 | return "%d %d %d %s" % (self.priority, self.weight, self.port, target) 46 | 47 | @classmethod 48 | def from_text( 49 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 50 | ): 51 | priority = tok.get_uint16() 52 | weight = tok.get_uint16() 53 | port = tok.get_uint16() 54 | target = tok.get_name(origin, relativize, relativize_to) 55 | return cls(rdclass, rdtype, priority, weight, port, target) 56 | 57 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 58 | three_ints = struct.pack("!HHH", self.priority, self.weight, self.port) 59 | file.write(three_ints) 60 | self.target.to_wire(file, compress, origin, canonicalize) 61 | 62 | @classmethod 63 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 64 | (priority, weight, port) = parser.get_struct("!HHH") 65 | target = parser.get_name(origin) 66 | return cls(rdclass, rdtype, priority, weight, port, target) 67 | 68 | def _processing_priority(self): 69 | return self.priority 70 | 71 | def _processing_weight(self): 72 | return self.weight 73 | 74 | @classmethod 75 | def _processing_order(cls, iterable): 76 | return dns.rdtypes.util.weighted_processing_order(iterable) 77 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/SVCB.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | import dns.rdtypes.svcbbase 4 | import dns.immutable 5 | 6 | 7 | @dns.immutable.immutable 8 | class SVCB(dns.rdtypes.svcbbase.SVCBBase): 9 | """SVCB record""" 10 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/WKS.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import socket 19 | import struct 20 | 21 | import dns.ipv4 22 | import dns.immutable 23 | import dns.rdata 24 | 25 | try: 26 | _proto_tcp = socket.getprotobyname("tcp") 27 | _proto_udp = socket.getprotobyname("udp") 28 | except OSError: 29 | # Fall back to defaults in case /etc/protocols is unavailable. 30 | _proto_tcp = 6 31 | _proto_udp = 17 32 | 33 | 34 | @dns.immutable.immutable 35 | class WKS(dns.rdata.Rdata): 36 | 37 | """WKS record""" 38 | 39 | # see: RFC 1035 40 | 41 | __slots__ = ["address", "protocol", "bitmap"] 42 | 43 | def __init__(self, rdclass, rdtype, address, protocol, bitmap): 44 | super().__init__(rdclass, rdtype) 45 | self.address = self._as_ipv4_address(address) 46 | self.protocol = self._as_uint8(protocol) 47 | self.bitmap = self._as_bytes(bitmap) 48 | 49 | def to_text(self, origin=None, relativize=True, **kw): 50 | bits = [] 51 | for i, byte in enumerate(self.bitmap): 52 | for j in range(0, 8): 53 | if byte & (0x80 >> j): 54 | bits.append(str(i * 8 + j)) 55 | text = " ".join(bits) 56 | return "%s %d %s" % (self.address, self.protocol, text) 57 | 58 | @classmethod 59 | def from_text( 60 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 61 | ): 62 | address = tok.get_string() 63 | protocol = tok.get_string() 64 | if protocol.isdigit(): 65 | protocol = int(protocol) 66 | else: 67 | protocol = socket.getprotobyname(protocol) 68 | bitmap = bytearray() 69 | for token in tok.get_remaining(): 70 | value = token.unescape().value 71 | if value.isdigit(): 72 | serv = int(value) 73 | else: 74 | if protocol != _proto_udp and protocol != _proto_tcp: 75 | raise NotImplementedError("protocol must be TCP or UDP") 76 | if protocol == _proto_udp: 77 | protocol_text = "udp" 78 | else: 79 | protocol_text = "tcp" 80 | serv = socket.getservbyname(value, protocol_text) 81 | i = serv // 8 82 | l = len(bitmap) 83 | if l < i + 1: 84 | for _ in range(l, i + 1): 85 | bitmap.append(0) 86 | bitmap[i] = bitmap[i] | (0x80 >> (serv % 8)) 87 | bitmap = dns.rdata._truncate_bitmap(bitmap) 88 | return cls(rdclass, rdtype, address, protocol, bitmap) 89 | 90 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 91 | file.write(dns.ipv4.inet_aton(self.address)) 92 | protocol = struct.pack("!B", self.protocol) 93 | file.write(protocol) 94 | file.write(self.bitmap) 95 | 96 | @classmethod 97 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 98 | address = parser.get_bytes(4) 99 | protocol = parser.get_uint8() 100 | bitmap = parser.get_remaining() 101 | return cls(rdclass, rdtype, address, protocol, bitmap) 102 | -------------------------------------------------------------------------------- /dns/rdtypes/IN/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """Class IN rdata type classes.""" 19 | 20 | __all__ = [ 21 | "A", 22 | "AAAA", 23 | "APL", 24 | "DHCID", 25 | "HTTPS", 26 | "IPSECKEY", 27 | "KX", 28 | "NAPTR", 29 | "NSAP", 30 | "NSAP_PTR", 31 | "PX", 32 | "SRV", 33 | "SVCB", 34 | "WKS", 35 | ] 36 | -------------------------------------------------------------------------------- /dns/rdtypes/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """DNS rdata type classes""" 19 | 20 | __all__ = [ 21 | "ANY", 22 | "IN", 23 | "CH", 24 | "dnskeybase", 25 | "dsbase", 26 | "euibase", 27 | "mxbase", 28 | "nsbase", 29 | "svcbbase", 30 | "tlsabase", 31 | "txtbase", 32 | "util", 33 | ] 34 | -------------------------------------------------------------------------------- /dns/rdtypes/dnskeybase.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import base64 19 | import enum 20 | import struct 21 | 22 | import dns.exception 23 | import dns.immutable 24 | import dns.dnssectypes 25 | import dns.rdata 26 | 27 | # wildcard import 28 | __all__ = ["SEP", "REVOKE", "ZONE"] # noqa: F822 29 | 30 | 31 | class Flag(enum.IntFlag): 32 | SEP = 0x0001 33 | REVOKE = 0x0080 34 | ZONE = 0x0100 35 | 36 | 37 | @dns.immutable.immutable 38 | class DNSKEYBase(dns.rdata.Rdata): 39 | 40 | """Base class for rdata that is like a DNSKEY record""" 41 | 42 | __slots__ = ["flags", "protocol", "algorithm", "key"] 43 | 44 | def __init__(self, rdclass, rdtype, flags, protocol, algorithm, key): 45 | super().__init__(rdclass, rdtype) 46 | self.flags = self._as_uint16(flags) 47 | self.protocol = self._as_uint8(protocol) 48 | self.algorithm = dns.dnssectypes.Algorithm.make(algorithm) 49 | self.key = self._as_bytes(key) 50 | 51 | def to_text(self, origin=None, relativize=True, **kw): 52 | return "%d %d %d %s" % ( 53 | self.flags, 54 | self.protocol, 55 | self.algorithm, 56 | dns.rdata._base64ify(self.key, **kw), 57 | ) 58 | 59 | @classmethod 60 | def from_text( 61 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 62 | ): 63 | flags = tok.get_uint16() 64 | protocol = tok.get_uint8() 65 | algorithm = tok.get_string() 66 | b64 = tok.concatenate_remaining_identifiers().encode() 67 | key = base64.b64decode(b64) 68 | return cls(rdclass, rdtype, flags, protocol, algorithm, key) 69 | 70 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 71 | header = struct.pack("!HBB", self.flags, self.protocol, self.algorithm) 72 | file.write(header) 73 | file.write(self.key) 74 | 75 | @classmethod 76 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 77 | header = parser.get_struct("!HBB") 78 | key = parser.get_remaining() 79 | return cls(rdclass, rdtype, header[0], header[1], header[2], key) 80 | 81 | 82 | ### BEGIN generated Flag constants 83 | 84 | SEP = Flag.SEP 85 | REVOKE = Flag.REVOKE 86 | ZONE = Flag.ZONE 87 | 88 | ### END generated Flag constants 89 | -------------------------------------------------------------------------------- /dns/rdtypes/dsbase.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2010, 2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | import binascii 20 | 21 | import dns.dnssectypes 22 | import dns.immutable 23 | import dns.rdata 24 | import dns.rdatatype 25 | 26 | 27 | @dns.immutable.immutable 28 | class DSBase(dns.rdata.Rdata): 29 | 30 | """Base class for rdata that is like a DS record""" 31 | 32 | __slots__ = ["key_tag", "algorithm", "digest_type", "digest"] 33 | 34 | # Digest types registry: 35 | # https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml 36 | _digest_length_by_type = { 37 | 1: 20, # SHA-1, RFC 3658 Sec. 2.4 38 | 2: 32, # SHA-256, RFC 4509 Sec. 2.2 39 | 3: 32, # GOST R 34.11-94, RFC 5933 Sec. 4 in conjunction with RFC 4490 Sec. 2.1 40 | 4: 48, # SHA-384, RFC 6605 Sec. 2 41 | } 42 | 43 | def __init__(self, rdclass, rdtype, key_tag, algorithm, digest_type, digest): 44 | super().__init__(rdclass, rdtype) 45 | self.key_tag = self._as_uint16(key_tag) 46 | self.algorithm = dns.dnssectypes.Algorithm.make(algorithm) 47 | self.digest_type = self._as_uint8(digest_type) 48 | self.digest = self._as_bytes(digest) 49 | try: 50 | if len(self.digest) != self._digest_length_by_type[self.digest_type]: 51 | raise ValueError("digest length inconsistent with digest type") 52 | except KeyError: 53 | if self.digest_type == 0: # reserved, RFC 3658 Sec. 2.4 54 | raise ValueError("digest type 0 is reserved") 55 | 56 | def to_text(self, origin=None, relativize=True, **kw): 57 | kw = kw.copy() 58 | chunksize = kw.pop("chunksize", 128) 59 | return "%d %d %d %s" % ( 60 | self.key_tag, 61 | self.algorithm, 62 | self.digest_type, 63 | dns.rdata._hexify(self.digest, chunksize=chunksize, **kw), 64 | ) 65 | 66 | @classmethod 67 | def from_text( 68 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 69 | ): 70 | key_tag = tok.get_uint16() 71 | algorithm = tok.get_string() 72 | digest_type = tok.get_uint8() 73 | digest = tok.concatenate_remaining_identifiers().encode() 74 | digest = binascii.unhexlify(digest) 75 | return cls(rdclass, rdtype, key_tag, algorithm, digest_type, digest) 76 | 77 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 78 | header = struct.pack("!HBB", self.key_tag, self.algorithm, self.digest_type) 79 | file.write(header) 80 | file.write(self.digest) 81 | 82 | @classmethod 83 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 84 | header = parser.get_struct("!HBB") 85 | digest = parser.get_remaining() 86 | return cls(rdclass, rdtype, header[0], header[1], header[2], digest) 87 | -------------------------------------------------------------------------------- /dns/rdtypes/euibase.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015 Red Hat, Inc. 2 | # Author: Petr Spacek 3 | # 4 | # Permission to use, copy, modify, and distribute this software and its 5 | # documentation for any purpose with or without fee is hereby granted, 6 | # provided that the above copyright notice and this permission notice 7 | # appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | import binascii 18 | 19 | import dns.rdata 20 | import dns.immutable 21 | 22 | 23 | @dns.immutable.immutable 24 | class EUIBase(dns.rdata.Rdata): 25 | 26 | """EUIxx record""" 27 | 28 | # see: rfc7043.txt 29 | 30 | __slots__ = ["eui"] 31 | # define these in subclasses 32 | # byte_len = 6 # 0123456789ab (in hex) 33 | # text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab 34 | 35 | def __init__(self, rdclass, rdtype, eui): 36 | super().__init__(rdclass, rdtype) 37 | self.eui = self._as_bytes(eui) 38 | if len(self.eui) != self.byte_len: 39 | raise dns.exception.FormError( 40 | "EUI%s rdata has to have %s bytes" % (self.byte_len * 8, self.byte_len) 41 | ) 42 | 43 | def to_text(self, origin=None, relativize=True, **kw): 44 | return dns.rdata._hexify(self.eui, chunksize=2, separator=b"-", **kw) 45 | 46 | @classmethod 47 | def from_text( 48 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 49 | ): 50 | text = tok.get_string() 51 | if len(text) != cls.text_len: 52 | raise dns.exception.SyntaxError( 53 | "Input text must have %s characters" % cls.text_len 54 | ) 55 | for i in range(2, cls.byte_len * 3 - 1, 3): 56 | if text[i] != "-": 57 | raise dns.exception.SyntaxError("Dash expected at position %s" % i) 58 | text = text.replace("-", "") 59 | try: 60 | data = binascii.unhexlify(text.encode()) 61 | except (ValueError, TypeError) as ex: 62 | raise dns.exception.SyntaxError("Hex decoding error: %s" % str(ex)) 63 | return cls(rdclass, rdtype, data) 64 | 65 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 66 | file.write(self.eui) 67 | 68 | @classmethod 69 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 70 | eui = parser.get_bytes(cls.byte_len) 71 | return cls(rdclass, rdtype, eui) 72 | -------------------------------------------------------------------------------- /dns/rdtypes/mxbase.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """MX-like base classes.""" 19 | 20 | import struct 21 | 22 | import dns.exception 23 | import dns.immutable 24 | import dns.rdata 25 | import dns.name 26 | import dns.rdtypes.util 27 | 28 | 29 | @dns.immutable.immutable 30 | class MXBase(dns.rdata.Rdata): 31 | 32 | """Base class for rdata that is like an MX record.""" 33 | 34 | __slots__ = ["preference", "exchange"] 35 | 36 | def __init__(self, rdclass, rdtype, preference, exchange): 37 | super().__init__(rdclass, rdtype) 38 | self.preference = self._as_uint16(preference) 39 | self.exchange = self._as_name(exchange) 40 | 41 | def to_text(self, origin=None, relativize=True, **kw): 42 | exchange = self.exchange.choose_relativity(origin, relativize) 43 | return "%d %s" % (self.preference, exchange) 44 | 45 | @classmethod 46 | def from_text( 47 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 48 | ): 49 | preference = tok.get_uint16() 50 | exchange = tok.get_name(origin, relativize, relativize_to) 51 | return cls(rdclass, rdtype, preference, exchange) 52 | 53 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 54 | pref = struct.pack("!H", self.preference) 55 | file.write(pref) 56 | self.exchange.to_wire(file, compress, origin, canonicalize) 57 | 58 | @classmethod 59 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 60 | preference = parser.get_uint16() 61 | exchange = parser.get_name(origin) 62 | return cls(rdclass, rdtype, preference, exchange) 63 | 64 | def _processing_priority(self): 65 | return self.preference 66 | 67 | @classmethod 68 | def _processing_order(cls, iterable): 69 | return dns.rdtypes.util.priority_processing_order(iterable) 70 | 71 | 72 | @dns.immutable.immutable 73 | class UncompressedMX(MXBase): 74 | 75 | """Base class for rdata that is like an MX record, but whose name 76 | is not compressed when converted to DNS wire format, and whose 77 | digestable form is not downcased.""" 78 | 79 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 80 | super()._to_wire(file, None, origin, False) 81 | 82 | 83 | @dns.immutable.immutable 84 | class UncompressedDowncasingMX(MXBase): 85 | 86 | """Base class for rdata that is like an MX record, but whose name 87 | is not compressed when convert to DNS wire format.""" 88 | 89 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 90 | super()._to_wire(file, None, origin, canonicalize) 91 | -------------------------------------------------------------------------------- /dns/rdtypes/nsbase.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """NS-like base classes.""" 19 | 20 | import dns.exception 21 | import dns.immutable 22 | import dns.rdata 23 | import dns.name 24 | 25 | 26 | @dns.immutable.immutable 27 | class NSBase(dns.rdata.Rdata): 28 | 29 | """Base class for rdata that is like an NS record.""" 30 | 31 | __slots__ = ["target"] 32 | 33 | def __init__(self, rdclass, rdtype, target): 34 | super().__init__(rdclass, rdtype) 35 | self.target = self._as_name(target) 36 | 37 | def to_text(self, origin=None, relativize=True, **kw): 38 | target = self.target.choose_relativity(origin, relativize) 39 | return str(target) 40 | 41 | @classmethod 42 | def from_text( 43 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 44 | ): 45 | target = tok.get_name(origin, relativize, relativize_to) 46 | return cls(rdclass, rdtype, target) 47 | 48 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 49 | self.target.to_wire(file, compress, origin, canonicalize) 50 | 51 | @classmethod 52 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 53 | target = parser.get_name(origin) 54 | return cls(rdclass, rdtype, target) 55 | 56 | 57 | @dns.immutable.immutable 58 | class UncompressedNS(NSBase): 59 | 60 | """Base class for rdata that is like an NS record, but whose name 61 | is not compressed when convert to DNS wire format, and whose 62 | digestable form is not downcased.""" 63 | 64 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 65 | self.target.to_wire(file, None, origin, False) 66 | -------------------------------------------------------------------------------- /dns/rdtypes/tlsabase.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2005-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | import struct 19 | import binascii 20 | 21 | import dns.rdata 22 | import dns.immutable 23 | import dns.rdatatype 24 | 25 | 26 | @dns.immutable.immutable 27 | class TLSABase(dns.rdata.Rdata): 28 | 29 | """Base class for TLSA and SMIMEA records""" 30 | 31 | # see: RFC 6698 32 | 33 | __slots__ = ["usage", "selector", "mtype", "cert"] 34 | 35 | def __init__(self, rdclass, rdtype, usage, selector, mtype, cert): 36 | super().__init__(rdclass, rdtype) 37 | self.usage = self._as_uint8(usage) 38 | self.selector = self._as_uint8(selector) 39 | self.mtype = self._as_uint8(mtype) 40 | self.cert = self._as_bytes(cert) 41 | 42 | def to_text(self, origin=None, relativize=True, **kw): 43 | kw = kw.copy() 44 | chunksize = kw.pop("chunksize", 128) 45 | return "%d %d %d %s" % ( 46 | self.usage, 47 | self.selector, 48 | self.mtype, 49 | dns.rdata._hexify(self.cert, chunksize=chunksize, **kw), 50 | ) 51 | 52 | @classmethod 53 | def from_text( 54 | cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None 55 | ): 56 | usage = tok.get_uint8() 57 | selector = tok.get_uint8() 58 | mtype = tok.get_uint8() 59 | cert = tok.concatenate_remaining_identifiers().encode() 60 | cert = binascii.unhexlify(cert) 61 | return cls(rdclass, rdtype, usage, selector, mtype, cert) 62 | 63 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 64 | header = struct.pack("!BBB", self.usage, self.selector, self.mtype) 65 | file.write(header) 66 | file.write(self.cert) 67 | 68 | @classmethod 69 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 70 | header = parser.get_struct("BBB") 71 | cert = parser.get_remaining() 72 | return cls(rdclass, rdtype, header[0], header[1], header[2], cert) 73 | -------------------------------------------------------------------------------- /dns/rdtypes/txtbase.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2006-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """TXT-like base class.""" 19 | 20 | from typing import Any, Dict, Iterable, Optional, Tuple, Union 21 | 22 | import struct 23 | 24 | import dns.exception 25 | import dns.immutable 26 | import dns.rdata 27 | import dns.tokenizer 28 | 29 | 30 | @dns.immutable.immutable 31 | class TXTBase(dns.rdata.Rdata): 32 | 33 | """Base class for rdata that is like a TXT record (see RFC 1035).""" 34 | 35 | __slots__ = ["strings"] 36 | 37 | def __init__( 38 | self, 39 | rdclass: dns.rdataclass.RdataClass, 40 | rdtype: dns.rdatatype.RdataType, 41 | strings: Iterable[Union[bytes, str]], 42 | ): 43 | """Initialize a TXT-like rdata. 44 | 45 | *rdclass*, an ``int`` is the rdataclass of the Rdata. 46 | 47 | *rdtype*, an ``int`` is the rdatatype of the Rdata. 48 | 49 | *strings*, a tuple of ``bytes`` 50 | """ 51 | super().__init__(rdclass, rdtype) 52 | self.strings: Tuple[bytes] = self._as_tuple( 53 | strings, lambda x: self._as_bytes(x, True, 255) 54 | ) 55 | 56 | def to_text( 57 | self, 58 | origin: Optional[dns.name.Name] = None, 59 | relativize: bool = True, 60 | **kw: Dict[str, Any] 61 | ) -> str: 62 | txt = "" 63 | prefix = "" 64 | for s in self.strings: 65 | txt += '{}"{}"'.format(prefix, dns.rdata._escapify(s)) 66 | prefix = " " 67 | return txt 68 | 69 | @classmethod 70 | def from_text( 71 | cls, 72 | rdclass: dns.rdataclass.RdataClass, 73 | rdtype: dns.rdatatype.RdataType, 74 | tok: dns.tokenizer.Tokenizer, 75 | origin: Optional[dns.name.Name] = None, 76 | relativize: bool = True, 77 | relativize_to: Optional[dns.name.Name] = None, 78 | ) -> dns.rdata.Rdata: 79 | strings = [] 80 | for token in tok.get_remaining(): 81 | token = token.unescape_to_bytes() 82 | # The 'if' below is always true in the current code, but we 83 | # are leaving this check in in case things change some day. 84 | if not ( 85 | token.is_quoted_string() or token.is_identifier() 86 | ): # pragma: no cover 87 | raise dns.exception.SyntaxError("expected a string") 88 | if len(token.value) > 255: 89 | raise dns.exception.SyntaxError("string too long") 90 | strings.append(token.value) 91 | if len(strings) == 0: 92 | raise dns.exception.UnexpectedEnd 93 | return cls(rdclass, rdtype, strings) 94 | 95 | def _to_wire(self, file, compress=None, origin=None, canonicalize=False): 96 | for s in self.strings: 97 | l = len(s) 98 | assert l < 256 99 | file.write(struct.pack("!B", l)) 100 | file.write(s) 101 | 102 | @classmethod 103 | def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): 104 | strings = [] 105 | while parser.remaining() > 0: 106 | s = parser.get_counted_bytes() 107 | strings.append(s) 108 | return cls(rdclass, rdtype, strings) 109 | -------------------------------------------------------------------------------- /dns/reversename.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2006-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """DNS Reverse Map Names.""" 19 | 20 | import binascii 21 | 22 | import dns.name 23 | import dns.ipv6 24 | import dns.ipv4 25 | 26 | ipv4_reverse_domain = dns.name.from_text("in-addr.arpa.") 27 | ipv6_reverse_domain = dns.name.from_text("ip6.arpa.") 28 | 29 | 30 | def from_address( 31 | text: str, 32 | v4_origin: dns.name.Name = ipv4_reverse_domain, 33 | v6_origin: dns.name.Name = ipv6_reverse_domain, 34 | ) -> dns.name.Name: 35 | """Convert an IPv4 or IPv6 address in textual form into a Name object whose 36 | value is the reverse-map domain name of the address. 37 | 38 | *text*, a ``str``, is an IPv4 or IPv6 address in textual form 39 | (e.g. '127.0.0.1', '::1') 40 | 41 | *v4_origin*, a ``dns.name.Name`` to append to the labels corresponding to 42 | the address if the address is an IPv4 address, instead of the default 43 | (in-addr.arpa.) 44 | 45 | *v6_origin*, a ``dns.name.Name`` to append to the labels corresponding to 46 | the address if the address is an IPv6 address, instead of the default 47 | (ip6.arpa.) 48 | 49 | Raises ``dns.exception.SyntaxError`` if the address is badly formed. 50 | 51 | Returns a ``dns.name.Name``. 52 | """ 53 | 54 | try: 55 | v6 = dns.ipv6.inet_aton(text) 56 | if dns.ipv6.is_mapped(v6): 57 | parts = ["%d" % byte for byte in v6[12:]] 58 | origin = v4_origin 59 | else: 60 | parts = [x for x in str(binascii.hexlify(v6).decode())] 61 | origin = v6_origin 62 | except Exception: 63 | parts = ["%d" % byte for byte in dns.ipv4.inet_aton(text)] 64 | origin = v4_origin 65 | return dns.name.from_text(".".join(reversed(parts)), origin=origin) 66 | 67 | 68 | def to_address( 69 | name: dns.name.Name, 70 | v4_origin: dns.name.Name = ipv4_reverse_domain, 71 | v6_origin: dns.name.Name = ipv6_reverse_domain, 72 | ) -> str: 73 | """Convert a reverse map domain name into textual address form. 74 | 75 | *name*, a ``dns.name.Name``, an IPv4 or IPv6 address in reverse-map name 76 | form. 77 | 78 | *v4_origin*, a ``dns.name.Name`` representing the top-level domain for 79 | IPv4 addresses, instead of the default (in-addr.arpa.) 80 | 81 | *v6_origin*, a ``dns.name.Name`` representing the top-level domain for 82 | IPv4 addresses, instead of the default (ip6.arpa.) 83 | 84 | Raises ``dns.exception.SyntaxError`` if the name does not have a 85 | reverse-map form. 86 | 87 | Returns a ``str``. 88 | """ 89 | 90 | if name.is_subdomain(v4_origin): 91 | name = name.relativize(v4_origin) 92 | text = b".".join(reversed(name.labels)) 93 | # run through inet_ntoa() to check syntax and make pretty. 94 | return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text)) 95 | elif name.is_subdomain(v6_origin): 96 | name = name.relativize(v6_origin) 97 | labels = list(reversed(name.labels)) 98 | parts = [] 99 | for i in range(0, len(labels), 4): 100 | parts.append(b"".join(labels[i : i + 4])) 101 | text = b":".join(parts) 102 | # run through inet_ntoa() to check syntax and make pretty. 103 | return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text)) 104 | else: 105 | raise dns.exception.SyntaxError("unknown reverse-map address family") 106 | -------------------------------------------------------------------------------- /dns/serial.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | """Serial Number Arthimetic from RFC 1982""" 4 | 5 | 6 | class Serial: 7 | def __init__(self, value: int, bits: int = 32): 8 | self.value = value % 2**bits 9 | self.bits = bits 10 | 11 | def __repr__(self): 12 | return f"dns.serial.Serial({self.value}, {self.bits})" 13 | 14 | def __eq__(self, other): 15 | if isinstance(other, int): 16 | other = Serial(other, self.bits) 17 | elif not isinstance(other, Serial) or other.bits != self.bits: 18 | return NotImplemented 19 | return self.value == other.value 20 | 21 | def __ne__(self, other): 22 | if isinstance(other, int): 23 | other = Serial(other, self.bits) 24 | elif not isinstance(other, Serial) or other.bits != self.bits: 25 | return NotImplemented 26 | return self.value != other.value 27 | 28 | def __lt__(self, other): 29 | if isinstance(other, int): 30 | other = Serial(other, self.bits) 31 | elif not isinstance(other, Serial) or other.bits != self.bits: 32 | return NotImplemented 33 | if self.value < other.value and other.value - self.value < 2 ** (self.bits - 1): 34 | return True 35 | elif self.value > other.value and self.value - other.value > 2 ** ( 36 | self.bits - 1 37 | ): 38 | return True 39 | else: 40 | return False 41 | 42 | def __le__(self, other): 43 | return self == other or self < other 44 | 45 | def __gt__(self, other): 46 | if isinstance(other, int): 47 | other = Serial(other, self.bits) 48 | elif not isinstance(other, Serial) or other.bits != self.bits: 49 | return NotImplemented 50 | if self.value < other.value and other.value - self.value > 2 ** (self.bits - 1): 51 | return True 52 | elif self.value > other.value and self.value - other.value < 2 ** ( 53 | self.bits - 1 54 | ): 55 | return True 56 | else: 57 | return False 58 | 59 | def __ge__(self, other): 60 | return self == other or self > other 61 | 62 | def __add__(self, other): 63 | v = self.value 64 | if isinstance(other, Serial): 65 | delta = other.value 66 | elif isinstance(other, int): 67 | delta = other 68 | else: 69 | raise ValueError 70 | if abs(delta) > (2 ** (self.bits - 1) - 1): 71 | raise ValueError 72 | v += delta 73 | v = v % 2**self.bits 74 | return Serial(v, self.bits) 75 | 76 | def __iadd__(self, other): 77 | v = self.value 78 | if isinstance(other, Serial): 79 | delta = other.value 80 | elif isinstance(other, int): 81 | delta = other 82 | else: 83 | raise ValueError 84 | if abs(delta) > (2 ** (self.bits - 1) - 1): 85 | raise ValueError 86 | v += delta 87 | v = v % 2**self.bits 88 | self.value = v 89 | return self 90 | 91 | def __sub__(self, other): 92 | v = self.value 93 | if isinstance(other, Serial): 94 | delta = other.value 95 | elif isinstance(other, int): 96 | delta = other 97 | else: 98 | raise ValueError 99 | if abs(delta) > (2 ** (self.bits - 1) - 1): 100 | raise ValueError 101 | v -= delta 102 | v = v % 2**self.bits 103 | return Serial(v, self.bits) 104 | 105 | def __isub__(self, other): 106 | v = self.value 107 | if isinstance(other, Serial): 108 | delta = other.value 109 | elif isinstance(other, int): 110 | delta = other 111 | else: 112 | raise ValueError 113 | if abs(delta) > (2 ** (self.bits - 1) - 1): 114 | raise ValueError 115 | v -= delta 116 | v = v % 2**self.bits 117 | self.value = v 118 | return self 119 | -------------------------------------------------------------------------------- /dns/tsigkeyring.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """A place to store TSIG keys.""" 19 | 20 | from typing import Any, Dict 21 | 22 | import base64 23 | 24 | import dns.name 25 | import dns.tsig 26 | 27 | 28 | def from_text(textring: Dict[str, Any]) -> Dict[dns.name.Name, dns.tsig.Key]: 29 | """Convert a dictionary containing (textual DNS name, base64 secret) 30 | pairs into a binary keyring which has (dns.name.Name, bytes) pairs, or 31 | a dictionary containing (textual DNS name, (algorithm, base64 secret)) 32 | pairs into a binary keyring which has (dns.name.Name, dns.tsig.Key) pairs. 33 | @rtype: dict""" 34 | 35 | keyring = {} 36 | for (name, value) in textring.items(): 37 | kname = dns.name.from_text(name) 38 | if isinstance(value, str): 39 | keyring[kname] = dns.tsig.Key(kname, value).secret 40 | else: 41 | (algorithm, secret) = value 42 | keyring[kname] = dns.tsig.Key(kname, secret, algorithm) 43 | return keyring 44 | 45 | 46 | def to_text(keyring: Dict[dns.name.Name, Any]) -> Dict[str, Any]: 47 | """Convert a dictionary containing (dns.name.Name, dns.tsig.Key) pairs 48 | into a text keyring which has (textual DNS name, (textual algorithm, 49 | base64 secret)) pairs, or a dictionary containing (dns.name.Name, bytes) 50 | pairs into a text keyring which has (textual DNS name, base64 secret) pairs. 51 | @rtype: dict""" 52 | 53 | textring = {} 54 | 55 | def b64encode(secret): 56 | return base64.encodebytes(secret).decode().rstrip() 57 | 58 | for (name, key) in keyring.items(): 59 | tname = name.to_text() 60 | if isinstance(key, bytes): 61 | textring[tname] = b64encode(key) 62 | else: 63 | if isinstance(key.secret, bytes): 64 | text_secret = b64encode(key.secret) 65 | else: 66 | text_secret = str(key.secret) 67 | 68 | textring[tname] = (key.algorithm.to_text(), text_secret) 69 | return textring 70 | -------------------------------------------------------------------------------- /dns/ttl.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """DNS TTL conversion.""" 19 | 20 | from typing import Union 21 | 22 | import dns.exception 23 | 24 | # Technically TTLs are supposed to be between 0 and 2**31 - 1, with values 25 | # greater than that interpreted as 0, but we do not impose this policy here 26 | # as values > 2**31 - 1 occur in real world data. 27 | # 28 | # We leave it to applications to impose tighter bounds if desired. 29 | MAX_TTL = 2**32 - 1 30 | 31 | 32 | class BadTTL(dns.exception.SyntaxError): 33 | """DNS TTL value is not well-formed.""" 34 | 35 | 36 | def from_text(text: str) -> int: 37 | """Convert the text form of a TTL to an integer. 38 | 39 | The BIND 8 units syntax for TTLs (e.g. '1w6d4h3m10s') is supported. 40 | 41 | *text*, a ``str``, the textual TTL. 42 | 43 | Raises ``dns.ttl.BadTTL`` if the TTL is not well-formed. 44 | 45 | Returns an ``int``. 46 | """ 47 | 48 | if text.isdigit(): 49 | total = int(text) 50 | elif len(text) == 0: 51 | raise BadTTL 52 | else: 53 | total = 0 54 | current = 0 55 | need_digit = True 56 | for c in text: 57 | if c.isdigit(): 58 | current *= 10 59 | current += int(c) 60 | need_digit = False 61 | else: 62 | if need_digit: 63 | raise BadTTL 64 | c = c.lower() 65 | if c == "w": 66 | total += current * 604800 67 | elif c == "d": 68 | total += current * 86400 69 | elif c == "h": 70 | total += current * 3600 71 | elif c == "m": 72 | total += current * 60 73 | elif c == "s": 74 | total += current 75 | else: 76 | raise BadTTL("unknown unit '%s'" % c) 77 | current = 0 78 | need_digit = True 79 | if not current == 0: 80 | raise BadTTL("trailing integer") 81 | if total < 0 or total > MAX_TTL: 82 | raise BadTTL("TTL should be between 0 and 2**32 - 1 (inclusive)") 83 | return total 84 | 85 | 86 | def make(value: Union[int, str]) -> int: 87 | if isinstance(value, int): 88 | return value 89 | elif isinstance(value, str): 90 | return dns.ttl.from_text(value) 91 | else: 92 | raise ValueError("cannot convert value to TTL") 93 | -------------------------------------------------------------------------------- /dns/version.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | # Copyright (C) 2003-2017 Nominum, Inc. 4 | # 5 | # Permission to use, copy, modify, and distribute this software and its 6 | # documentation for any purpose with or without fee is hereby granted, 7 | # provided that the above copyright notice and this permission notice 8 | # appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | """dnspython release version information.""" 19 | 20 | #: MAJOR 21 | MAJOR = 2 22 | #: MINOR 23 | MINOR = 3 24 | #: MICRO 25 | MICRO = 0 26 | #: RELEASELEVEL 27 | RELEASELEVEL = 0x0F 28 | #: SERIAL 29 | SERIAL = 1 30 | 31 | if RELEASELEVEL == 0x0F: # pragma: no cover lgtm[py/unreachable-statement] 32 | #: version 33 | version = "%d.%d.%d" % (MAJOR, MINOR, MICRO) # lgtm[py/unreachable-statement] 34 | elif RELEASELEVEL == 0x00: # pragma: no cover lgtm[py/unreachable-statement] 35 | version = "%d.%d.%ddev%d" % ( 36 | MAJOR, 37 | MINOR, 38 | MICRO, 39 | SERIAL, 40 | ) # lgtm[py/unreachable-statement] 41 | elif RELEASELEVEL == 0x0C: # pragma: no cover lgtm[py/unreachable-statement] 42 | version = "%d.%d.%drc%d" % ( 43 | MAJOR, 44 | MINOR, 45 | MICRO, 46 | SERIAL, 47 | ) # lgtm[py/unreachable-statement] 48 | else: # pragma: no cover lgtm[py/unreachable-statement] 49 | version = "%d.%d.%d%x%d" % ( 50 | MAJOR, 51 | MINOR, 52 | MICRO, 53 | RELEASELEVEL, 54 | SERIAL, 55 | ) # lgtm[py/unreachable-statement] 56 | 57 | #: hexversion 58 | hexversion = MAJOR << 24 | MINOR << 16 | MICRO << 8 | RELEASELEVEL << 4 | SERIAL 59 | -------------------------------------------------------------------------------- /dns/wire.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | from typing import Iterator, Optional, Tuple 4 | 5 | import contextlib 6 | import struct 7 | 8 | import dns.exception 9 | import dns.name 10 | 11 | 12 | class Parser: 13 | def __init__(self, wire: bytes, current: int = 0): 14 | self.wire = wire 15 | self.current = 0 16 | self.end = len(self.wire) 17 | if current: 18 | self.seek(current) 19 | self.furthest = current 20 | 21 | def remaining(self) -> int: 22 | return self.end - self.current 23 | 24 | def get_bytes(self, size: int) -> bytes: 25 | assert size >= 0 26 | if size > self.remaining(): 27 | raise dns.exception.FormError 28 | output = self.wire[self.current : self.current + size] 29 | self.current += size 30 | self.furthest = max(self.furthest, self.current) 31 | return output 32 | 33 | def get_counted_bytes(self, length_size: int = 1) -> bytes: 34 | length = int.from_bytes(self.get_bytes(length_size), "big") 35 | return self.get_bytes(length) 36 | 37 | def get_remaining(self) -> bytes: 38 | return self.get_bytes(self.remaining()) 39 | 40 | def get_uint8(self) -> int: 41 | return struct.unpack("!B", self.get_bytes(1))[0] 42 | 43 | def get_uint16(self) -> int: 44 | return struct.unpack("!H", self.get_bytes(2))[0] 45 | 46 | def get_uint32(self) -> int: 47 | return struct.unpack("!I", self.get_bytes(4))[0] 48 | 49 | def get_uint48(self) -> int: 50 | return int.from_bytes(self.get_bytes(6), "big") 51 | 52 | def get_struct(self, format: str) -> Tuple: 53 | return struct.unpack(format, self.get_bytes(struct.calcsize(format))) 54 | 55 | def get_name(self, origin: Optional["dns.name.Name"] = None) -> "dns.name.Name": 56 | name = dns.name.from_wire_parser(self) 57 | if origin: 58 | name = name.relativize(origin) 59 | return name 60 | 61 | def seek(self, where: int) -> None: 62 | # Note that seeking to the end is OK! (If you try to read 63 | # after such a seek, you'll get an exception as expected.) 64 | if where < 0 or where > self.end: 65 | raise dns.exception.FormError 66 | self.current = where 67 | 68 | @contextlib.contextmanager 69 | def restrict_to(self, size: int) -> Iterator: 70 | assert size >= 0 71 | if size > self.remaining(): 72 | raise dns.exception.FormError 73 | saved_end = self.end 74 | try: 75 | self.end = self.current + size 76 | yield 77 | # We make this check here and not in the finally as we 78 | # don't want to raise if we're already raising for some 79 | # other reason. 80 | if self.current != self.end: 81 | raise dns.exception.FormError 82 | finally: 83 | self.end = saved_end 84 | 85 | @contextlib.contextmanager 86 | def restore_furthest(self) -> Iterator: 87 | try: 88 | yield None 89 | finally: 90 | self.current = self.furthest 91 | -------------------------------------------------------------------------------- /dns/zonetypes.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 | 3 | """Common zone-related types.""" 4 | 5 | # This is a separate file to avoid import circularity between dns.zone and 6 | # the implementation of the ZONEMD type. 7 | 8 | import hashlib 9 | 10 | import dns.enum 11 | 12 | 13 | class DigestScheme(dns.enum.IntEnum): 14 | """ZONEMD Scheme""" 15 | 16 | SIMPLE = 1 17 | 18 | @classmethod 19 | def _maximum(cls): 20 | return 255 21 | 22 | 23 | class DigestHashAlgorithm(dns.enum.IntEnum): 24 | """ZONEMD Hash Algorithm""" 25 | 26 | SHA384 = 1 27 | SHA512 = 2 28 | 29 | @classmethod 30 | def _maximum(cls): 31 | return 255 32 | 33 | 34 | _digest_hashers = { 35 | DigestHashAlgorithm.SHA384: hashlib.sha384, 36 | DigestHashAlgorithm.SHA512: hashlib.sha512, 37 | } 38 | -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nneonneo/iOS-SOCKS-Server/e8722f91418e9c0897adbb2041d7cc214ed82738/lib/__init__.py -------------------------------------------------------------------------------- /lib/ifaddrs.py: -------------------------------------------------------------------------------- 1 | # adapted from https://stackoverflow.com/a/30495952/1204143 2 | import collections 3 | import socket 4 | from ctypes import ( 5 | CDLL, 6 | POINTER, 7 | Structure, 8 | addressof, 9 | byref, 10 | c_char, 11 | c_char_p, 12 | c_int, 13 | c_ubyte, 14 | c_uint, 15 | c_ushort, 16 | c_void_p, 17 | cast, 18 | create_string_buffer, 19 | memmove, 20 | memset, 21 | sizeof, 22 | ) 23 | 24 | 25 | def get_sockaddr(sockaddr_p): 26 | if not sockaddr_p: 27 | return None 28 | sa_len, sa_family = cast(sockaddr_p, POINTER(c_ubyte * 2)).contents 29 | if sa_family == socket.AF_INET: 30 | sin = copy_zerofill(SockaddrIn(), sockaddr_p, sa_len) 31 | buf = create_string_buffer(16 + 1) 32 | libc.inet_ntop(sa_family, sin.sin_addr, buf) 33 | return SocketAddress(sa_family, buf.value.decode()) 34 | elif sa_family == socket.AF_INET6: 35 | sin6 = copy_zerofill(SockaddrIn6(), sockaddr_p, sa_len) 36 | buf = create_string_buffer(46 + 1) 37 | libc.inet_ntop(sa_family, byref(sin6.sin6_addr), buf) 38 | return SocketAddress(sa_family, buf.value.decode()) 39 | else: 40 | sa_data = cast(sockaddr_p, POINTER(c_char * sa_len)).contents.raw 41 | return SocketAddress(sa_family, sa_data) 42 | 43 | 44 | def copy_zerofill(dstobj, srcptr, srclen): 45 | dstlen = sizeof(dstobj) 46 | memset(addressof(dstobj), 0, dstlen) 47 | memmove(addressof(dstobj), srcptr, min(dstlen, srclen)) 48 | return dstobj 49 | 50 | 51 | class SockaddrIn(Structure): 52 | _fields_ = [ 53 | ("sin_len", c_ubyte), 54 | ("sin_family", c_ubyte), 55 | ("sin_port", c_ushort), 56 | ("sin_addr", c_ubyte * 4), 57 | ] 58 | 59 | 60 | class SockaddrIn6(Structure): 61 | _fields_ = [ 62 | ("sin6_len", c_ubyte), 63 | ("sin6_family", c_ubyte), 64 | ("sin6_port", c_ushort), 65 | ("sin6_flowinfo", c_uint), 66 | ("sin6_addr", c_ubyte * 16), 67 | ("sin6_scope_id", c_uint), 68 | ] 69 | 70 | 71 | class Sockaddr(Structure): 72 | _fields_ = [("sa_len", c_ubyte), ("sa_family", c_ubyte), ("sa_data", c_char * 14)] 73 | 74 | 75 | class Ifaddrs(Structure): 76 | pass 77 | 78 | 79 | Ifaddrs._fields_ = [ 80 | ("ifa_next", POINTER(Ifaddrs)), 81 | ("ifa_name", c_char_p), 82 | ("ifa_flags", c_uint), 83 | ("ifa_addr", POINTER(Sockaddr)), 84 | ("ifa_netmask", POINTER(Sockaddr)), 85 | ("ifa_dstaddr", POINTER(Sockaddr)), 86 | ("ifa_data", c_void_p), 87 | ] 88 | 89 | try: 90 | libc = CDLL("libSystem.dylib") 91 | except OSError: 92 | from ctypes.util import find_library 93 | 94 | libc = CDLL(find_library("libSystem.dylib")) 95 | libc.getifaddrs.restype = c_int 96 | libc.getifaddrs.argtypes = [POINTER(POINTER(Ifaddrs))] 97 | 98 | 99 | def errno(): 100 | return cast(libc.errno, POINTER(c_int)).contents 101 | 102 | 103 | SocketAddress = collections.namedtuple("SocketAddress", "family address") 104 | Interface = collections.namedtuple("Interface", "name flags addr netmask dstaddr") 105 | 106 | 107 | def get_interfaces(): 108 | ifaddr_p = POINTER(Ifaddrs)() 109 | ret = libc.getifaddrs(byref(ifaddr_p)) 110 | if ret < 0: 111 | raise OSError("getifaddrs failed: errno=%d" % errno()) 112 | 113 | interfaces = [] 114 | head = ifaddr_p 115 | while ifaddr_p: 116 | ifaddr = ifaddr_p.contents 117 | interfaces.append( 118 | Interface( 119 | ifaddr.ifa_name.decode(), 120 | ifaddr.ifa_flags, 121 | get_sockaddr(ifaddr.ifa_addr), 122 | get_sockaddr(ifaddr.ifa_netmask), 123 | get_sockaddr(ifaddr.ifa_dstaddr), 124 | ) 125 | ) 126 | ifaddr_p = ifaddr_p.contents.ifa_next 127 | libc.freeifaddrs(head) 128 | return interfaces 129 | 130 | 131 | if __name__ == "__main__": 132 | for iface in get_interfaces(): 133 | print(iface) 134 | --------------------------------------------------------------------------------