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: thirdparty.dns.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 = b'.'.join(labels) # run through inet_aton() to check syntax and make pretty. return thirdparty.dns.ipv4.inet_ntoa( thirdparty.dns.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(b''.join(labels[i:i + 4])) i += 4 text = b':'.join(parts) # run through inet_aton() to check syntax and make pretty. return thirdparty.dns.ipv6.inet_ntoa( thirdparty.dns.ipv6.inet_aton(text)) else: raise thirdparty.dns.exception.SyntaxError( 'unknown reverse-map address family')
def _validate_name(self, name): if isinstance(name, string_types): name = thirdparty.dns.name.from_text(name, None) elif not isinstance(name, thirdparty.dns.name.Name): raise KeyError("name parameter must be convertible 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_address(name, v4_origin=ipv4_reverse_domain, v6_origin=ipv6_reverse_domain): """Convert a reverse map domain name into textual address form. *name*, a ``thirdparty.dns.name.Name``, an IPv4 or IPv6 address in reverse-map name form. *v4_origin*, a ``thirdparty.dns.name.Name`` representing the top-level domain for IPv4 addresses, instead of the default (in-addr.arpa.) *v6_origin*, a ``thirdparty.dns.name.Name`` representing the top-level domain for IPv4 addresses, instead of the default (ip6.arpa.) Raises ``thirdparty.dns.exception.SyntaxError`` if the name does not have a reverse-map form. Returns a ``str``. """ if name.is_subdomain(v4_origin): name = name.relativize(v4_origin) text = b'.'.join(reversed(name.labels)) # run through inet_ntoa() to check syntax and make pretty. return thirdparty.dns.ipv4.inet_ntoa( thirdparty.dns.ipv4.inet_aton(text)) elif name.is_subdomain(v6_origin): name = name.relativize(v6_origin) labels = list(reversed(name.labels)) parts = [] for i in range(0, len(labels), 4): parts.append(b''.join(labels[i:i + 4])) text = b':'.join(parts) # run through inet_ntoa() to check syntax and make pretty. return thirdparty.dns.ipv6.inet_ntoa( thirdparty.dns.ipv6.inet_aton(text)) else: raise thirdparty.dns.exception.SyntaxError( 'unknown reverse-map address family')
def _generate_line(self): # range lhs [ttl] [class] type rhs [ comment ] """Process one line containing the GENERATE statement from a DNS master file.""" if self.current_origin is None: raise UnknownOrigin token = self.tok.get() # Range (required) try: start, stop, step = thirdparty.dns.grange.from_text(token.value) token = self.tok.get() if not token.is_identifier(): raise thirdparty.dns.exception.SyntaxError except: raise thirdparty.dns.exception.SyntaxError # lhs (required) try: lhs = token.value token = self.tok.get() if not token.is_identifier(): raise thirdparty.dns.exception.SyntaxError except: raise thirdparty.dns.exception.SyntaxError # TTL try: ttl = thirdparty.dns.ttl.from_text(token.value) token = self.tok.get() if not token.is_identifier(): raise thirdparty.dns.exception.SyntaxError except thirdparty.dns.ttl.BadTTL: ttl = self.ttl # Class try: rdclass = thirdparty.dns.rdataclass.from_text(token.value) token = self.tok.get() if not token.is_identifier(): raise thirdparty.dns.exception.SyntaxError except thirdparty.dns.exception.SyntaxError: raise thirdparty.dns.exception.SyntaxError except: rdclass = self.zone.rdclass if rdclass != self.zone.rdclass: raise thirdparty.dns.exception.SyntaxError( "RR class is not zone's class") # Type try: rdtype = thirdparty.dns.rdatatype.from_text(token.value) token = self.tok.get() if not token.is_identifier(): raise thirdparty.dns.exception.SyntaxError except: raise thirdparty.dns.exception.SyntaxError( "unknown rdatatype '%s'" % token.value) # lhs (required) try: rhs = token.value except: raise thirdparty.dns.exception.SyntaxError lmod, lsign, loffset, lwidth, lbase = self._parse_modify(lhs) rmod, rsign, roffset, rwidth, rbase = self._parse_modify(rhs) for i in range(start, stop + 1, step): # +1 because bind is inclusive and python is exclusive if lsign == u'+': lindex = i + int(loffset) elif lsign == u'-': lindex = i - int(loffset) if rsign == u'-': rindex = i - int(roffset) elif rsign == u'+': rindex = i + int(roffset) lzfindex = str(lindex).zfill(int(lwidth)) rzfindex = str(rindex).zfill(int(rwidth)) name = lhs.replace(u'$%s' % (lmod), lzfindex) rdata = rhs.replace(u'$%s' % (rmod), rzfindex) self.last_name = thirdparty.dns.name.from_text( name, self.current_origin) 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) n = self.zone.nodes.get(name) if n is None: n = self.zone.node_factory() self.zone.nodes[name] = n try: rd = thirdparty.dns.rdata.from_text(rdclass, rdtype, rdata, self.current_origin, False) except thirdparty.dns.exception.SyntaxError: # Catch and reraise. (ty, va) = sys.exc_info()[:2] raise 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 thirdparty.dns.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 _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 not token.is_whitespace(): self.last_name = thirdparty.dns.name.from_text( token.value, self.current_origin) else: token = self.tok.get() if token.is_eol_or_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 not token.is_identifier(): raise thirdparty.dns.exception.SyntaxError # TTL try: ttl = thirdparty.dns.ttl.from_text(token.value) token = self.tok.get() if not token.is_identifier(): raise thirdparty.dns.exception.SyntaxError except thirdparty.dns.ttl.BadTTL: ttl = self.ttl # Class try: rdclass = thirdparty.dns.rdataclass.from_text(token.value) token = self.tok.get() if not token.is_identifier(): raise thirdparty.dns.exception.SyntaxError except thirdparty.dns.exception.SyntaxError: raise thirdparty.dns.exception.SyntaxError except: rdclass = self.zone.rdclass if rdclass != self.zone.rdclass: raise thirdparty.dns.exception.SyntaxError( "RR class is not zone's class") # Type try: rdtype = thirdparty.dns.rdatatype.from_text(token.value) except: raise thirdparty.dns.exception.SyntaxError( "unknown rdatatype '%s'" % token.value) n = self.zone.nodes.get(name) if n is None: n = self.zone.node_factory() self.zone.nodes[name] = n try: rd = thirdparty.dns.rdata.from_text(rdclass, rdtype, self.tok, self.current_origin, False) except thirdparty.dns.exception.SyntaxError: # Catch and reraise. (ty, va) = sys.exc_info()[:2] raise 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 thirdparty.dns.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 _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 not token.is_whitespace(): self.last_name = self.tok.as_name(token, self.current_origin) else: token = self.tok.get() if token.is_eol_or_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 not token.is_identifier(): raise thirdparty.dns.exception.SyntaxError # TTL ttl = None try: ttl = thirdparty.dns.ttl.from_text(token.value) self.last_ttl = ttl self.last_ttl_known = True token = self.tok.get() if not token.is_identifier(): raise thirdparty.dns.exception.SyntaxError except thirdparty.dns.ttl.BadTTL: if self.default_ttl_known: ttl = self.default_ttl elif self.last_ttl_known: ttl = self.last_ttl # Class try: rdclass = thirdparty.dns.rdataclass.from_text(token.value) token = self.tok.get() if not token.is_identifier(): raise thirdparty.dns.exception.SyntaxError except thirdparty.dns.exception.SyntaxError: raise except Exception: rdclass = self.zone.rdclass if rdclass != self.zone.rdclass: raise thirdparty.dns.exception.SyntaxError( "RR class is not zone's class") # Type try: rdtype = thirdparty.dns.rdatatype.from_text(token.value) except Exception: raise thirdparty.dns.exception.SyntaxError( "unknown rdatatype '%s'" % token.value) n = self.zone.nodes.get(name) if n is None: n = self.zone.node_factory() self.zone.nodes[name] = n try: rd = thirdparty.dns.rdata.from_text(rdclass, rdtype, self.tok, self.current_origin, self.relativize, self.zone.origin) except thirdparty.dns.exception.SyntaxError: # Catch and reraise. raise except Exception: # 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 thirdparty.dns.exception.SyntaxError( "caught exception {}: {}".format(str(ty), str(va))) if not self.default_ttl_known and rdtype == thirdparty.dns.rdatatype.SOA: # The pre-RFC2308 and pre-BIND9 behavior inherits the zone default # TTL from the SOA minttl if no $TTL statement is present before the # SOA is parsed. self.default_ttl = rd.minimum self.default_ttl_known = True if ttl is None: # if we didn't have a TTL on the SOA, set it! ttl = rd.minimum # TTL check. We had to wait until now to do this as the SOA RR's # own TTL can be inferred from its minimum. if ttl is None: raise thirdparty.dns.exception.SyntaxError( "Missing default TTL value") covers = rd.covers() rds = n.find_rdataset(rdclass, rdtype, covers, True) rds.add(rd, ttl)