You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
3.1 KiB

4 years ago
  1. # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
  2. # Copyright (C) 2001-2017 Nominum, Inc.
  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 NOMINUM 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. """DNS Rdata Classes."""
  17. import re
  18. import dns.exception
  19. RESERVED0 = 0
  20. IN = 1
  21. CH = 3
  22. HS = 4
  23. NONE = 254
  24. ANY = 255
  25. _by_text = {
  26. 'RESERVED0': RESERVED0,
  27. 'IN': IN,
  28. 'CH': CH,
  29. 'HS': HS,
  30. 'NONE': NONE,
  31. 'ANY': ANY
  32. }
  33. # We construct the inverse mapping programmatically to ensure that we
  34. # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
  35. # would cause the mapping not to be true inverse.
  36. _by_value = {y: x for x, y in _by_text.items()}
  37. # Now that we've built the inverse map, we can add class aliases to
  38. # the _by_text mapping.
  39. _by_text.update({
  40. 'INTERNET': IN,
  41. 'CHAOS': CH,
  42. 'HESIOD': HS
  43. })
  44. _metaclasses = {
  45. NONE: True,
  46. ANY: True
  47. }
  48. _unknown_class_pattern = re.compile('CLASS([0-9]+)$', re.I)
  49. class UnknownRdataclass(dns.exception.DNSException):
  50. """A DNS class is unknown."""
  51. def from_text(text):
  52. """Convert text into a DNS rdata class value.
  53. The input text can be a defined DNS RR class mnemonic or
  54. instance of the DNS generic class syntax.
  55. For example, "IN" and "CLASS1" will both result in a value of 1.
  56. Raises ``dns.rdatatype.UnknownRdataclass`` if the class is unknown.
  57. Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535.
  58. Returns an ``int``.
  59. """
  60. value = _by_text.get(text.upper())
  61. if value is None:
  62. match = _unknown_class_pattern.match(text)
  63. if match is None:
  64. raise UnknownRdataclass
  65. value = int(match.group(1))
  66. if value < 0 or value > 65535:
  67. raise ValueError("class must be between >= 0 and <= 65535")
  68. return value
  69. def to_text(value):
  70. """Convert a DNS rdata type value to text.
  71. If the value has a known mnemonic, it will be used, otherwise the
  72. DNS generic class syntax will be used.
  73. Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535.
  74. Returns a ``str``.
  75. """
  76. if value < 0 or value > 65535:
  77. raise ValueError("class must be between >= 0 and <= 65535")
  78. text = _by_value.get(value)
  79. if text is None:
  80. text = 'CLASS' + repr(value)
  81. return text
  82. def is_metaclass(rdclass):
  83. """True if the specified class is a metaclass.
  84. The currently defined metaclasses are ANY and NONE.
  85. *rdclass* is an ``int``.
  86. """
  87. if rdclass in _metaclasses:
  88. return True
  89. return False