rcode.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. # Copyright (C) 2001-2007, 2009-2011 Nominum, Inc.
  2. #
  3. # Permission to use, copy, modify, and distribute this software and its
  4. # documentation for any purpose with or without fee is hereby granted,
  5. # provided that the above copyright notice and this permission notice
  6. # appear in all copies.
  7. #
  8. # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
  9. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
  11. # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  14. # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. """DNS Result Codes."""
  16. import dns.exception
  17. from ._compat import long
  18. NOERROR = 0
  19. FORMERR = 1
  20. SERVFAIL = 2
  21. NXDOMAIN = 3
  22. NOTIMP = 4
  23. REFUSED = 5
  24. YXDOMAIN = 6
  25. YXRRSET = 7
  26. NXRRSET = 8
  27. NOTAUTH = 9
  28. NOTZONE = 10
  29. BADVERS = 16
  30. _by_text = {
  31. 'NOERROR': NOERROR,
  32. 'FORMERR': FORMERR,
  33. 'SERVFAIL': SERVFAIL,
  34. 'NXDOMAIN': NXDOMAIN,
  35. 'NOTIMP': NOTIMP,
  36. 'REFUSED': REFUSED,
  37. 'YXDOMAIN': YXDOMAIN,
  38. 'YXRRSET': YXRRSET,
  39. 'NXRRSET': NXRRSET,
  40. 'NOTAUTH': NOTAUTH,
  41. 'NOTZONE': NOTZONE,
  42. 'BADVERS': BADVERS
  43. }
  44. # We construct the inverse mapping programmatically to ensure that we
  45. # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that
  46. # would cause the mapping not to be a true inverse.
  47. _by_value = dict((y, x) for x, y in _by_text.items())
  48. class UnknownRcode(dns.exception.DNSException):
  49. """A DNS rcode is unknown."""
  50. def from_text(text):
  51. """Convert text into an rcode.
  52. @param text: the textual rcode
  53. @type text: string
  54. @raises UnknownRcode: the rcode is unknown
  55. @rtype: int
  56. """
  57. if text.isdigit():
  58. v = int(text)
  59. if v >= 0 and v <= 4095:
  60. return v
  61. v = _by_text.get(text.upper())
  62. if v is None:
  63. raise UnknownRcode
  64. return v
  65. def from_flags(flags, ednsflags):
  66. """Return the rcode value encoded by flags and ednsflags.
  67. @param flags: the DNS flags
  68. @type flags: int
  69. @param ednsflags: the EDNS flags
  70. @type ednsflags: int
  71. @raises ValueError: rcode is < 0 or > 4095
  72. @rtype: int
  73. """
  74. value = (flags & 0x000f) | ((ednsflags >> 20) & 0xff0)
  75. if value < 0 or value > 4095:
  76. raise ValueError('rcode must be >= 0 and <= 4095')
  77. return value
  78. def to_flags(value):
  79. """Return a (flags, ednsflags) tuple which encodes the rcode.
  80. @param value: the rcode
  81. @type value: int
  82. @raises ValueError: rcode is < 0 or > 4095
  83. @rtype: (int, int) tuple
  84. """
  85. if value < 0 or value > 4095:
  86. raise ValueError('rcode must be >= 0 and <= 4095')
  87. v = value & 0xf
  88. ev = long(value & 0xff0) << 20
  89. return (v, ev)
  90. def to_text(value):
  91. """Convert rcode into text.
  92. @param value: the rcode
  93. @type value: int
  94. @rtype: string
  95. """
  96. text = _by_value.get(value)
  97. if text is None:
  98. text = str(value)
  99. return text