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.

189 lines
6.0 KiB

4 years ago
  1. # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
  2. # Copyright (C) 2003-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 RRsets (an RRset is a named rdataset)"""
  17. import dns.name
  18. import dns.rdataset
  19. import dns.rdataclass
  20. import dns.renderer
  21. from ._compat import string_types
  22. class RRset(dns.rdataset.Rdataset):
  23. """A DNS RRset (named rdataset).
  24. RRset inherits from Rdataset, and RRsets can be treated as
  25. Rdatasets in most cases. There are, however, a few notable
  26. exceptions. RRsets have different to_wire() and to_text() method
  27. arguments, reflecting the fact that RRsets always have an owner
  28. name.
  29. """
  30. __slots__ = ['name', 'deleting']
  31. def __init__(self, name, rdclass, rdtype, covers=dns.rdatatype.NONE,
  32. deleting=None):
  33. """Create a new RRset."""
  34. super(RRset, self).__init__(rdclass, rdtype, covers)
  35. self.name = name
  36. self.deleting = deleting
  37. def _clone(self):
  38. obj = super(RRset, self)._clone()
  39. obj.name = self.name
  40. obj.deleting = self.deleting
  41. return obj
  42. def __repr__(self):
  43. if self.covers == 0:
  44. ctext = ''
  45. else:
  46. ctext = '(' + dns.rdatatype.to_text(self.covers) + ')'
  47. if self.deleting is not None:
  48. dtext = ' delete=' + dns.rdataclass.to_text(self.deleting)
  49. else:
  50. dtext = ''
  51. return '<DNS ' + str(self.name) + ' ' + \
  52. dns.rdataclass.to_text(self.rdclass) + ' ' + \
  53. dns.rdatatype.to_text(self.rdtype) + ctext + dtext + ' RRset>'
  54. def __str__(self):
  55. return self.to_text()
  56. def __eq__(self, other):
  57. if not isinstance(other, RRset):
  58. return False
  59. if self.name != other.name:
  60. return False
  61. return super(RRset, self).__eq__(other)
  62. def match(self, name, rdclass, rdtype, covers, deleting=None):
  63. """Returns ``True`` if this rrset matches the specified class, type,
  64. covers, and deletion state.
  65. """
  66. if not super(RRset, self).match(rdclass, rdtype, covers):
  67. return False
  68. if self.name != name or self.deleting != deleting:
  69. return False
  70. return True
  71. def to_text(self, origin=None, relativize=True, **kw):
  72. """Convert the RRset into DNS master file format.
  73. See ``dns.name.Name.choose_relativity`` for more information
  74. on how *origin* and *relativize* determine the way names
  75. are emitted.
  76. Any additional keyword arguments are passed on to the rdata
  77. ``to_text()`` method.
  78. *origin*, a ``dns.name.Name`` or ``None``, the origin for relative
  79. names.
  80. *relativize*, a ``bool``. If ``True``, names will be relativized
  81. to *origin*.
  82. """
  83. return super(RRset, self).to_text(self.name, origin, relativize,
  84. self.deleting, **kw)
  85. def to_wire(self, file, compress=None, origin=None, **kw):
  86. """Convert the RRset to wire format.
  87. All keyword arguments are passed to ``dns.rdataset.to_wire()``; see
  88. that function for details.
  89. Returns an ``int``, the number of records emitted.
  90. """
  91. return super(RRset, self).to_wire(self.name, file, compress, origin,
  92. self.deleting, **kw)
  93. def to_rdataset(self):
  94. """Convert an RRset into an Rdataset.
  95. Returns a ``dns.rdataset.Rdataset``.
  96. """
  97. return dns.rdataset.from_rdata_list(self.ttl, list(self))
  98. def from_text_list(name, ttl, rdclass, rdtype, text_rdatas,
  99. idna_codec=None):
  100. """Create an RRset with the specified name, TTL, class, and type, and with
  101. the specified list of rdatas in text format.
  102. Returns a ``dns.rrset.RRset`` object.
  103. """
  104. if isinstance(name, string_types):
  105. name = dns.name.from_text(name, None, idna_codec=idna_codec)
  106. if isinstance(rdclass, string_types):
  107. rdclass = dns.rdataclass.from_text(rdclass)
  108. if isinstance(rdtype, string_types):
  109. rdtype = dns.rdatatype.from_text(rdtype)
  110. r = RRset(name, rdclass, rdtype)
  111. r.update_ttl(ttl)
  112. for t in text_rdatas:
  113. rd = dns.rdata.from_text(r.rdclass, r.rdtype, t)
  114. r.add(rd)
  115. return r
  116. def from_text(name, ttl, rdclass, rdtype, *text_rdatas):
  117. """Create an RRset with the specified name, TTL, class, and type and with
  118. the specified rdatas in text format.
  119. Returns a ``dns.rrset.RRset`` object.
  120. """
  121. return from_text_list(name, ttl, rdclass, rdtype, text_rdatas)
  122. def from_rdata_list(name, ttl, rdatas, idna_codec=None):
  123. """Create an RRset with the specified name and TTL, and with
  124. the specified list of rdata objects.
  125. Returns a ``dns.rrset.RRset`` object.
  126. """
  127. if isinstance(name, string_types):
  128. name = dns.name.from_text(name, None, idna_codec=idna_codec)
  129. if len(rdatas) == 0:
  130. raise ValueError("rdata list must not be empty")
  131. r = None
  132. for rd in rdatas:
  133. if r is None:
  134. r = RRset(name, rd.rdclass, rd.rdtype)
  135. r.update_ttl(ttl)
  136. r.add(rd)
  137. return r
  138. def from_rdata(name, ttl, *rdatas):
  139. """Create an RRset with the specified name and TTL, and with
  140. the specified rdata objects.
  141. Returns a ``dns.rrset.RRset`` object.
  142. """
  143. return from_rdata_list(name, ttl, rdatas)