133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Copyright (C) 2001-2007, 2009, 2010 Nominum, Inc. 233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# 333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Permission to use, copy, modify, and distribute this software and its 433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# documentation for any purpose with or without fee is hereby granted, 533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# provided that the above copyright notice and this permission notice 633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# appear in all copies. 733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# 833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 1133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 1433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck"""DNS rdatasets (an rdataset is a set of rdatas of a given type and class)""" 1733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport random 1933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport StringIO 2033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport struct 2133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.exception 2333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.rdatatype 2433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.rdataclass 2533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.rdata 2633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport dns.set 2733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# define SimpleSet here for backwards compatibility 2933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John ReckSimpleSet = dns.set.Set 3033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass DifferingCovers(dns.exception.DNSException): 3233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Raised if an attempt is made to add a SIG/RRSIG whose covered type 3333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck is not the same as that of the other rdatas in the rdataset.""" 3433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 3533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass IncompatibleTypes(dns.exception.DNSException): 3733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Raised if an attempt is made to add rdata of an incompatible type.""" 3833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 3933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass Rdataset(dns.set.Set): 4133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """A DNS rdataset. 4233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @ivar rdclass: The class of the rdataset 4433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type rdclass: int 4533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @ivar rdtype: The type of the rdataset 4633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type rdtype: int 4733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @ivar covers: The covered type. Usually this value is 4833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or 4933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dns.rdatatype.RRSIG, then the covers value will be the rdata 5033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck type the SIG/RRSIG covers. The library treats the SIG and RRSIG 5133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck types as if they were a family of 5233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much 5333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck easier to work with than if RRSIGs covering different rdata 5433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck types were aggregated into a single RRSIG rdataset. 5533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type covers: int 5633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @ivar ttl: The DNS TTL (Time To Live) value 5733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type ttl: int 5833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 5933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck __slots__ = ['rdclass', 'rdtype', 'covers', 'ttl'] 6133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __init__(self, rdclass, rdtype, covers=dns.rdatatype.NONE): 6333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Create a new rdataset of the specified class and type. 6433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @see: the description of the class instance variables for the 6633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck meaning of I{rdclass} and I{rdtype}""" 6733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck super(Rdataset, self).__init__() 6933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.rdclass = rdclass 7033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.rdtype = rdtype 7133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.covers = covers 7233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.ttl = 0 7333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 7433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def _clone(self): 7533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck obj = super(Rdataset, self)._clone() 7633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck obj.rdclass = self.rdclass 7733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck obj.rdtype = self.rdtype 7833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck obj.covers = self.covers 7933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck obj.ttl = self.ttl 8033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return obj 8133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 8233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def update_ttl(self, ttl): 8333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Set the TTL of the rdataset to be the lesser of the set's current 8433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck TTL or the specified TTL. If the set contains no rdatas, set the TTL 8533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck to the specified TTL. 8633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param ttl: The TTL 8733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type ttl: int""" 8833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 8933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(self) == 0: 9033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.ttl = ttl 9133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif ttl < self.ttl: 9233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.ttl = ttl 9333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 9433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def add(self, rd, ttl=None): 9533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Add the specified rdata to the rdataset. 9633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 9733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck If the optional I{ttl} parameter is supplied, then 9833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.update_ttl(ttl) will be called prior to adding the rdata. 9933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 10033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param rd: The rdata 10133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type rd: dns.rdata.Rdata object 10233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param ttl: The TTL 10333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type ttl: int""" 10433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 10533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # 10633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # If we're adding a signature, do some special handling to 10733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # check that the signature covers the same type as the 10833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # other rdatas in this rdataset. If this is the first rdata 10933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # in the set, initialize the covers field. 11033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # 11133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if self.rdclass != rd.rdclass or self.rdtype != rd.rdtype: 11233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise IncompatibleTypes 11333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not ttl is None: 11433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.update_ttl(ttl) 11533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if self.rdtype == dns.rdatatype.RRSIG or \ 11633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.rdtype == dns.rdatatype.SIG: 11733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck covers = rd.covers() 11833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(self) == 0 and self.covers == dns.rdatatype.NONE: 11933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.covers = covers 12033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elif self.covers != covers: 12133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise DifferingCovers 12233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if dns.rdatatype.is_singleton(rd.rdtype) and len(self) > 0: 12333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.clear() 12433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck super(Rdataset, self).add(rd) 12533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 12633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def union_update(self, other): 12733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.update_ttl(other.ttl) 12833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck super(Rdataset, self).union_update(other) 12933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 13033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def intersection_update(self, other): 13133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.update_ttl(other.ttl) 13233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck super(Rdataset, self).intersection_update(other) 13333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 13433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def update(self, other): 13533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Add all rdatas in other to self. 13633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 13733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param other: The rdataset from which to update 13833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type other: dns.rdataset.Rdataset object""" 13933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 14033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.update_ttl(other.ttl) 14133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck super(Rdataset, self).update(other) 14233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 14333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __repr__(self): 14433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if self.covers == 0: 14533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ctext = '' 14633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 14733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ctext = '(' + dns.rdatatype.to_text(self.covers) + ')' 14833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return '<DNS ' + dns.rdataclass.to_text(self.rdclass) + ' ' + \ 14933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dns.rdatatype.to_text(self.rdtype) + ctext + ' rdataset>' 15033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 15133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __str__(self): 15233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return self.to_text() 15333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 15433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __eq__(self, other): 15533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Two rdatasets are equal if they have the same class, type, and 15633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck covers, and contain the same rdata. 15733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: bool""" 15833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 15933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not isinstance(other, Rdataset): 16033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return False 16133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if self.rdclass != other.rdclass or \ 16233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.rdtype != other.rdtype or \ 16333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.covers != other.covers: 16433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return False 16533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return super(Rdataset, self).__eq__(other) 16633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 16733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def __ne__(self, other): 16833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return not self.__eq__(other) 16933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 17033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_text(self, name=None, origin=None, relativize=True, 17133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck override_rdclass=None, **kw): 17233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Convert the rdataset into DNS master file format. 17333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 17433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @see: L{dns.name.Name.choose_relativity} for more information 17533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck on how I{origin} and I{relativize} determine the way names 17633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck are emitted. 17733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 17833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck Any additional keyword arguments are passed on to the rdata 17933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck to_text() method. 18033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 18133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param name: If name is not None, emit a RRs with I{name} as 18233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck the owner name. 18333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type name: dns.name.Name object 18433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param origin: The origin for relative names, or None. 18533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type origin: dns.name.Name object 18633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param relativize: True if names should names be relativized 18733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type relativize: bool""" 18833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not name is None: 18933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck name = name.choose_relativity(origin, relativize) 19033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ntext = str(name) 19133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pad = ' ' 19233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 19333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck ntext = '' 19433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pad = '' 19533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck s = StringIO.StringIO() 19633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not override_rdclass is None: 19733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck rdclass = override_rdclass 19833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 19933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck rdclass = self.rdclass 20033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(self) == 0: 20133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # 20233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Empty rdatasets are used for the question section, and in 20333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # some dynamic updates, so we don't need to print out the TTL 20433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # (which is meaningless anyway). 20533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # 20633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck print >> s, '%s%s%s %s' % (ntext, pad, 20733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dns.rdataclass.to_text(rdclass), 20833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dns.rdatatype.to_text(self.rdtype)) 20933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 21033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for rd in self: 21133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck print >> s, '%s%s%d %s %s %s' % \ 21233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (ntext, pad, self.ttl, dns.rdataclass.to_text(rdclass), 21333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck dns.rdatatype.to_text(self.rdtype), 21433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck rd.to_text(origin=origin, relativize=relativize, **kw)) 21533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # 21633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # We strip off the final \n for the caller's convenience in printing 21733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # 21833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return s.getvalue()[:-1] 21933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 22033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def to_wire(self, name, file, compress=None, origin=None, 22133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck override_rdclass=None, want_shuffle=True): 22233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Convert the rdataset to wire format. 22333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 22433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param name: The owner name of the RRset that will be emitted 22533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type name: dns.name.Name object 22633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param file: The file to which the wire format data will be appended 22733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type file: file 22833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param compress: The compression table to use; the default is None. 22933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @type compress: dict 23033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @param origin: The origin to be appended to any relative names when 23133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck they are emitted. The default is None. 23233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @returns: the number of records emitted 23333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: int 23433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 23533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 23633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if not override_rdclass is None: 23733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck rdclass = override_rdclass 23833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck want_shuffle = False 23933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 24033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck rdclass = self.rdclass 24133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck file.seek(0, 2) 24233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(self) == 0: 24333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck name.to_wire(file, compress, origin) 24433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck stuff = struct.pack("!HHIH", self.rdtype, rdclass, 0, 0) 24533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck file.write(stuff) 24633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return 1 24733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 24833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if want_shuffle: 24933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l = list(self) 25033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck random.shuffle(l) 25133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck else: 25233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck l = self 25333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for rd in l: 25433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck name.to_wire(file, compress, origin) 25533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck stuff = struct.pack("!HHIH", self.rdtype, rdclass, 25633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.ttl, 0) 25733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck file.write(stuff) 25833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck start = file.tell() 25933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck rd.to_wire(file, compress, origin) 26033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck end = file.tell() 26133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck assert end - start < 65536 26233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck file.seek(start - 2) 26333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck stuff = struct.pack("!H", end - start) 26433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck file.write(stuff) 26533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck file.seek(0, 2) 26633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return len(self) 26733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 26833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def match(self, rdclass, rdtype, covers): 26933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Returns True if this rdataset matches the specified class, type, 27033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck and covers""" 27133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if self.rdclass == rdclass and \ 27233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.rdtype == rdtype and \ 27333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck self.covers == covers: 27433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return True 27533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return False 27633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 27733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef from_text_list(rdclass, rdtype, ttl, text_rdatas): 27833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Create an rdataset with the specified class, type, and TTL, and with 27933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck the specified list of rdatas in text format. 28033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 28133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.rdataset.Rdataset object 28233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 28333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 28433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if isinstance(rdclass, str): 28533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck rdclass = dns.rdataclass.from_text(rdclass) 28633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if isinstance(rdtype, str): 28733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck rdtype = dns.rdatatype.from_text(rdtype) 28833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck r = Rdataset(rdclass, rdtype) 28933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck r.update_ttl(ttl) 29033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for t in text_rdatas: 29133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck rd = dns.rdata.from_text(r.rdclass, r.rdtype, t) 29233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck r.add(rd) 29333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return r 29433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 29533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef from_text(rdclass, rdtype, ttl, *text_rdatas): 29633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Create an rdataset with the specified class, type, and TTL, and with 29733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck the specified rdatas in text format. 29833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 29933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.rdataset.Rdataset object 30033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 30133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 30233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return from_text_list(rdclass, rdtype, ttl, text_rdatas) 30333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 30433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef from_rdata_list(ttl, rdatas): 30533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Create an rdataset with the specified TTL, and with 30633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck the specified list of rdata objects. 30733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 30833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.rdataset.Rdataset object 30933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 31033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 31133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if len(rdatas) == 0: 31233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise ValueError("rdata list must not be empty") 31333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck r = None 31433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck for rd in rdatas: 31533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if r is None: 31633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck r = Rdataset(rd.rdclass, rd.rdtype) 31733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck r.update_ttl(ttl) 31833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck first_time = False 31933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck r.add(rd) 32033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return r 32133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 32233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef from_rdata(ttl, *rdatas): 32333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Create an rdataset with the specified TTL, and with 32433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck the specified rdata objects. 32533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 32633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck @rtype: dns.rdataset.Rdataset object 32733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 32833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 32933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return from_rdata_list(ttl, rdatas) 330