def to_address(name): """Convert a reverse map domain name into textual address form. @param name: an IPv4 or IPv6 address in reverse-map form. @type name: dnspython.name.Name object @rtype: str """ if name.is_subdomain(ipv4_reverse_domain): name = name.relativize(ipv4_reverse_domain) labels = list(name.labels) labels.reverse() text = '.'.join(labels) # run through inet_aton() to check syntax and make pretty. return dnspython.ipv4.inet_ntoa(dnspython.ipv4.inet_aton(text)) elif name.is_subdomain(ipv6_reverse_domain): name = name.relativize(ipv6_reverse_domain) labels = list(name.labels) labels.reverse() parts = [] i = 0 l = len(labels) while i < l: parts.append(''.join(labels[i:i+4])) i += 4 text = ':'.join(parts) # run through inet_aton() to check syntax and make pretty. return dnspython.ipv6.inet_ntoa(dnspython.ipv6.inet_aton(text)) else: raise dnspython.exception.SyntaxError, 'unknown reverse-map address family'
def _validate_name(self, name): if isinstance(name, (str, unicode)): name = dnspython.name.from_text(name, None) elif not isinstance(name, dnspython.name.Name): raise KeyError, "name parameter must be convertable to a DNS name" if name.is_absolute(): if not name.is_subdomain(self.origin): raise KeyError, "name parameter must be a subdomain of the zone origin" if self.relativize: name = name.relativize(self.origin) return name
def to_e164(name, origin=public_enum_domain, want_plus_prefix=True): """Convert an ENUM domain name into an E.164 number. @param name: the ENUM domain name. @type name: dnspython.name.Name object. @param origin: A domain containing the ENUM domain name. The name is relativized to this domain before being converted to text. @type: dnspython.name.Name object or None @param want_plus_prefix: if True, add a '+' to the beginning of the returned number. @rtype: str """ if not origin is None: name = name.relativize(origin) dlabels = [d for d in name.labels if (d.isdigit() and len(d) == 1)] if len(dlabels) != len(name.labels): raise dnspython.exception.SyntaxError, 'non-digit labels in ENUM domain name' dlabels.reverse() text = ''.join(dlabels) if want_plus_prefix: text = '+' + text return text
def _rr_line(self): """Process one line from a DNS master file.""" # Name if self.current_origin is None: raise UnknownOrigin token = self.tok.get(want_leading=True) if token[0] != dnspython.tokenizer.WHITESPACE: self.last_name = dnspython.name.from_text(token[1], self.current_origin) else: token = self.tok.get() if token[0] == dnspython.tokenizer.EOL or token[0] == dnspython.tokenizer.EOF: # treat leading WS followed by EOL/EOF as if they were EOL/EOF. return self.tok.unget(token) name = self.last_name if not name.is_subdomain(self.zone.origin): self._eat_line() return if self.relativize: name = name.relativize(self.zone.origin) token = self.tok.get() if token[0] != dnspython.tokenizer.IDENTIFIER: raise dnspython.exception.SyntaxError # TTL try: ttl = dnspython.ttl.from_text(token[1]) token = self.tok.get() if token[0] != dnspython.tokenizer.IDENTIFIER: raise dnspython.exception.SyntaxError except dnspython.ttl.BadTTL: ttl = self.ttl # Class try: rdclass = dnspython.rdataclass.from_text(token[1]) token = self.tok.get() if token[0] != dnspython.tokenizer.IDENTIFIER: raise dnspython.exception.SyntaxError except dnspython.exception.SyntaxError: raise dnspython.exception.SyntaxError except: rdclass = self.zone.rdclass if rdclass != self.zone.rdclass: raise dnspython.exception.SyntaxError, "RR class is not zone's class" # Type try: rdtype = dnspython.rdatatype.from_text(token[1]) except: raise dnspython.exception.SyntaxError, "unknown rdatatype '%s'" % token[1] n = self.zone.nodes.get(name) if n is None: n = self.zone.node_factory() self.zone.nodes[name] = n try: rd = dnspython.rdata.from_text(rdclass, rdtype, self.tok, self.current_origin, False) except dnspython.exception.SyntaxError: # Catch and reraise. (ty, va) = sys.exc_info()[:2] raise ty, va except: # All exceptions that occur in the processing of rdata # are treated as syntax errors. This is not strictly # correct, but it is correct almost all of the time. # We convert them to syntax errors so that we can emit # helpful filename:line info. (ty, va) = sys.exc_info()[:2] raise dnspython.exception.SyntaxError, "caught exception %s: %s" % (str(ty), str(va)) rd.choose_relativity(self.zone.origin, self.relativize) covers = rd.covers() rds = n.find_rdataset(rdclass, rdtype, covers, True) rds.add(rd, ttl)
def _get_section(self, section, count): """Read the next I{count} records from the wire data and add them to the specified section. @param section: the section of the message to which to add records @type section: list of dnspython.rrset.RRset objects @param count: the number of records to read @type count: int""" if self.updating or self.one_rr_per_rrset: force_unique = True else: force_unique = False seen_opt = False for i in xrange(0, count): rr_start = self.current (name, used) = dnspython.name.from_wire(self.wire, self.current) absolute_name = name if not self.message.origin is None: name = name.relativize(self.message.origin) self.current = self.current + used (rdtype, rdclass, ttl, rdlen) = \ struct.unpack('!HHIH', self.wire[self.current:self.current + 10]) self.current = self.current + 10 if rdtype == dnspython.rdatatype.OPT: if not section is self.message.additional or seen_opt: raise BadEDNS self.message.payload = rdclass self.message.ednsflags = ttl self.message.edns = (ttl & 0xff0000) >> 16 self.message.options = [] current = self.current optslen = rdlen while optslen > 0: (otype, olen) = \ struct.unpack('!HH', self.wire[current:current + 4]) current = current + 4 opt = dnspython.ednspython.option_from_wire(otype, self.wire, current, olen) self.message.options.append(opt) current = current + olen optslen = optslen - 4 - olen seen_opt = True elif rdtype == dnspython.rdatatype.TSIG: if not (section is self.message.additional and i == (count - 1)): raise BadTSIG if self.message.keyring is None: raise UnknownTSIGKey, 'got signed message without keyring' secret = self.message.keyring.get(absolute_name) if secret is None: raise UnknownTSIGKey, "key '%s' unknown" % name self.message.tsig_ctx = \ dnspython.tsig.validate(self.wire, absolute_name, secret, int(time.time()), self.message.request_mac, rr_start, self.current, rdlen, self.message.tsig_ctx, self.message.multi, self.message.first) self.message.had_tsig = True else: if ttl < 0: ttl = 0 if self.updating and \ (rdclass == dnspython.rdataclass.ANY or rdclass == dnspython.rdataclass.NONE): deleting = rdclass rdclass = self.zone_rdclass else: deleting = None if deleting == dnspython.rdataclass.ANY or \ (deleting == dnspython.rdataclass.NONE and \ section == self.message.answer): covers = dnspython.rdatatype.NONE rd = None else: rd = dnspython.rdata.from_wire(rdclass, rdtype, self.wire, self.current, rdlen, self.message.origin) covers = rd.covers() if self.message.xfr and rdtype == dnspython.rdatatype.SOA: force_unique = True rrset = self.message.find_rrset(section, name, rdclass, rdtype, covers, deleting, True, force_unique) if not rd is None: rrset.add(rd, ttl) self.current = self.current + rdlen