Source code for constants
"""
The constants module defines the various DNS constants, and also
provides some utility functions for dealing with these.
"""
import enum
# The DNS QR header flag can be either 0 (query) or 1 (response).
[docs]@enum.unique
class QR(enum.IntEnum):
"""
Enumerates the possible QR bit values.
"""
QUERY = 0 #: QR flag for queries
RESPONSE = 1 #: QR flag for responses
# Possible DNS operation code values are listed on the IANA DNS
# parameters page:
# https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5
[docs]@enum.unique
class OpCode(enum.IntEnum):
"""
Enumerates the defined DNS operation codes.
"""
QUERY = 0 #: OpCode for queries
IQUERY = 1 #: OpCode for inverse queries
STATUS = 2 #: OpCode for status queries
# 3 is unassigned
NOTIFY = 4 #: OpCode for NOTIFY messages
UPDATE = 5 #: OpCode for UPDATE messages
DSO = 6 #: OpCode for DNS Stateful Operation (DSO) messages
# Possible DNS result code values are listed on the IANA DNS
# parameters page:
# https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
#
# Note that we do not include the extended RCODE values here, which
# are returned in the EDNS OPT record, if present.
#
# We define two versions of each number, starting with the mixed
# capitalization used on the IANA page. This is so that the name
# attribute provided returns the IANA version:
#
# >>> foo = RCODE(2)
# >>> foo.name
# 'ServFail'
# >>> bar = RCODE.SERVFAIL
# >>> bar.name
# 'ServFail'
# >>> bar == foo
# True
# >>> baz = RCODE['SERVFAIL']
# >>> baz
# <RCODE.ServFail: 2>
[docs]class RCODE(enum.IntEnum):
"""
Enumerates the defined DNS response codes.
"""
# pylint: disable=invalid-name
NoError = 0 #: No Error RCODE
NOERROR = NoError
FormErr = 1 #: Format Error RCODE
FORMERR = FormErr
ServFail = 2 #: Server Failure RCODE
SERVFAIL = ServFail
NXDomain = 3 #: Non-Existent Domain RCODE
NXDOMAIN = NXDomain
NotImp = 4 #: Not Implemented RCODE
NOTIMP = NotImp
Refused = 5 #: Query Refused RCODE
REFUSED = Refused
YXDomain = 6 #: Name Exists when it should not RCODE
YXDOMAIN = YXDomain
YXRRSet = 7 #: RR Set Exists when it should not RCODE
YXRRSET = YXRRSet
NXRRSet = 8 #: RR Set that should exist does not RCODE
NXRRSET = NXRRSet
NotAuth = 9 #: Server Not Authoritative for zone / Not Authorized RCODE
NOTAUTH = NotAuth
NotZone = 10 #: Name not contained in zone RCODE
NOTZONE = NotZone
DSOTYPENI = 11 #: DSO-TYPE Not Implemented RCODE
# Resource record (RR) types are documented on the IANA DNS parameters
# page:
# https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4
[docs]@enum.unique
class Type(enum.IntEnum):
"""
Enumerates the defined DNS types.
"""
A = 1 #: a host address RTYPE
NS = 2 #: an authoritative name server RTYPE
MD = 3 #: a mail destination RTYPE
MF = 4 #: a mail forwarder RTYPE
CNAME = 5 #: the canonical name for an alias RTYPE
SOA = 6 #: marks the start of a zone of authority RTYPE
MB = 7 #: a mailbox domain name RTYPE
MG = 8 #: a mail group member RTYPE
MR = 9 #: a mail rename domain name RTYPE
NULL = 10 #: a null RR RTYPE
WKS = 11 #: a well known service description RTYPE
PTR = 12 #: a domain name pointer RTYPE
HINFO = 13 #: host information RTYPE
MINFO = 14 #: mailbox or mail list information RTYPE
MX = 15 #: mail exchange RTYPE
TXT = 16 #: text strings RTYPE
RP = 17 #: for Responsible Person RTYPE
AFSDB = 18 #: for AFS Data Base location RTYPE
X25 = 19 #: for X.25 PSDN address RTYPE
ISDN = 20 #: for ISDN address RTYPE
RT = 21 #: for Route Through RTYPE
NSAP = 22 #: for NSAP address, NSAP style A record RTYPE
NSAP_PTR = 23 #: for domain name pointer, NSAP style RTYPE
SIG = 24 #: for security signature RTYPE
KEY = 25 #: for security key RTYPE
PX = 26 #: X.400 mail mapping information RTYPE
GPOS = 27 #: Geographical Position RTYPE
AAAA = 28 #: IP6 Address RTYPE
OPT = 41 #: OPT RTYPE
RRSIG = 46 #: RRSIG RTYPE
TSIG = 250 #: Transaction Signature
IXFR = 251 #: incremental transfer
AXFR = 252 #: transfer of an entire zone
ANY = 255
#: A request for some or all record the server has available RTYPE
[docs]def type_name(dns_type: int) -> str:
"""
Converts a numeric type value to a name. This is the symbolic
name if we know it (like `NS` or `AAAA`), otherwise the `RFC 3597
<https://tools.ietf.org/html/rfc3597>`_ version (`TYPE####`).
Numbers out of range raise a :py:class:`ValueError` exception.
:param dns_type: Numeric value of a DNS type to convert to string.
:type dns_type: str
:return: String version of the type identifier.
:rtype: str
:raises: :py:class:`ValueError` if `dns_type` is not an unsigned
16-bit value.
"""
# Special case NSAP-PTR, since the '-' is not allowed in Python
# variable names.
if dns_type == Type.NSAP_PTR:
return "NSAP-PTR"
# For other defined types return the enum type name.
try:
return Type(dns_type).name
except ValueError:
if 0 <= dns_type <= 65535:
return f"TYPE{dns_type}"
msg = f"DNS type not between 0 and 65535: {dns_type}"
raise ValueError(msg) from None
# DNS classes are documented on the IANA DNS parameters page:
# https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2
[docs]@enum.unique
class Class(enum.IntEnum):
"""
Enumerates the defined DNS classes.
"""
IN = 1 #: Internet class
# 2 is unassigned
CH = 3 #: Chaos class
HS = 4 #: Hesiod class
NONE = 254 #: "NONE" class
ANY = 255 #: "ANY" class
[docs]def class_name(dns_class: int) -> str:
"""
Converts a numeric class value to a name. This is the symbolic
name if we know it (like `IN` or `CH`), otherwise the `RFC 3597
<https://tools.ietf.org/html/rfc3597>`_ version (`CLASS####`).
Numbers out of range raise a :py:class:`ValueError` exception.
:param dns_class: Numeric value of a DNS class to convert to string.
:type dns_class: str
:return: String version of the class identifier.
:rtype: str
:raises: :py:class:`ValueError` if `dns_class` is not an unsigned
16-bit value.
"""
try:
return Class(dns_class).name
except ValueError:
if 0 <= dns_class <= 65535:
return f"CLASS{dns_class}"
msg = f"DNS class not between 0 and 65535: {dns_class}"
raise ValueError(msg) from None