Ejemplo n.º 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: 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'
Ejemplo n.º 2
0
 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
Ejemplo n.º 3
0
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
Ejemplo n.º 4
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 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)
Ejemplo n.º 5
0
    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