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 Types.""" 19 20import re 21 22import dns.exception 23 24NONE = 0 25A = 1 26NS = 2 27MD = 3 28MF = 4 29CNAME = 5 30SOA = 6 31MB = 7 32MG = 8 33MR = 9 34NULL = 10 35WKS = 11 36PTR = 12 37HINFO = 13 38MINFO = 14 39MX = 15 40TXT = 16 41RP = 17 42AFSDB = 18 43X25 = 19 44ISDN = 20 45RT = 21 46NSAP = 22 47NSAP_PTR = 23 48SIG = 24 49KEY = 25 50PX = 26 51GPOS = 27 52AAAA = 28 53LOC = 29 54NXT = 30 55SRV = 33 56NAPTR = 35 57KX = 36 58CERT = 37 59A6 = 38 60DNAME = 39 61OPT = 41 62APL = 42 63DS = 43 64SSHFP = 44 65IPSECKEY = 45 66RRSIG = 46 67NSEC = 47 68DNSKEY = 48 69DHCID = 49 70NSEC3 = 50 71NSEC3PARAM = 51 72TLSA = 52 73HIP = 55 74CDS = 59 75CDNSKEY = 60 76OPENPGPKEY = 61 77CSYNC = 62 78SPF = 99 79UNSPEC = 103 80EUI48 = 108 81EUI64 = 109 82TKEY = 249 83TSIG = 250 84IXFR = 251 85AXFR = 252 86MAILB = 253 87MAILA = 254 88ANY = 255 89URI = 256 90CAA = 257 91AVC = 258 92TA = 32768 93DLV = 32769 94 95_by_text = { 96 'NONE': NONE, 97 'A': A, 98 'NS': NS, 99 'MD': MD, 100 'MF': MF, 101 'CNAME': CNAME, 102 'SOA': SOA, 103 'MB': MB, 104 'MG': MG, 105 'MR': MR, 106 'NULL': NULL, 107 'WKS': WKS, 108 'PTR': PTR, 109 'HINFO': HINFO, 110 'MINFO': MINFO, 111 'MX': MX, 112 'TXT': TXT, 113 'RP': RP, 114 'AFSDB': AFSDB, 115 'X25': X25, 116 'ISDN': ISDN, 117 'RT': RT, 118 'NSAP': NSAP, 119 'NSAP-PTR': NSAP_PTR, 120 'SIG': SIG, 121 'KEY': KEY, 122 'PX': PX, 123 'GPOS': GPOS, 124 'AAAA': AAAA, 125 'LOC': LOC, 126 'NXT': NXT, 127 'SRV': SRV, 128 'NAPTR': NAPTR, 129 'KX': KX, 130 'CERT': CERT, 131 'A6': A6, 132 'DNAME': DNAME, 133 'OPT': OPT, 134 'APL': APL, 135 'DS': DS, 136 'SSHFP': SSHFP, 137 'IPSECKEY': IPSECKEY, 138 'RRSIG': RRSIG, 139 'NSEC': NSEC, 140 'DNSKEY': DNSKEY, 141 'DHCID': DHCID, 142 'NSEC3': NSEC3, 143 'NSEC3PARAM': NSEC3PARAM, 144 'TLSA': TLSA, 145 'HIP': HIP, 146 'CDS': CDS, 147 'CDNSKEY': CDNSKEY, 148 'OPENPGPKEY': OPENPGPKEY, 149 'CSYNC': CSYNC, 150 'SPF': SPF, 151 'UNSPEC': UNSPEC, 152 'EUI48': EUI48, 153 'EUI64': EUI64, 154 'TKEY': TKEY, 155 'TSIG': TSIG, 156 'IXFR': IXFR, 157 'AXFR': AXFR, 158 'MAILB': MAILB, 159 'MAILA': MAILA, 160 'ANY': ANY, 161 'URI': URI, 162 'CAA': CAA, 163 'AVC': AVC, 164 'TA': TA, 165 'DLV': DLV, 166} 167 168# We construct the inverse mapping programmatically to ensure that we 169# cannot make any mistakes (e.g. omissions, cut-and-paste errors) that 170# would cause the mapping not to be true inverse. 171 172_by_value = {y: x for x, y in _by_text.items()} 173 174_metatypes = { 175 OPT: True 176} 177 178_singletons = { 179 SOA: True, 180 NXT: True, 181 DNAME: True, 182 NSEC: True, 183 CNAME: True, 184} 185 186_unknown_type_pattern = re.compile('TYPE([0-9]+)$', re.I) 187 188 189class UnknownRdatatype(dns.exception.DNSException): 190 """DNS resource record type is unknown.""" 191 192 193def from_text(text): 194 """Convert text into a DNS rdata type value. 195 196 The input text can be a defined DNS RR type mnemonic or 197 instance of the DNS generic type syntax. 198 199 For example, "NS" and "TYPE2" will both result in a value of 2. 200 201 Raises ``dns.rdatatype.UnknownRdatatype`` if the type is unknown. 202 203 Raises ``ValueError`` if the rdata type value is not >= 0 and <= 65535. 204 205 Returns an ``int``. 206 """ 207 208 value = _by_text.get(text.upper()) 209 if value is None: 210 match = _unknown_type_pattern.match(text) 211 if match is None: 212 raise UnknownRdatatype 213 value = int(match.group(1)) 214 if value < 0 or value > 65535: 215 raise ValueError("type must be between >= 0 and <= 65535") 216 return value 217 218 219def to_text(value): 220 """Convert a DNS rdata type value to text. 221 222 If the value has a known mnemonic, it will be used, otherwise the 223 DNS generic type syntax will be used. 224 225 Raises ``ValueError`` if the rdata type value is not >= 0 and <= 65535. 226 227 Returns a ``str``. 228 """ 229 230 if value < 0 or value > 65535: 231 raise ValueError("type must be between >= 0 and <= 65535") 232 text = _by_value.get(value) 233 if text is None: 234 text = 'TYPE' + repr(value) 235 return text 236 237 238def is_metatype(rdtype): 239 """True if the specified type is a metatype. 240 241 *rdtype* is an ``int``. 242 243 The currently defined metatypes are TKEY, TSIG, IXFR, AXFR, MAILA, 244 MAILB, ANY, and OPT. 245 246 Returns a ``bool``. 247 """ 248 249 if rdtype >= TKEY and rdtype <= ANY or rdtype in _metatypes: 250 return True 251 return False 252 253 254def is_singleton(rdtype): 255 """Is the specified type a singleton type? 256 257 Singleton types can only have a single rdata in an rdataset, or a single 258 RR in an RRset. 259 260 The currently defined singleton types are CNAME, DNAME, NSEC, NXT, and 261 SOA. 262 263 *rdtype* is an ``int``. 264 265 Returns a ``bool``. 266 """ 267 268 if rdtype in _singletons: 269 return True 270 return False 271 272 273def register_type(rdtype, rdtype_text, is_singleton=False): # pylint: disable=redefined-outer-name 274 """Dynamically register an rdatatype. 275 276 *rdtype*, an ``int``, the rdatatype to register. 277 278 *rdtype_text*, a ``text``, the textual form of the rdatatype. 279 280 *is_singleton*, a ``bool``, indicating if the type is a singleton (i.e. 281 RRsets of the type can have only one member.) 282 """ 283 284 _by_text[rdtype_text] = rdtype 285 _by_value[rdtype] = rdtype_text 286 if is_singleton: 287 _singletons[rdtype] = True 288