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.

144 lines
3.5 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 Result Codes."""
  17. import dns.exception
  18. from ._compat import long
  19. #: No error
  20. NOERROR = 0
  21. #: Form error
  22. FORMERR = 1
  23. #: Server failure
  24. SERVFAIL = 2
  25. #: Name does not exist ("Name Error" in RFC 1025 terminology).
  26. NXDOMAIN = 3
  27. #: Not implemented
  28. NOTIMP = 4
  29. #: Refused
  30. REFUSED = 5
  31. #: Name exists.
  32. YXDOMAIN = 6
  33. #: RRset exists.
  34. YXRRSET = 7
  35. #: RRset does not exist.
  36. NXRRSET = 8
  37. #: Not authoritative.
  38. NOTAUTH = 9
  39. #: Name not in zone.
  40. NOTZONE = 10
  41. #: Bad EDNS version.
  42. BADVERS = 16
  43. _by_text = {
  44. 'NOERROR': NOERROR,
  45. 'FORMERR': FORMERR,
  46. 'SERVFAIL': SERVFAIL,
  47. 'NXDOMAIN': NXDOMAIN,
  48. 'NOTIMP': NOTIMP,
  49. 'REFUSED': REFUSED,
  50. 'YXDOMAIN': YXDOMAIN,
  51. 'YXRRSET': YXRRSET,
  52. 'NXRRSET': NXRRSET,
  53. 'NOTAUTH': NOTAUTH,
  54. 'NOTZONE': NOTZONE,
  55. 'BADVERS': BADVERS
  56. }
  57. # We construct the inverse mapping programmatically to ensure that we
  58. # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
  59. # would cause the mapping not to be a true inverse.
  60. _by_value = {y: x for x, y in _by_text.items()}
  61. class UnknownRcode(dns.exception.DNSException):
  62. """A DNS rcode is unknown."""
  63. def from_text(text):
  64. """Convert text into an rcode.
  65. *text*, a ``text``, the textual rcode or an integer in textual form.
  66. Raises ``dns.rcode.UnknownRcode`` if the rcode mnemonic is unknown.
  67. Returns an ``int``.
  68. """
  69. if text.isdigit():
  70. v = int(text)
  71. if v >= 0 and v <= 4095:
  72. return v
  73. v = _by_text.get(text.upper())
  74. if v is None:
  75. raise UnknownRcode
  76. return v
  77. def from_flags(flags, ednsflags):
  78. """Return the rcode value encoded by flags and ednsflags.
  79. *flags*, an ``int``, the DNS flags field.
  80. *ednsflags*, an ``int``, the EDNS flags field.
  81. Raises ``ValueError`` if rcode is < 0 or > 4095
  82. Returns an ``int``.
  83. """
  84. value = (flags & 0x000f) | ((ednsflags >> 20) & 0xff0)
  85. if value < 0 or value > 4095:
  86. raise ValueError('rcode must be >= 0 and <= 4095')
  87. return value
  88. def to_flags(value):
  89. """Return a (flags, ednsflags) tuple which encodes the rcode.
  90. *value*, an ``int``, the rcode.
  91. Raises ``ValueError`` if rcode is < 0 or > 4095.
  92. Returns an ``(int, int)`` tuple.
  93. """
  94. if value < 0 or value > 4095:
  95. raise ValueError('rcode must be >= 0 and <= 4095')
  96. v = value & 0xf
  97. ev = long(value & 0xff0) << 20
  98. return (v, ev)
  99. def to_text(value):
  100. """Convert rcode into text.
  101. *value*, and ``int``, the rcode.
  102. Raises ``ValueError`` if rcode is < 0 or > 4095.
  103. Returns a ``text``.
  104. """
  105. if value < 0 or value > 4095:
  106. raise ValueError('rcode must be >= 0 and <= 4095')
  107. text = _by_value.get(value)
  108. if text is None:
  109. text = str(value)
  110. return text