Пример #1
0
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')
Пример #2
0
 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
Пример #3
0
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')
Пример #4
0
    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)
Пример #5
0
    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)
Пример #6
0
    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)